Morx

Thank you so much for reviewing the morx code!
I will make the recommended changes and commit it when it’s done.
From: Wesley Moore
Sent: Wednesday, January 18, 2023 12:36 PM
To: yeslogic/allsorts
Cc: cliu2018 ; Author
Subject: Re: [yeslogic/allsorts] Morx (PR #85)
@wezm commented on this pull request.
Great to see this coming in. Hopefully it opens up shaping of fonts like Apple Color Emoji, Hoefler Text, Zapfino, etc.
Some general comments:
We have in the past been a bit stingy with derives on structs (see #69) it would be good to add Copy/Clone, and PartialEq/Eq to new public structs.
Speaking of public structs, we should consider making the fields of structs that map directly to table data public too.
I think we need some more test coverage of this code to ensure that it's working as expected and remains working in the future. It might be worth trying to see if there are any freely licensed fonts out there that have a morx table that we might be able to add to the repo (in tests/fonts) and write some tests to exercise the code using that font. Probably worth checking if Harfbuzz has already identified such a font.
The unicode text rendering tests also have 40 odd morx tests and we've already integrated Allosorts into that project. It would be worth running that test suite against this branch to see how it fares.

In src/morx.rs:

@@ -0,0 +1,1825 @@

+use std::convert::TryFrom;

+use crate::binary::read::{ReadBinary, ReadBinaryDep, ReadCtxt, ReadFrom, ReadScope};
+use crate::binary::U16Be;
+use crate::binary::U32Be;
+use crate::binary::U8;
+use crate::error::ParseError;
+use crate::gsub::{FeatureMask, Features, GlyphOrigin, RawGlyph};
+use crate::tinyvec::tiny_vec;

+//----------------------------------------------------------------------------------
+#[derive(Debug)]
+pub struct MorxHeader {

version: u16,

unused: u16,

Since this is unused I don't think we need to store it.

In src/morx.rs:

+#[derive(Debug)]

+pub struct Chain {

chain_header: ChainHeader,

feature_array: Vec,

subtables: Vec,

+}

+impl<'a> ReadBinary<'a> for Chain {

type HostType = Self;

fn read(ctxt: &mut ReadCtxt<'a>) -> Result<Self, ParseError> {

   let chain_header = ctxt.read::<ChainHeader>()?;

   let features =

       ctxt.read_array::<Feature>(usize::try_from(chain_header.n_feature_entries)?)?;

   let feature_vec = features.to_vec();

No need to allocate a vector here, I think the features can be stored as ReadArray on Chain.

In src/morx.rs:

+//----------------------------------------------------------------------------------
+#[derive(Debug)]
+pub struct Subtable {

subtable_header: SubtableHeader,

subtable_body: SubtableType,

+}

+impl<'a> ReadBinary<'a> for Subtable {

type HostType = Self;

fn read(ctxt: &mut ReadCtxt<'a>) -> Result<Self, ParseError> {

   let subtable_header = ctxt.read::<SubtableHeader>()?;

   let subtable_body: SubtableType;

   let subtable_body_length: usize = usize::try_from(subtable_header.length - 12)?;

No need to annotate the type here and it might be worth including a comment to explain that 12 is subtracted to skip the size of the header fields.

In src/morx.rs:

           let ligature_subtable = subtable_scope.read::<LigatureSubtable>()?;

           subtable_body = SubtableType::Ligature { ligature_subtable };

       }

       4 => {

           //Get a shorter scope from the context to read the subtable

           let subtable_scope = ctxt.read_scope(subtable_body_length)?;

           let noncontextual_subtable = subtable_scope.read::<NonContextualSubtable>()?;

           subtable_body = SubtableType::NonContextual {

               noncontextual_subtable,

           };

       }

       _ => {

           //read the subtable to a Vec<u8> if it is another type other than ligature or noncontextual

           //let subtable_array = ctxt.read_array::<U8>(subtable_body_length)?;

           let subtable_array = ctxt.read_array::<U8>(subtable_body_length)?;

           let subtable_vec = subtable_array.to_vec();

I don't think a vector needs to be allocated here. A slice could be used instead:
let subtable_scope = ctxt.read_scope(subtable_body_length)?;
let data = subtable_scope.data();If this was done all branches would create the subtable_scope so that could be moved out of the match as well.

In src/morx.rs:

+/***************************************************************************************************

+//--------------------------------------------------------------------------------------------------
+#[derive(Debug)]
+pub enum SubtableType {

Rearragement {

   rearrangement_subtable: RearrangementSubtable,

},

Contextual {

   contextual_subtable: ContextualSubstitutionSubtable,

},

Ligature {

   ligature_subtable: LigatureSubtable,

},

NonContextual {

   noncontextual_subtable: NonContextualSubstitutionSubtable,

},

Insertion {

   insertion_subtable: InsertionSubtable,

},

+}

+****************************************************************************************************/
Suggest deleting commented out code.

In src/morx.rs:

+//------------------------------------ Subtables ------------------------------------------------

+//Indic Rearrangement Subtable
+#[derive(Debug)]
+pub struct RearrangementSubtable {

stx_header: STXheader,

//subtable body here,

//the rearrangement subtable is just a state table

+}

+//Contextual Glyph Substitution Subtable
+#[derive(Debug)]
+pub struct ContextualSubtable {

stx_header: STXheader,

substitution_subtables_offset: u32,

I don't think needs to be stored as it's only needed when parsing.

In src/morx.rs:

       2 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       4 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       6 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       8 => {

           bin_srch_header = None;

       }

       10 => {

           bin_srch_header = None;

       }

       _ => return Err(ParseError::BadVersion),

I think this would probably be BadValue.

In src/morx.rs:

   let bin_srch_header: Option<BinSrchHeader>;

   match format {

       0 => {

           bin_srch_header = None;

       }

       2 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       4 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       6 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       8 => {

           bin_srch_header = None;

       }

       10 => {

           bin_srch_header = None;

       }

       _ => return Err(ParseError::BadVersion),

   }

This could be simplified:
⬇ Suggested change

   let bin_srch_header: Option<BinSrchHeader>;

   match format {

       0 => {

           bin_srch_header = None;

       }

       2 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       4 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       6 => {

           bin_srch_header = Some(ctxt.read::<BinSrchHeader>()?);

       }

       8 => {

           bin_srch_header = None;

       }

       10 => {

           bin_srch_header = None;

       }

       _ => return Err(ParseError::BadVersion),

   }

   let bin_srch_header = match format {

       2 | 4 | 6 => Some(ctxt.read::<BinSrchHeader>()?,

       0 | 8 | 10 => None,

       _ => return Err(ParseError::BadVersion),

   };

In src/morx.rs:

   loop {

       let ligature = match ctxt.read_u16be() {

           Ok(val) => val,

           Err(_err) => break,

       };

       ligature_list.push(ligature);

   }

This pattern of a loop that reads as many values as it can is repeated in a number of places (I'll not leave comments on the other occurrences). I think that it might be able to be made a bit more robust (by not swallowing all errors) and avoid the need to allocate a vector using code like this.
let len_remaining = ctxt.scope().data().len();
ctxt.check(len_remaining % size::U16 == 0)?;
let ligature_list = ctxt.read_array::(len_remaining / size::U16)?;Since it's used in at least 3 or 4 places it could be extracted to a function too, perhaps even added to ReadCtxt.

In src/morx.rs:

   let mut state_array: Vec<Vec<u16>> = Vec::new();

   'outer: loop {

       let mut state_row: Vec<u16> = Vec::new();

       for _i in 0..n_classes.0 {

           let value = match ctxt.read_u16be() {

               Ok(val) => val,

               Err(_err) => break 'outer,

           };

           state_row.push(value);

       }

       state_array.push(state_row);

   }

ReadArray might be able to simplify this:
⬇ Suggested change

   let mut state_array: Vec<Vec<u16>> = Vec::new();

   'outer: loop {

       let mut state_row: Vec<u16> = Vec::new();

       for _i in 0..n_classes.0 {

           let value = match ctxt.read_u16be() {

               Ok(val) => val,

               Err(_err) => break 'outer,

           };

           state_row.push(value);

       }

       state_array.push(state_row);

   }

   let mut state_array: Vec<ReadArray<U16Be>> = Vec::new();

   loop {

       let mut state_row = match ctxt.read_array(n_classes.0) {

           Ok(array) => array,

           Err(ParseError::Eof) => break,

           Err(err) => return Err(err),

       }

       state_array.push(state_row);

   }

In src/morx.rs:

Format2 {

   lookup_segments: Vec<LookupSegmentFmt2>, //Segment Single format 2

},

Format4 {

   lookup_segments: Vec<LookupValuesFmt4>, //Segment Array format 4

},

Format6 {

   lookup_entries: Vec<LookupSingleFmt6>, //Single Table format 6

},

Format8 {

   first_glyph: u16,

   glyph_count: u16,

   lookup_values: Vec<u16>, //Trimmed Array format 8

},

Format10 {

   unit_size: u16,

I don't think this field needs to be stored since its information is captured by lookup_values.

In src/morx.rs:

       }

       2 => {

           //Get a shorter scope from the context to read the subtable

           let subtable_scope = ctxt.read_scope(subtable_body_length)?;

           let ligature_subtable = subtable_scope.read::<LigatureSubtable>()?;

           subtable_body = SubtableType::Ligature { ligature_subtable };

       }

       4 => {

           //Get a shorter scope from the context to read the subtable

           let subtable_scope = ctxt.read_scope(subtable_body_length)?;

           let noncontextual_subtable = subtable_scope.read::<NonContextualSubtable>()?;

           subtable_body = SubtableType::NonContextual {

               noncontextual_subtable,

           };

       }

       _ => {

It looks like the spec only defines subtable types 0–5. Perhaps it would be a good idea to create SubtableType::Other for 0 and 5, and return an error for other values.

In src/morx.rs:

OneByte { lookup_values: Vec },

TwoByte { lookup_values: Vec },

FourByte { lookup_values: Vec },

EightByte { lookup_values: Vec },

I think these could be ReadArray as I think the length is known in each case.

In src/morx.rs:

               let mut lookup_segments = Vec::new();

               for _i in 0..b_sch_header.n_units {

                   let lookup_segment = match ctxt.read::<LookupSegmentFmt2>() {

                       Ok(val) => val,

                       Err(_err) => break,

                   };

                   lookup_segments.push(lookup_segment);

               }

               let lookup_table = LookupTable::Format2 { lookup_segments };

I think this could use ReadArray

In src/morx.rs:

                   let mut lookup_values: Vec<u16> = Vec::new();

                   for _i in 0..(segment.last_glyph - segment.first_glyph + 1) {

                       let lookup_value = match read_ctxt.read_u16be() {

                           Ok(val) => val,

                           Err(_err) => break,

                       };

                       lookup_values.push(lookup_value);

                   }

I think this can use ReadArray.

In src/morx.rs:

               let mut lookup_entries = Vec::new();

               for _i in 0..b_sch_header.n_units {

                   let lookup_entry = match ctxt.read::<LookupSingleFmt6>() {

                       Ok(val) => val,

                       Err(_err) => break,

                   };

                   lookup_entries.push(lookup_entry);

               }

I think this could use ReadArray

In src/morx.rs:

               let mut lookup_values = Vec::new();

               for _i in 0..glyph_count {

                   let lookup_value = ctxt.read_u16be()?;

                   lookup_values.push(lookup_value);

               }

I think ReadArray could be used here.

In src/morx.rs:

               if (glyph as usize) < lookup_values.len() {

                   return Some(lookup_values[glyph as usize]);

               } else {

                   return None; //out of bounds

               }

This pattern (which it repeated a few times) could be simplified using get:
⬇ Suggested change

               if (glyph as usize) < lookup_values.len() {

                   return Some(lookup_values[glyph as usize]);

               } else {

                   return None; //out of bounds

               }

               return lookup_values.get(usize::from(glyph))

In src/morx.rs:

               for lookup_segment in lookup_segments {

                   if (glyph >= lookup_segment.first_glyph)

                       && (glyph <= lookup_segment.last_glyph)

                   {

                       if ((glyph - lookup_segment.first_glyph) as usize)

                           < lookup_segment.lookup_values.len()

                       {

                           return Some(

                               lookup_segment.lookup_values

                                   [usize::from(glyph - lookup_segment.first_glyph)],

                           );

                       }

                   }

               }

               return None; //out of bounds

This code is quite complex. Perhaps something like this could make it simpler. I think a similar refactoring could be applied to some of the other lookups as well.
return lookup_segments.iter().find_map(|lookup_segment| {
lookup_segment.contains(glyph)

    .then(|| lookup_segment.get(usize::from(glyph - lookup_segment.first_glyph)))

})
// where lookup_segment.contains would be:
impl LookupSegmentFmt4 {
fn contains(glyph: u16) -> bool {

    (self.first_glyph..=self.last_glyph).contains(glyph)

}

}
In src/morx.rs:

                       return Some(lookup_segment.lookup_value);

                   }

               }

               return None; //out of bounds

           }

           _ => return None, //Only Format2 is valid here.

       }

   }

   4 => {

       match &lookup_table.lookup_table {

           LookupTable::Format4 { lookup_segments } => {

               for lookup_segment in lookup_segments {

                   if (glyph >= lookup_segment.first_glyph)

                       && (glyph <= lookup_segment.last_glyph)

                   {

                       if ((glyph - lookup_segment.first_glyph) as usize)

In cases where we add or subtract values supplied by the font (such as lookup_segment.first_glyph) we probably should use checked arithmetic to avoid under/overflow. Example from elsewhere in the code:
https://github.com/yeslogic/allsorts/blob/1d05ffa243d857770b45d2b0244bb2d747520bd4/src/woff2.rs#L537-L539

In src/morx.rs:

   const SET_MARK: u16 = 0x8000;

   const DONT_ADVANCE: u16 = 0x4000;

   let mut old_glyph: u16;

   let mut new_glyph: u16;

   //loop through glyphs:

   for i in 0..self.glyphs.len() {

       let current_glyph: u16 = self.glyphs[i].glyph_index;

       old_glyph = self.glyphs[i].glyph_index;

       new_glyph = self.glyphs[i].glyph_index;

       let mut class = glyph_class(current_glyph, &contextual_subtable.class_table);

       'glyph: loop {

           let index_to_entry_table = contextual_subtable.state_array.state_array

               [usize::from(self.next_state)][usize::from(class)];

In places where we index into arrays with values provided by the font I think get should be used in order to avoid panics if the value happens to be out of bounds.

In src/morx.rs:

   'glyphs: loop {

       let glyph: RawGlyph<()>;

       if i < self.glyphs.len() {

           glyph = self.glyphs[i].clone(); //length of glyphs might have changed due to substitution. So need to check.

       }

       //assume the length of the glyphs array is shorter or unchanged.

       else {

           break 'glyphs;

       }

This could probably be a while loop:
while let Some(glyph) = self.glyphs.get(i) {
let glyph = glyph.clone();

⋮

}
In src/morx.rs:

for chain in morx_table.morx_chains.iter() {

   let subfeatureflags: u32 = subfeatureflags(chain, features)?;

   for subtable in chain.subtables.iter() {

       if subfeatureflags & subtable.subtable_header.sub_feature_flags != 0 {

           match subtable.subtable_header.coverage & 0xFF {

               1 => {

                   let mut contextual_subst: ContextualSubstitution<'_> =

                       ContextualSubstitution::new(glyphs);

                   if let SubtableType::Contextual {

                       contextual_subtable,

                   } = &subtable.subtable_body

                   {

                       contextual_subst.next_state = 0;

                       contextual_subst.process_glyphs(contextual_subtable)?;

                   }

Should there be else branches on these to return an error if the sub-table type is not the expected type?

In src/morx.rs:

                       liga_subst.next_state = 0;

                       liga_subst.component_stack.clear();

I think these lines duplicate what LigatureSubstitution::new does.

In src/morx.rs:

const LOWERCASE_TYPE: u16 = 37;

//Feature selectors:

const LOWERCASE_SMALL_CAPS: u16 = 1;

//---------------------------------------

//Feature type:

const UPPERCASE_TYPE: u16 = 38;

//Feature selectors:

const UPPERCASE_SMALL_CAPS: u16 = 1;

//---------------------------------------

let mut subfeature_flags = chain.chain_header.default_flags;

for entry in chain.feature_array.iter() {

   match features {

       Features::Custom(_features_list) => {

           return Ok(subfeature_flags);

Should this return the supplied custom features instead of the default features?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: @.***>

Thanks for reviewing the morx code and making the suggestions.
I will make the changes and re-commit it when it’s ready.
From: Wesley Moore
Sent: Thursday, November 09, 2023 4:52 PM
To: yeslogic/allsorts
Cc: cliu2018 ; Author
Subject: Re: [yeslogic/allsorts] Morx (PR #85)
@wezm commented on this pull request.
Overall this is shaping up well. I've left a lot of comments—sorry. Many relate to style, following Rust idioms, or consistency with the rest of the code base. All comments prefixed with "Minor" or "Optional" are changes that I don't think should block merging this work, the others I think should be addressed before merging.
There are a couple general comments that apply in several places:
a.. I think indexing, particularly when processing glyphs needs to reviewed to ensure it will not panic with user controlled data.
b.. I think there are various places that probably should be using checked arithmetic. I noted some of them but not all.
c.. There are some areas that are long and deeply nested which makes it a little difficult to read. I think extracting functions/adding methods to types could help but it's not essential.
d.. It would be good to add at least one small (file size wise), permissively licensed font in the code base (E.g. tests/fonts/morx) and add some basic tests that use it to help ensure the code works on a real font (and stays working).

In src/font.rs:

+use crate::morx;
+use crate::morx::MorxTable;
Minor:

⬇ Suggested change
-use crate::morx;
-use crate::morx::MorxTable;
+use crate::morx::{self, MorxTable};

In src/font.rs:

       //let res = morx::apply(&morx_cache, &mut glyphs, features);

       //check_set_err(res, &mut err);

Commented out code should be removed.

In src/font.rs:

@@ -726,6 +750,22 @@ impl<T: FontTableProvider> Font {
})
}

//pub fn morx_table(&mut self) -> Result<Option<Rc>, ParseError> {
Commented out code should be removed.

In src/font.rs:

     let opt_gdef_table = opt_gdef_table.as_ref().map(Rc::as_ref);

     let (dotted_circle_index, _) =
         self.lookup_glyph_index(DOTTED_CIRCLE, MatchingPresentation::NotRequired, None);

   //apply morx if table is present

Minor:
⬇ Suggested change

   //apply morx if table is present

   // Apply morx if table is present

In src/morx.rs:

+pub struct MorxHeader {

_version: u16,
n_chains: u32,
+}

+impl ReadFrom for MorxHeader {

type ReadType = (U16Be, U16Be, U32Be);

fn from((_version, _unused, n_chains): (u16, u16, u32)) -> Self {

   MorxHeader { _version, n_chains }

}
+}

+#[derive(Debug)]
+pub struct MorxTable<'a> {

_morx_header: MorxHeader,
Since this field is unused I think it can be dropped from the struct.

In src/morx.rs:

       //get a scope of length "chain_length" to read the chain and

       //advance to the correct position in the buffer for reading

       //the next chain, regardless whether the "Subtable Glyph Coverage table"

       //is present at the end of the chain.

This is a general style comment that applies to the whole PR. The style for comments in the rest of the code is // followed by a space. It would be good to have all the comments in this PR follow that style too.

In src/morx.rs:

       //advance to the correct position in the buffer for reading

       //the next chain, regardless whether the "Subtable Glyph Coverage table"

       //is present at the end of the chain.

       let chain_scope = ctxt.read_scope(chain_length)?;

       let chain = chain_scope.read::<Chain<'a>>()?;

       chain_vec.push(chain);

   }

   Ok(MorxTable {

       _morx_header: morx_header,

       morx_chains: chain_vec,

   })

}
+}

+//----------------------------------------------------------------------------------
Minor: We haven't used separators like this in the rest of the code. For consistency I suggest removing them.

In src/morx.rs:

+#[derive(Debug)]
+pub struct ChainHeader {

default_flags: u32,
chain_length: u32,
n_feature_entries: u32,
n_subtables: u32,
+}
Minor: As a general rule all the types are placed at the top of the file with the impls following.

In src/morx.rs:

fn from((_version, _unused, n_chains): (u16, u16, u32)) -> Self {

   MorxHeader { _version, n_chains }

}
+}

+#[derive(Debug)]
+pub struct MorxTable<'a> {

_morx_header: MorxHeader,
morx_chains: Vec<Chain<'a>>,
+}

+impl<'b> ReadBinary for MorxTable<'b> {

type HostType<'a> = MorxTable<'a>;

fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {

   let morx_header = ctxt.read::<MorxHeader>()?;

It looks like this code only supports version 3. Suggest checking this. E.g.
ctxt.check_version(version == 3)
In src/morx.rs:

   MorxHeader { _version, n_chains }

}
+}

+#[derive(Debug)]
+pub struct MorxTable<'a> {

_morx_header: MorxHeader,
morx_chains: Vec<Chain<'a>>,
+}

+impl<'b> ReadBinary for MorxTable<'b> {

type HostType<'a> = MorxTable<'a>;

fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {

   let morx_header = ctxt.read::<MorxHeader>()?;

   let mut chain_vec = Vec::new();

Suggest pre-allocating this Vec:
⬇ Suggested change

   let mut chain_vec = Vec::new();

   let mut chain_vec = Vec::with_capacity(morx_header.n_chains);

In src/morx.rs:

_morx_header: MorxHeader,

morx_chains: Vec<Chain<'a>>,
+}

+impl<'b> ReadBinary for MorxTable<'b> {

type HostType<'a> = MorxTable<'a>;

fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {

   let morx_header = ctxt.read::<MorxHeader>()?;

   let mut chain_vec = Vec::new();

   for _i in 0..morx_header.n_chains {

       //read the chain header to get the chain length

       let scope_hdr = ctxt.scope();

       let chain_header = scope_hdr.read::<ChainHeader>()?;

       let chain_length: usize = usize::try_from(chain_header.chain_length)?;

⬇ Suggested change

       let chain_length: usize = usize::try_from(chain_header.chain_length)?;

       let chain_length = usize::try_from(chain_header.chain_length)?;

In src/morx.rs:

+pub struct Chain<'a> {

chain_header: ChainHeader,
feature_array: ReadArray<'a, Feature>,
subtables: Vec<Subtable<'a>>,
+}

+impl<'b> ReadBinary for Chain<'b> {

type HostType<'a> = Chain<'a>;

fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {

   let chain_header = ctxt.read::<ChainHeader>()?;

   let features =

       ctxt.read_array::<Feature>(usize::try_from(chain_header.n_feature_entries)?)?;

   let mut subtable_vec = Vec::new();

Suggest pre-allocating this Vec:
⬇ Suggested change

   let mut subtable_vec = Vec::new();

   let mut subtable_vec = Vec::with_capacity(chain_header.n_subtables);

In src/morx.rs:

+pub enum SubtableType<'a> {

Contextual {

   contextual_subtable: ContextualSubtable<'a>,

},
Ligature {

   ligature_subtable: LigatureSubtable<'a>,

},
NonContextual {

   noncontextual_subtable: NonContextualSubtable<'a>,

},
Other {

   other_subtable: &'a [u8],

},
+}
Optional: Perhaps this would be a little nicer using tuple variants?

⬇ Suggested change
-pub enum SubtableType<'a> {

Contextual {

   contextual_subtable: ContextualSubtable<'a>,

},
Ligature {

   ligature_subtable: LigatureSubtable<'a>,

},
NonContextual {

   noncontextual_subtable: NonContextualSubtable<'a>,

},
Other {

   other_subtable: &'a [u8],

},
-}
+pub enum SubtableType<'a> {

Contextual(ContextualSubtable<'a>),
Ligature(LigatureSubtable<'a>),
NonContextual(NonContextualSubtable<'a>,
Other(&'a [u8])
+}

In src/morx.rs:

},

Ligature {

   ligature_subtable: LigatureSubtable<'a>,

},
NonContextual {

   noncontextual_subtable: NonContextualSubtable<'a>,

},
Other {

   other_subtable: &'a [u8],

},
+}

+//----------------------------- Extended State Table Header ------------------------------------------
+
+#[derive(Debug)]
+pub struct STXheader {
⬇ Suggested change
-pub struct STXheader {
+pub struct STXHeader {

In src/morx.rs:

) -> Self {

   STXheader {

       n_classes,

       class_table_offset,

       state_array_offset,

       entry_table_offset,

   }

}
+}

+//------------------------------------ Subtables ------------------------------------------------
+
+//Contextual Glyph Substitution Subtable
+#[derive(Debug)]
+pub struct ContextualSubtable<'a> {

_stx_header: STXheader,
If this isn't used after parsing suggest dropping it form the struct. (this comment applies to the other structs too)

In src/morx.rs:

   let mut offsets_to_subst_tables: Vec<u32> = Vec::new();

   for _i in 0..offset_array_len {

       let value = match subst_tables_ctxt.read_u32be() {

           Ok(val) => val,

           Err(_err) => break,

       };

       offsets_to_subst_tables.push(value);

   }

   let mut substitution_subtables: Vec<ClassLookupTable<'a>> = Vec::new();

   for &offset in offsets_to_subst_tables.iter() {

       let subst_subtable = match subtable

           .offset(usize::try_from(substitution_subtables_offset)?)

           .offset(usize::try_from(offset)?)

           .read::<ClassLookupTable<'a>>()

       {

           Ok(val) => val,

           Err(_err) => break,

       };

       substitution_subtables.push(subst_subtable);

   }

I don't really like that errors are being swallowed in this code (and other places down further). Perhaps the error matching could be more specific:
match x {
Ok(val) => val,
Err(ParseError::BadEof) => break,
Err(err) => return Err(err)
}Additionally I think we might be able to avoid allocating a vector for the offsets:
    let mut substitution_subtables: Vec<ClassLookupTable<'a>> = Vec::new();
    loop {
        let offset = match subst_tables_ctxt.read_u32be() {
            Ok(offset) => offset,
            Err(ParseError::BadEof) => break,
            Err(err) => return Err(err),
        };
        let subst_subtable = match subtable
            .offset(usize::try_from(substitution_subtables_offset)?)
            .offset(usize::try_from(offset)?)
            .read::<ClassLookupTable<'a>>()?;
        substitution_subtables.push(subst_subtable);
    }

In src/morx.rs:

           Some(ref b_sch_header) => {

               if b_sch_header.unit_size != 6 {

                   return Err(ParseError::BadValue);

               }

               let lookup_segments =

                   ctxt.read_array::<LookupSegmentFmt2>(usize::from(b_sch_header.n_units))?;

               let lookup_table = LookupTable::Format2 { lookup_segments };

               return Ok(ClassLookupTable {

                   lookup_header,

                   lookup_table,

               });

           }

           None => return Err(ParseError::BadValue),

Optional: This pattern used below as well can be simplified:
⬇ Suggested change

           Some(ref b_sch_header) => {

               if b_sch_header.unit_size != 6 {

                   return Err(ParseError::BadValue);

               }

               let lookup_segments =

                   ctxt.read_array::<LookupSegmentFmt2>(usize::from(b_sch_header.n_units))?;

               let lookup_table = LookupTable::Format2 { lookup_segments };

               return Ok(ClassLookupTable {

                   lookup_header,

                   lookup_table,

               });

           }

           None => return Err(ParseError::BadValue),

           Some(ref b_sch_header) if b_sch_header.unit_size == 6 => {

               let lookup_segments =

                   ctxt.read_array::<LookupSegmentFmt2>(usize::from(b_sch_header.n_units))?;

               let lookup_table = LookupTable::Format2 { lookup_segments };

               return Ok(ClassLookupTable {

                   lookup_header,

                   lookup_table,

               });

           }

           _ => return Err(ParseError::BadValue),

In src/morx.rs:

                   let segment = match ctxt.read::<LookupSegmentFmt4>() {

                       Ok(val) => val,

                       Err(_err) => break,

                   };

                   let offset_to_lookup_values = segment.offset;

                   if (segment.first_glyph == 0xFFFF) && (segment.last_glyph == 0xFFFF) {

                       break;

                   }

                   let mut read_ctxt = class_table

                       .offset(usize::from(offset_to_lookup_values))

                       .ctxt();

                   let lookup_values = read_ctxt.read_array::<U16Be>(usize::from(

                       segment.last_glyph - segment.first_glyph + 1,

Probably should use checked arithmetic here since these are values originating from the font data.

In src/morx.rs:

       2 => match lookup_header.bin_srch_header {

           Some(ref b_sch_header) => {

Optional: I think a level of nesting can be avoided, which might make the code a bit easier to read by matching on the format and the expected binary search header in one pattern. E.g.
match (lookup_header.format, lookup_header.bin_srch_header.as_ref()) {
(0, None) => { … }
(1, Some(b_sch_header)) => { … }
⋮
}
In src/morx.rs:

               };

               return Ok(ClassLookupTable {

                   lookup_header,

                   lookup_table,

               });

           }

           _ => return Err(ParseError::BadValue),

       },

       10 => match lookup_header.bin_srch_header {

           None => {

               let unit_size = ctxt.read_u16be()?;

               let first_glyph = ctxt.read_u16be()?;

               let glyph_count = ctxt.read_u16be()?;

               match unit_size {

Optional: Might be worth extracting this match out to its own function of ReadBinary impl since the outer match is already quite long.

In src/morx.rs:

   loop {

       let entry = match ctxt.read::<ContextualEntry>() {

           Ok(val) => val,

           Err(_err) => break,

       };

       entry_vec.push(entry);

   }

Optional: This pattern is repeated a number of times I wonder if it would be worth adding a method on ReadCtxt, read_until_end() so it can be reused in each place.

In src/morx.rs:

match lookup_table.lookup_header.format {

   0 => {

       match &lookup_table.lookup_table {

I would expect that lookup_table.lookup_header.format and the lookup table format to match because the ReadBinary impl on ClassLookupTable uses the format from the header to drive which lookup table it tries parse. As a result I think the match on lookup_table.lookup_header.format can be removed and replaced with just a match on lookup_table.lookup_table.

In src/morx.rs:

                           match lookup_segment

                               .lookup_values

                               .read_item(usize::from(glyph - lookup_segment.first_glyph))

                           {

                               Ok(val) => return Some(val as u16),

                               Err(_err) => return None,

                           }

This can be simplified. Also val is already u16 so the cast can be removed. There are other place below where mapping Err to None can also be simplified using ok().
⬇ Suggested change

                           match lookup_segment

                               .lookup_values

                               .read_item(usize::from(glyph - lookup_segment.first_glyph))

                           {

                               Ok(val) => return Some(val as u16),

                               Err(_err) => return None,

                           }

                           lookup_segment

                               .lookup_values

                               .read_item(usize::from(glyph - lookup_segment.first_glyph)).ok()

In src/morx.rs:

               for lookup_entry in lookup_entries {

                   if glyph == lookup_entry.glyph {

                       return Some(lookup_entry.lookup_value);

                   }

               }

               return None; //out of bounds

Optional: This can be simplified with an iterator:
⬇ Suggested change

               for lookup_entry in lookup_entries {

                   if glyph == lookup_entry.glyph {

                       return Some(lookup_entry.lookup_value);

                   }

               }

               return None; //out of bounds

               lookup_entries

                   .iter()

                   .find_map(|entry| (entry.glyph == glyph).then(entry.lookup_value))

In src/morx.rs:

}
+}

+//------------------------------ Lookup function --------------------------------------------------------
+pub fn lookup<'a>(glyph: u16, lookup_table: &ClassLookupTable<'a>) -> Option {

if glyph == 0xFFFF {

   return Some(0xFFFF);

}

match lookup_table.lookup_header.format {

   0 => {

       match &lookup_table.lookup_table {

           LookupTable::Format0 { lookup_values } => {

               return lookup_values.get(usize::from(glyph)).copied();

           }

           _ => return None, //Only Format0 is valid here.

Optional: I think all the places that aren't an early return can remove the use of the return keyword.

In src/morx.rs:

                   }

                   UnitSize::TwoByte {

                       lookup_values: two_byte_values,

                   } => {

                       if (glyph >= *first_glyph)

                           && (glyph <= (*first_glyph + *glyph_count - 1))

                       {

                           match two_byte_values.read_item(usize::from(glyph - *first_glyph)) {

                               Ok(val) => return Some(val as u16),

                               Err(_err) => return None,

                           }

                       } else {

                           return None; //out of bounds

                       }

                   }

                   _ => return None, //Note: ignore 4-byte and 8-byte lookup values for now

Perhaps it should be documented in the comment why these aren't handled at the moment.

In src/morx.rs:

match lookup(glyph, class_table) {

   None => {

       return 1;

   }

   Some(val) => {

       if val == 0xFFFF {

           return 2;

       } else {

           return val;

       }

   }

}
⬇ Suggested change

match lookup(glyph, class_table) {

   None => {

       return 1;

   }

   Some(val) => {

       if val == 0xFFFF {

           return 2;

       } else {

           return val;

       }

   }

}

match lookup(glyph, class_table) {

   Some(0xFFFF) => 2,

   Some(val) => val,

   None => 1,

}

In src/morx.rs:

           if let Some(contxt_entry) = contextual_subtable

               .entry_table

               .contextual_entries

               .get(usize::from(index_to_entry_table))

           {

               entry = contxt_entry;

Typo:
⬇ Suggested change

           if let Some(contxt_entry) = contextual_subtable

               .entry_table

               .contextual_entries

               .get(usize::from(index_to_entry_table))

           {

               entry = contxt_entry;

           if let Some(context_entry) = contextual_subtable

               .entry_table

               .contextual_entries

               .get(usize::from(index_to_entry_table))

           {

               entry = context_entry;

In src/morx.rs:

                           [usize::from(entry.mark_index)],

                   ) {

                       self.glyphs[mark_pos].glyph_index = mark_glyph_subst;

                       self.glyphs[mark_pos].glyph_origin = GlyphOrigin::Direct;

We're directly indexing into things here (using [ ]), which makes me nervous as some of the values appear to come from the font data and this operation will panic if the value is out of bounds. I'd suggest using get when the value cannot be guaranteed to be in bounds.

In src/morx.rs:

       mark: None,

   }

}

pub fn process_glyphs<'b>(

   &mut self,

   contextual_subtable: &ContextualSubtable<'b>,

) -> Result<(), ParseError> {

   const SET_MARK: u16 = 0x8000;

   const DONT_ADVANCE: u16 = 0x4000;

   let mut old_glyph: u16;

   let mut new_glyph: u16;

   //loop through glyphs:

   for i in 0..self.glyphs.len() {

       let current_glyph: u16 = self.glyphs[i].glyph_index;

self.glyphs[i].glyph_index: There are a few places below that are repeating this expression where I think they could use current_glyph instead.

In src/morx.rs:

                           ligature.variation = val.variation;

                       }

                       None => return Err(ParseError::MissingValue),

                   };

                   let action: u32 = ligature_subtable.action_table.actions[action_index];

                   action_index += 1;

                   let mut offset = action & 0x3FFFFFFF; //take 30 bits

                   if offset & 0x20000000 != 0 {

                       offset |= 0xC0000000; //sign-extend it to 32 bits

                   }

                   let offset = offset as i32; //convert to signed integer

                   let index_to_components = glyph_popped as i32 + offset;

Suggest avoiding cast with i32::from

In src/morx.rs:

                   if index_to_components < 0 {

                       return Err(ParseError::BadValue);

                   }

                   let index_to_component_table: usize =

                       match usize::try_from(index_to_components) {

                           Ok(index) => index,

                           Err(_err) => return Err(ParseError::BadValue),

                       };

You can skip the < 0 check as usize::try_from will return an Err if the value is negative.

In src/morx.rs:

                       //let ligature_glyph = ligature_subtable.ligature_list.ligature_list

                       //[usize::from(index_to_ligature)];

Remove commented out code.

In src/morx.rs:

let mut glyph: u16;

let mut subst: u16;
for i in 0..glyphs.len() {

   glyph = glyphs[i].glyph_index;

   subst = noncontextual_lookup(glyph, &noncontextual_subtable.lookup_table);

   if (subst != 0xFFFF) && (subst != glyph) {

       glyphs[i].glyph_index = subst;

       glyphs[i].glyph_origin = GlyphOrigin::Direct;

   }

}
Ok(())
This can be made more idiomatic with an iterator:

⬇ Suggested change

let mut glyph: u16;
let mut subst: u16;
for i in 0..glyphs.len() {

   glyph = glyphs[i].glyph_index;

   subst = noncontextual_lookup(glyph, &noncontextual_subtable.lookup_table);

   if (subst != 0xFFFF) && (subst != glyph) {

       glyphs[i].glyph_index = subst;

       glyphs[i].glyph_origin = GlyphOrigin::Direct;

   }

}
Ok(())

for glyph in glyphs {

   let subst = noncontextual_lookup(glyph.glyph_index, &noncontextual_subtable.lookup_table);

   if (subst != 0xFFFF) && (subst != glyph.glyph_index) {

       glyph.glyph_index = subst;

       glyph.glyph_origin = GlyphOrigin::Direct;

   }

}
Ok(())

In src/morx.rs:

   small_caps: false,

   multi_subst_dup: false,

   is_vert_alt: false,

   fake_bold: false,

   fake_italic: false,

   extra_data: (),

   variation: None,

};

let mut glyphs: Vec<RawGlyph<()>> = vec![glyph1, glyph2, glyph3, glyph4, glyph5];

let features = Features::Custom(Vec::new());

let _res = apply(&morx_table, &mut glyphs, &features);

//println!("The glyphs array after morx substitutions: {:?}", glyphs);
Remove commented out code

In src/morx.rs:

for chain in morx_table.morx_chains.iter() {

   for subtable in chain.subtables.iter() {

       if subtable.subtable_header.coverage & 0xFF == 2 {

           //liga_subtable_no += 1;

           //println!("Ligature subtable No: {}", liga_subtable_no);

           if let SubtableType::Ligature { ligature_subtable } = &subtable.subtable_body {

               liga_subst.next_state = 0;

               liga_subst.component_stack.clear();

               liga_subst.process_glyphs(ligature_subtable)?;

           }

       }

   }

}

// println!("The glyphs array after ligature substitutions: {:?}", glyphs);
I think this test should have assertions that the glyphs array is in the expected state after applying the substitutions.

In src/morx.rs:

               }

               _ => false,

           };

           if apply {

               subfeature_flags =

                   (subfeature_flags & entry.disable_flags) | entry.enable_flags;

           }

       }

   }

}
Ok(subfeature_flags)
+}

+//------------------------------------ Ligature Substitution Test ----------------------------------------------------------
+pub fn morx_ligature_test<'a>(scope: ReadScope<'a>) -> Result<(), ParseError> {
Tests should have test attribute so they are run by cargo test,
⬇ Suggested change
-pub fn morx_ligature_test<'a>(scope: ReadScope<'a>) -> Result<(), ParseError> {
+#[test]
+pub fn morx_ligature_test<'a>(scope: ReadScope<'a>) -> Result<(), ParseError> {

In src/morx.rs:

                   !feature_mask.contains(FeatureMask::CLIG)

               }

               _ => false,

           };

           if apply {

               subfeature_flags =

                   (subfeature_flags & entry.disable_flags) | entry.enable_flags;

           }

       }

   }

}
Ok(subfeature_flags)
+}

+//------------------------------------ Ligature Substitution Test ----------------------------------------------------------
Tests should be in a module guarded by the test attribute so they are only built for the test harness:
#[cfg(test)]
mod tests {
// test functions in here
}
In src/morx.rs:

//string: "ptgffigpfl" (for Zapfino.ttf)

//let mut glyphs: Vec = vec![585, 604, 541, 536, 536, 552, 541, 585, 536, 565];

//string: "ptpfgffigpfl" (for Zapfino.ttf)
//let mut glyphs: Vec = vec![585, 604, 585, 536, 541, 536, 536, 552, 541, 585, 536, 565];

//string: "Zapfino" (for Zapfino.ttf)
//let mut glyphs:  Vec = vec![104, 504, 585, 536, 552, 573, 580];

//string: "ptgffigpfl" (for Ayuthaya.ttf)
//let mut glyphs: Vec = vec![197, 201, 188, 187, 187, 190, 188, 197, 187, 193];

//string: ""\u{1F468}\u{200D}\u{1F469}\u{200D}\u{1F467}\u{200D}\u{1F467}"" (for emoji.ttf)
//let mut glyphs:  Vec = vec![1062, 43, 1164, 43, 1056, 43, 1056];

//string: "U+1F1E6 U+1F1FA" (for emoji.ttf)
//let mut glyphs:  Vec = vec![16, 36];
Remove commented out code.

In src/morx.rs:

//print glyph array after applying substitutions.

for glyph in glyphs.iter() {

   println!("  {:?}", glyph);

}
I think this should also be replaced by assertions that the glyphs are as expected.

—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: @.***>


chore(small investigation): Slider component in full screen modal

The type of this PR is: TYPE

Description
Played around with the slider component in a modal screen and found out the following.
In the ArtworkFilterNavigator where we declare each filter modal screen the default horizontal gestureResponseDistance is 50 according the react navigation docs.
This resulted in the following behaviour:
User presses the left side of the slider and in iOS only (since in android the back gesture is not enabled by default), and at the same time the back gesture is triggered and the slider moves at the same time (see first video)
https://user-images.githubusercontent.com/21178754/152165873-236bc656-c4bf-433d-bac6-db43e5354dc3.mp4
This can be solved with the following addition in the <Stack.Screen> component
  options={{ gestureResponseDistance: { horizontal: 35 } }}

https://user-images.githubusercontent.com/21178754/152165897-f66cb1ed-ad25-41b2-94ab-8d168170bb40.mp4

PR Checklist (tick all before merging)

[ ] I have included screenshots or videos to illustrate my changes, or I have not changed anything that impacts the UI.
[ ] I have tested my changes on iOS and Android.
[ ] I have added tests/stories for my changes, or my changes don't require testing/stories, or I have included a link to a separate Jira ticket covering the tests.
[ ] I have added a feature flag, or my changes don't require a feature flag. (How do I add one?)
[ ] I have documented any follow-up work that this PR will require, or it does not require any.
[ ] I have added an app state migration, or my changes do not require one. (What are migrations?)
[ ] I have added a changelog entry below or my changes do not require one.

To the reviewers 👀

[ ] I would like at least one of the reviewers to run this PR on the simulator or device.

Changelog updates
Changelog updates

Cross-platform user-facing changes

iOS user-facing changes

Android user-facing changes

Dev changes

I like your idea. FIY We also have a similar screen and gestures are disabled for it 😄

Warnings

:warning:

❌ An error occurred while validating your changelog, please make sure you provided a valid changelog.

  Generated by :no_entry_sign: dangerJS against a839393a304087461c01a519c9940be5e932edf0

I like your idea. FIY We also have a similar screen and gestures are disabled for it 😄

Interesting, we might have to change that to a smaller distance in order to have the same behaviour in all screens 👍 , I think 10 might do the job as well:

Closing this since it has served its purpose (here is the actual implementation)


Add savings to cost Provider

Hi,
I'm working on GCP and I can view the cost of my services, So far everything is perfect.
But the plugin show me the cost of services without saving, is it possible to add the commitments?
Documentation:
https://cloud.google.com/billing/docs/how-to/bq-examples
Example:
SELECT   invoice.month,   SUM(cost)     + SUM(IFNULL((SELECT SUM(c.amount)                   FROM UNNEST(credits) c), 0))     AS total,   (SUM(CAST(cost AS NUMERIC))     + SUM(IFNULL((SELECT SUM(CAST(c.amount AS NUMERIC))                   FROM UNNEST(credits) AS c), 0)))     AS total_exact FROM 'project-ID.dataset.gcp_billing_export_v1_XXXXXX-XXXXXX-XXXXXX' GROUP BY 1 ORDER BY 1 ASC ;
Thank you.

Hi @jonathan-arenas-edo, thanks for the suggestion. It is quite a nice idea. I think this is also a generic case for different cloud providers. There are different kinds of costs (e.g., unblended cost, amortized cost, etc.). Ideally, users should be to configure what kind of cost InfraWallet needs to query (in the config yaml file at least for now, because later on we can provide UI for configurations).
I will discuss more with the team and see how we can support it :)

Great @gluckzhang thank you for your time and effort on it.

Hi @jonathan-arenas-edo, based on the example, I have updated the query to (SUM(CAST(cost AS NUMERIC)) + SUM(IFNULL((SELECT SUM(CAST(c.amount AS NUMERIC)) FROM UNNEST(credits) AS c), 0))) AS total_cost for GCP client. This is available in https://github.com/electrolux-oss/infrawallet/releases/tag/v0.1.7. Welcome to verify it :)

Great! I will check asap and I will give you my feedback.

Hi @gluckzhang, I confirm that it is working well, I can see the costs with savings.
Thank you.
Best regards.

That's great. Then I am going to close this ticket :)


Gowin and Tang Nano

I tried to write the Tang Nano. I have little experience with FPGA so far. Gowin is new to me.
A progress bar appears while writing, but an error message appears at the end.
Any tips for troubleshooting?
I used gigatron.fs and fpga_games.fi. If successful, will this create a Gigatron ROM?

With the GOWIN Programmer V<IP_ADDRESS> it now works

With the GOWIN Programmer V<IP_ADDRESS> it now works


blog: kyverno playground

Related issue
kyverno playground blog post 🤷

cc @fjogeleit

TODO: mention this old issue https://github.com/kyverno/kyverno/issues/2378

Keeping or ?

Keeping or ?

As discussed on slack, i will post it on my personal blog as the tone is not appropriate for the official kyverno blog.

Ok


ACM-12689: Adding rw mutexes for RBAC query proxy enforcement

Why
RBAC Query proxy utils.go watches for managed clusters asynchronously, whilst also facilitating query RBAC enforcement requests that both touch the same maps.
E.g.

Change happens to clusterA
User queries data with perms to access clusterA simultaneously

Resulting in the following error:
I0710 15:50:22.603117       1 util.go:97] managedcluster label names update required: false
I0710 15:50:22.685471       1 util.go:263] changed a managedcluster: namgcbswd41p
fatal error: concurrent map iteration and map writegoroutine 14780 [running]:
github.com/stolostron/multicluster-observability-operator/proxy/pkg/util.canAccessAllClusters(...)

I've added a RWmutex so that reads/writes can happen concurrently without panic.

/cherrypick release-2.11 release-2.10 release-2.9

/retest


mslink: fix darwin build

Motivation for this change
Things done

[x] Tested using sandboxing (nix.useSandbox on NixOS, or option sandbox in nix.conf on non-NixOS linux)
Built on platform(s)

[ ] NixOS
[x] macOS
[ ] other Linux distributions

[ ] Tested via one or more NixOS test(s) if existing and applicable for the change (look inside nixos/tests)
[ ] Tested compilation of all pkgs that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review wip"
[x] Tested execution of all binary files (usually in ./result/bin/)
[ ] Determined the impact on package closure size (by running nix path-info -S before and after)
[ ] Ensured that relevant documentation is up to date
[ ] Fits CONTRIBUTING.md.

Result of nixpkgs-review pr 119228 at 381f4a97 run on aarch64-linux 1

1 package built successfully:

mslink

1 suggestion:

warning: missing-phase-hooks
installPhase should probably contain runHook preInstall and runHook postInstall.
Near pkgs/tools/misc/mslink/default.nix:19:3:
   |
19 |   installPhase = ''
   |   ^


Request the training dataset for MarkerPose

Hi @jhacsonmeza
Sorry to bother you, I'm trying to replicate your code, can you expose train_ellipsegnet.py and train_superpoint.py data sets?

Hi @Gjj152
Unfortunately the dataset for train_superpoint.py isn't publicly available. On the other hand, you can find here https://github.com/jhacsonmeza/MarkerPose/issues/1#issuecomment-872415774 the dataset for train_ellipsegnet.py.
Let me know if you have any other question.

Hi @Gjj152 Unfortunately the dataset for train_superpoint.py isn't publicly available. On the other hand, you can find here #1 (comment) the dataset for train_ellipsegnet.py. Let me know if you have any other question.
Thank you for your answer. May I know the dataset structure of train_superpoint.py. Greatly appreciate!

Hi @Gjj152 Unfortunately the dataset for train_superpoint.py isn't publicly available. On the other hand, you can find here #1 (comment) the dataset for train_ellipsegnet.py. Let me know if you have any other question.

Thank you for your answer. May I know the dataset structure of train_superpoint.py. Greatly appreciate!

Hi @Gjj152 Unfortunately the dataset for train_superpoint.py isn't publicly available. On the other hand, you can find here #1 (comment) the dataset for train_ellipsegnet.py. Let me know if you have any other question.

Thank you for your answer. May I know the dataset structure of train_superpoint.py. I can make my own dataset for train_superpoint.py. Greatly appreciate!

Hi @Gjj152 Unfortunately the dataset for isn't publicly available. On the other hand, you can find here #1 (comment) the dataset for . Let me know if you have any other question.train_superpoint.py``train_ellipsegnet.py

Grateful appreciate!

Hi @jhacsonmeza
Sorry to bother you again. I try to use my own dataset to run train_superpoint.py, but it always went to wrong(like the picture post down).

I made this dataset by using Azure Kinect DK, the image size is (3840,2160) . I changed your ground_truth.txt and by using this code i got the data_centers.csv(like the picture post down)

then i changed the images and the data_centers.csv to (320,240) like this

By using this dataset, train_superpoint.py may ran dozens of epoch

What do you think about this question.
In addition, in my dataset i used c1 to cx , am I right?

Hi @Gjj152.
The error you're getting is in this line: https://github.com/jhacsonmeza/MarkerPose/blob/91b4761e7332e56381f0236dd51bd6adfeede329/Python/modules/dataset.py#L36 and it's due to an out of bound indexation in mask[target[:,1],target[:,0]]. If you see the error message, the code is indexing with 240 which is a coordinate that is out of the image (considering that your image size is 320x240). What is not clear to me is if you're getting this error after many epochs or at the beginning of training. Also it's not clear in which line of train_superpoint.py you're getting the error.
For your second question, yes you're right: (cXx, cXy) are the coordinates of c1, and (cYx, cYy) are the coordinates of c2.

Hi @jhacsonmeza ，
After a few debugs, I found that the problem appeared in Python/modules/transformations.py
https://github.com/jhacsonmeza/MarkerPose/blob/91b4761e7332e56381f0236dd51bd6adfeede329/Python/modules/transformations.py#L88
I found that some points would meet the above criteria, but would exceed the size of (320，240). For example, a bbox's left top point is (21,21) and right bottom point is (184,241) , according to your code union_wh[0]union_wh[1] will smaller than im.size, but  it goes beyond the boundary of the image. I try to address this issue by changing 88 line. The following code is what I use to replace line 88, ' if union_wh[0]union_wh[1] > (sz[0]-2k)(sz[1]-2*k):'. This solution is valid, but it will limit the target points to the range of (20,20) to (300,220), I don't know how this will affect the training of the network, may I ask your thoughts on writing line 88
Finally, I wonder if you could share the specific size of this pattern's inside diameter and outside diameter.

Hi @Gjj152, sorry for my late reply!
You're correct with the change. If you see the C++ implementation: https://github.com/jhacsonmeza/MarkerPose/blob/91b4761e7332e56381f0236dd51bd6adfeede329/C%2B%2B/src/transformations/points_trans.cpp#L68 we check if the union_bbox area is larger than the restriction_bbox area. This restriction_bbox is defined as:
int k = 20;
cv::Rect restriction_bbox(k, k, sz.width-2*k, sz.height-2*k);

where sz is the sized of the resized image (320x240 in your case). When we compute restriction_bbox.area() we basically get (sz.width-2*k)*(sz.height-2*k) which is the product between the width and height of the restriction_bbox.
This restriction bbox is used to avoid getting points very close to the image borders, and this is why you see the points are restricted to the range (20,20) to (300,220). The change you propose is correct and is exactly what the C++ implementation does. Thank you for spotting that bug! I already solved the problem here https://github.com/jhacsonmeza/MarkerPose/commit/4794f402e784c472770bebf491ff8615fc24fb44.
It's interesting that we wasn't able to get the same error than you, maybe it's because the randomness of the transformations. Did you get it after many runs?

Finally, I wonder if you could share the specific size of this pattern's inside diameter and outside diameter.

Inner diameter is 8mm and outer diameter is 20mm.
I'm attaching the SVG file of the target we used. You can measure all the dimensions you need there:

Hi @jhacsonmeza Thank you very much for your answer.
After completing the data set, I tried the program a dozen times, but every run failed, sometimes it reached hundreds of epcho, sometimes it stopped after dozens of epcho, maybe as you said, it result in the randomness of the transformations.

I see. That's interesting. Even though the bug is clear, we didn't get any error in the multiple times we used the code. Perhaps we had luck because the transformations are applied randomly and we only trained for 300-500 epochs, we never tried training with thousands of epochs as you did. Of course the more epochs you use, the more likely it's to get the error.
However, thank you again for catching the bug! Hope you can now train without problems. And please let me know if you have any other question.

Hi @Gjj152, sorry for my late response.
If I'm not wrong, there's a slight difference between the OpenCV and Matlab stereo calibration. If you calibrated your system with Matlab, you need to transpose the intrinsic matrices of camera 1 and camera 2 (K1 and K2) and also the rotation R and translation t between camera 1 and camera 2. Please try this a let me know if this solves your problem.
Another alternative to check if your problem is with the calibration or with your model, could be to visualize the center of the circles predicted by your model. For example, you can print here c1 and c2 and check if those coordinates are accurate, or you can even add a block of code below to visualize the points on the image:
# Check first view
cv2.circle(x1, (int(c1[0,0]),int(c1[0,1])), 5, (0,0,255), -1)
cv2.circle(x1, (int(c1[1,0]),int(c1[1,1])), 5, (0,255,0), -1)
cv2.circle(x1, (int(c1[2,0]),int(c1[2,1])), 5, (255,0,0), -1)
cv2.imshow('im1',x1)
cv2.waitKey(0)
cv2.destroyAllWindows()

# Check second view
cv2.circle(x2, (int(c2[0,0]),int(c2[0,1])), 5, (0,0,255), -1)
cv2.circle(x2, (int(c2[1,0]),int(c2[1,1])), 5, (0,255,0), -1)
cv2.circle(x2, (int(c2[2,0]),int(c2[2,1])), 5, (255,0,0), -1)
cv2.imshow('im2',x2)
cv2.waitKey(0)
cv2.destroyAllWindows()

See that I used x1 and x2which are the full resolution images.
Please let me know if you solve your problem.


Timezone

Logs are in GMT but my timezone is GMT+2
Resulting in the graph being offset by 2 hours

Any way to change that?

TZ=GMT ./chiaharvestgraph config/mainnet/log


Drogon update at vcpkg

Drogon's version at vcpkg is only 1.5.1

no, it's 1.6.0 on vcpkg, I'll make a pr for v1.7.0 after trantor's pr is accepted.

1.7.1 have been merged in vcpkg.


Added support for running restorecon after modifying file contexts

The fcontext defined type sets the permanent state, but you still have to run restorecon to actually make that change take effect.   This is a proposal that by default will always run restorecon on the pathname (unless disabled with the $restorecond = false flag set)
Happy to look at better ways of doing this, but I wanted to be able to make the changes take effect without having to take a second step in puppet.

Thanks for the code!


Assignment 2 upload

Hi Jeremy, it did not work. Try running a npm install on your terminal and then pushing again


Refactored moving image animation to ensure continuous scrolling

This commit improves the layout of the partner logo section by ensuring both sets of images scroll seamlessly in a continuous horizontal loop. The .move "div 's" are now aligned side by side using display: flex, eliminating any gaps between the scrolling rows. The animation timing and structure have been adjusted to maintain smooth transitions, enhancing the visual effect of the partner logo carousel.

ISSUE #76
Hi @anuragverma108 and @piyushshrma  i have made the moving image animation to ensure continuous horizontal scrolling and let me know if any changes are required.

Conflicting files
assets/css/style.css
index.html
Please see the conflicts highlighted in the image above. Resolve the conflicts in the mentioned files. Ensure you pull all the latest changes before pushing your feature/bug fixes to the main branch. After resolving the conflicts, please open a new PR for review.
Thank you!


Setup merged Windows toolchain

Swift for TensorFlow macOS toolchains have a merged image, we should do similar releases for Windows

This seems less important now.  I wouldn't be against this, but I am very unlikely to ever bother with this.  The split model works very well, and with swift package manager and the latest installer improvements is completely a non-issue.


Draft rich command

This is a superseding draft #10416. I listened to your remarks but the code has changed too much to modify it.
This draft is a proof of concept of a new management of more centralized commands, to better organize the code.
Summary
The central concept is the IRichCommand interface which is a command with its attributes (label, glyph, hotkey, ...) and which can be used even if the commands are not accepted. These IRichCommand are not implemented directly, but by implementing the IAction interface which simplifies the creation of the commands.
IRichCommand
It is a command observable which includes descriptive properties (Label, Glyph, UserHotKey, DefaultHotKey, ...), usage properties (IsOn, IsExecutable) and call methods to be called in any context (Toggle, Tapped, ...). The command never takes a parameter and always exists, it is not created on demand. The command must itself find its context (for example the list of selected items) and notify its modifications (via CanExecuteChanged and/or PropertyChanging/ed). This way of doing things allows them to be placed in a menu or to assign a hotkey.
The use of commands is greatly simplified. In particular, it is no longer necessary to handle IsEnabled in views since the command updates its state. Menu creation is made easier because ContextMenuFlyoutItemViewModel accepts an IRichCommand in its constructor which makes numerous parameters unnecessary, including the visibility settings because the command itself decides if it is visible. Views must use all attributes because they must not know which ones are used.
ICommandManager
This service provides access to all commands for easy use in views.
IAction
This interface is used by the command manager to facilitate the implementation of commands. If an action implements INotifyPropertyChanging and/or INotifyPropertyChanged, this will be used to update the command. The interface includes default implementations for certain properties.
In this draft, I show some examples of easy-to-do UX changes:
ClearSelection is only active if items are selected.
Layout change menus no longer use texts containing hotkeys, they are generated by the command.
Hotkeys are displayed in tooltip or menu.
The toggle menu uses a command instead of a viewmodel, these commands can have a hotkey.
Hotkeys are centralized and no longer duplicated. They can be updated without having to restart the application (including the display in the menus).
The main problem to manage is to easily obtain the context of actions, and to be notified in case of changes.
I'm using an ICommandContext interface which gets updated on change, but it's not ideal (it's tentative but it's more structured than now). SidebarViewModel or IShellPage seem good candidates to have access to data but changes are not always notified
and, where possible, it manages change notifications at several hierarchical levels. The ideal would be to have a more complete hierarchical viewmodel layer, without containing commands but functions that allow you to do everything.
To add this functionality, it will be necessary to add the base, then to add the commands gradually.

Closing this PR since the work has been implemented in another PR.


Calling slice on a dynamic size array

Hey folks,
I'm struggling to find a way to call slice() on a dynamic ranked array, and can find a way to make it work.
extern crate ndarray;
use ndarray::*;

fn main() {
    let array: ArrayD<f32> = Array::zeros(vec![8, 8, 8]);
    foo(&array.view());
}

fn foo<'a>(a: &'a ArrayViewD<'a, f32>) -> ArrayViewD<'a, f32> {
    let slicer: Vec<SliceOrIndex> = (0..a.ndim())
        .map(|_| SliceOrIndex::Slice {
            start: 2,
            end: Some(6),
            step: 1,
        }).collect();
    let slice = SliceInfo::new(slicer).unwrap();
    a.slice(slice)
}

The gist of the issue is the type of the AsRef<[SliceOrIndex]> in  (slicer in the example).
   |
13 |     a.slice(slice)
   |             ^^^^^ expected reference, found struct `ndarray::SliceInfo`
   |
   = note: expected type `&ndarray::SliceInfo<[ndarray::SliceOrIndex], ndarray::Dim<ndarray::IxDynImpl>>`
              found type `ndarray::SliceInfo<std::vec::Vec<ndarray::SliceOrIndex>, _>`

I can't see how to make the typechecker happy here, and I can't instantiate SliceInfo<[ndarray::SliceOrIndex]> because [ndarray::SliceOrIndex] is not sized. Am I missing something obvious ?

The solution is to call .as_ref() manually on slice to perform the conversion, like this:
a.slice(slice.as_ref())

This calls this AsRef implementation (SliceInfo docs):
impl<T, D> AsRef<SliceInfo<[SliceOrIndex], D>> for SliceInfo<T, D>
where
    T: AsRef<[SliceOrIndex]>,
    D: Dimension,

This is a somewhat ugly part of the API. I have a plan to fix this but haven't gotten around to it yet.
Fwiw, for this particular example, it's simpler to use a series of .slice_axis() or .slice_axis_inplace() calls, like this:
fn foo<'a>(a: &'a ArrayViewD<'a, f32>) -> ArrayViewD<'a, f32> {
    let mut view = a.clone();
    for axis in 0..a.ndim() {
        view.slice_axis_inplace(Axis(axis), Slice::from(2..6));
    }
    view
}

@jturner314  Ha, thanks a lot. for the solution and, and for the slice_axis_inplace tip. Everything is dynamic in my case, s! is not an option.


Administrative management

Description of the new feature / enhancement
Companies do see value in some of the PowerToys features that help with daily tasks, which allows the users to be more productive.
However, since the introduction of Mouse Without Borders, this has now become a security concern for IT Admins. Some company polices do not allow personal devices to either access, connect, and/or share data with company issued devices. MWB allows users to circumvent these policies.
Please provide IT Admins with the ability to control features within PowerToys (e.g. Intune).
Scenario when this would be used?
Intune
Supporting information
No response

Hello and thanks for your message. Do you men (e.g.) Group Policy? Because that is possible with PowerToys.

@NVader2000
You can find the documentation at
https://github.com/microsoft/PowerToys/blob/main/doc/gpo/README.md.

https://learn.microsoft.com/en-us/windows/powertoys/grouppolicy

We do our best to include the files in release assets

what can we do better?

https://learn.microsoft.com/en-us/windows/powertoys/grouppolicy

Don't know this. Needs an update to implement the updater and experimentation policies.


[BUGFIX] Fix comment parsing to support multiple comments (backported)

Because of an eager consumption of whitespace, the rule parsing would swallow a trailing comment, meaning the comment for the next rule would be affected. This patch addresses this by only consuming real whitespace without comments after a rule.
Fixes #173

I'm a bit confused … do I need to forward-port this, or is this not necessary due to other upcoming changes in main?
(In general, if we want to create a PR that we are also planning to backport, we first create the PR for main and then backport it to the maintenance branch after it has been merged.)

I've now forward-ported this in #672. For future patches, please let's create the change for main first, and I (or another maintainer) will then take care of the backport. (This also works better with the branch protection in place, where we need another reviewer if we want to merge to main and would need to override this protection if we want to do a forward-port without an additional review.)

I wasn't done with the patches. As the solution for v8.x looks very different from the proposed solution for v9.0, I was about to create different patches. Either back-porting or forward-porting would have meant a completely different approach.

All right. I’m looking forward to your PRs! 🙏

And if you think talking things through would be helpful, please feel free to chat me up.


Removed unused views

Removed unused views and renamed ones in annotations/templates until those pages have been Bootstrapped DMPRoadmap/roadmap#667
moved plan navigation partial from shared to plans dir
removed old es5 version of org details JS. was causing JS compilation issues
fixed typos in location of plan nav partial
removed unused views and renamed a few in annotations and templates until those pages have been bootstrapped and we can confirm they are not needed.
switched API docs link to point to wiki docs
added template history view back in. remove token_permission_type controller and test. it was being used to list the API permission types and was linked from the 'How to use API' link. Updated that link to point to Wiki docs
added answer locking partial and phase preview back
added question preview back

Closing to rebase with latest changes


update "image delete" error to match actual behavior

The error message;
unable to delete .... (must be forced) - image is referenced in one or more repositories

Looks to be incorrect
Given the following images:
docker images | grep 2d36b1c0ea40
registry                           2                                     2d36b1c0ea40        7 weeks ago         171.2 MB
registry                           2.4.1                                 2d36b1c0ea40        7 weeks ago         171.2 MB

Removing the image by id fails:
docker rmi 2d36b1c0ea40
Error response from daemon: conflict: unable to delete 2d36b1c0ea40 (must be forced) - image is referenced in one or more repositories

However, after untagging one image:
docker rmi registry:2
Untagged: registry:2

Removing the image works:
docker rmi 2d36b1c0ea40
Untagged: registry:2.4.1
Deleted: sha256:2d36b1c0ea40159adc8b36f7563f1d7a6d443384fe2611e8b393c1cb3ae2e6ad
Deleted: sha256:7abfddbf4e61927307b6646010845eeb7513ecc6541f33ea6103b2493e36aa4e
Deleted: sha256:f512d7699dbb2994fe15d30ee1d404e57b58c3c310617b4471db649680b4cfa0
Deleted: sha256:7291e34714908270aeda93f1dc681485f9734d41314e2fdc6c11f32ffa782a21
Deleted: sha256:548f6562929484f3d78267e4b1e31dcfeb9f303059668888b4423ce5501c7fbc
Deleted: sha256:afe56b46629e6d8e0bfc36fed13395a7cfa2bd83b58bb489976ef13553eff20b
Deleted: sha256:cf0c3bd5d6a0a14ebf96cc7d3df79a37774a70f3086273e09da71a86fe74fec2
Deleted: sha256:c5fdaf8b055f544d0211043e687905315c3a0b71c1c08df07e473dd0a30e43c8

docker images | grep 2d36b1c0ea40
<empty>

This changes the error message to reflect that behavior
This also changes the comparison to check for > 1 reference for clarity;
The conflictActiveReference bit is only unset
(inside ImageDelete()) if there's just a single
reference to the image;
if isSingleReference(repoRefs) {
    c := conflictHard
    if !force {
        c |= conflictSoft &^ conflictActiveReference
    }

So changing to > 1 does not affect the actual flow, but makes it slightly more understandable.

ping @tonistiigi @aaronlehmann

hm, looks like this broke something? I'll need to look

@thaJeztah: This check only runs if the conflictActiveReference bit is set. The code in ImageDelete never actually sets this bit - it unsets it in the !force case (think conflictSoft except conflictActiveReference). So the only code path where this applies is imageDeleteHelper, which is called after at least one reference is already removed.
Yes, it's confusing :(

@aaronlehmann thanks! Looks like I missed that part; agree it's confusing (and explains why we changed this logic a couple of times before).
Should I still update the error message alone? Wondering if there's a situation where a single reference is reason to block deletion

Yes, it's okay by me to change the error message to be consistent with the user expectations (rather than the internal code flow).

@aaronlehmann updated to only change the error message, but keep the logic

LGTM

LGTM

TestApiSwarmRestartCluster in experimental is known flaky test https://github.com/docker/swarmkit/issues/1183


RUNTIME ERROR during make deploy

Hello!
I've answered all questions to deploy to vsphere and then ran make deploy, but i got an error!
i've added "set -x" in phase1/do to get more information.
make deploy
util/config_to_json /opt/kubernetes-anywhere/.config > /opt/kubernetes-anywhere/.config.json
make do WHAT=deploy-cluster
make[1]: Entering directory '/opt/kubernetes-anywhere'
( cd "phase1/vsphere"; ./do deploy-cluster )
+ set -o errexit
+ set -o pipefail
+ set -o nounset
+ cd .
++ jq -r .phase1.cluster_name ../../.config.json
+ CLUSTER_NAME=kubernetes
+ TMP_DIR=kubernetes/.tmp
+ case "${1:-}" in
+ deploy
+ gen
+ mkdir -p kubernetes/.tmp
+ jsonnet -J ../../ --multi kubernetes/.tmp all.jsonnet
RUNTIME ERROR: Field does not exist: cluster
       vSphere.jsonnet:109:22-40       object <anonymous>
       vSphere.jsonnet:(98:32)-(125:7) object <anonymous>
       std.jsonnet:(943:13)-(952:13)   object <anonymous>
       std.jsonnet:(943:13)-(952:13)   object <anonymous>
       all.jsonnet:3:49-79     object <anonymous>
       During manifestation
Makefile:70: recipe for target 'do' failed
make[1]: *** [do] Error 1
make[1]: Leaving directory '/opt/kubernetes-anywhere'
Makefile:48: recipe for target 'deploy-cluster' failed
make: *** [deploy-cluster] Error 2

thanks, maldex, this brought me one step further. .....now struggling with proxy :-/


replace bad characters before logging them out

Signed-off-by: Maksym Lisogorskyi<EMAIL_ADDRESS>Which issue(s) this PR fixes:
Fixes #3595
What this PR does / why we need it:
Replace an invalid character before it is logged out again.
Docs Changes:
none
Release Note:
invalid byte sequence is replaced in log line will not log out the invalid character.

Thanks!


How to set CompactionTableSize and WriteBuffer?

I do not understand the relationship between CompactionTableSize,CompactionTotalSize,WriteBuffer , and I just want to set the sst file size is 4M, how should set .
try set:
CompactionTableSize: 4 * opt.MiB,
CompactionTotalSize: 4 * 5 * opt.MiB,
WriteBuffer:         16 * opt.MiB,

but sst file size is 6M,why?

Currently CompactionTableSize only limits tables produced by table compaction but not memdb compaction (level-0). So level-0 tables size depends on memdb size (WriteBuffer).

Thank you very much , I understand


Does regex checking account for Filter Lists?

When using the regex checking feature, does the list of blocked domains include the fact that they might also be blocked by a filter list, or is the regex checker independent of the filter list checker?
I am trying to determine if I need the regex configurations that I have applied.

This has been merged into master.


Fixes collection-link display in Collection view

It uses same ID for more than one record and crashes visualization:

Changed to use ClassName instead

Fixed with https://github.com/agentejo/cockpit/commit/ab718dc5bf4fd4328149520ae00f956e9094d9f5


chore(deps): update common-dev-assets digest to 54b3d7e

This PR contains the following updates:

Package
Update
Change

common-dev-assets
digest
593e4fb -> 54b3d7e

Configuration
📅 Schedule: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
👻 Immortal: This PR will be recreated if closed unmerged. Get config help if that's undesired.

[ ] If you want to rebase/retry this PR, check this box

This PR has been generated by Renovate Bot.

/run pipeline

/run pipeline

/run pipeline


Android Default language management

Hi,
I've added the management of default language in csv2android command.
If a default language is set, the translations will be stored in the "values" folder.
Also, I have added a test set.
Thanks

Hey @filippodelfra and @netbe,
 I've try to use this functionality but it doesn't seems to work, here is my .babelish config:

`# This is a sample configuration file
###################################### Base2CSV ###############################
#######
required
filename: Localization.csv
default_lang: "en"
langs:
English: "en"
French: "fr"
comments_column: 0
keys_column: 1
###################################### General ################################\

csv_separator: ';'`
I've tried to change the default_lang with multiple things, like English, en, en-US etc but it doesn't seems to work with this pull request ... Do I am doing something wrong? I also tried with the command line variable but it doesn't work too
Thanks in advance,

@ExPl0siF could you be more specific about what you expect?
@filippodelfra default_lang option is supposed to be fallback on values (if a value is not translated it will use the one in the default_lang
If you want to overwrite the location of files, it might be with the output_dir and output_basename

@netbe I just want my Babelish config to output one values and one values-fr, but atm I only get one values-en and one values-fr, I juste want to remove the -en on my default langage :) Thanks in advance

@ExPl0siF did you manage to solve this issue?

@ExPl0siF did you manage to solve this issue?

Nope ... Never got an answer ... So I wrote a shell script that run babelish and then I mv the bad folder name

@ExPl0siF Thanks for your swift reply, really appreciated :)
ok, I will do the same.


Update readme for CLI plugin

I'm going to give this a :+1: for now, but we have more to do on the readme. I'd just rather not have one PR languishing for a while, trying to keep pace with other changes. I'd rather merge this and move on to other changes in a new PR.


New App: Billboard Top 10

Description
Displays the Top 10 songs from either US, Japan, or Global.
Pick your colors for the display text.
Uses RapidAPI Key - Programmed to pull data < 20 times a month which is the free level.
Request some help with the API Key, hoping Tidbyt can create their own RapidAPI Key in place of mine.
If you guys are willing to pay for $5 a month, I could rewrite the caching logic to check more often, but cache for a full 7 days once a new list is detected. That should make the updates more timely. Otherwise, no worries, close enough! :)
Copilot
copilot:all

Hey, thanks for the PR!
I'd prefer not to pick up the RapidAPI bill. No so much because of the cost, as the hassle of keeping track of yet another recurring payment. Paperwork's needed for each and every one of them... =\


Publish GitHub releases

Now we only publish tags (https://github.com/JetBrains/compose-jb/tags)
We should publish releases similar to https://github.com/JetBrains/skiko/releases, so we can see them in notifications (https://github.com/notifications?query=repo%3AJetBrains%2Fcompose-jb)

Done https://github.com/JetBrains/compose-jb/releases/latest

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.


HOW TO: Error handling

Documentation describing on a high level

Why we need a means to perform error handling, and why we don't use plain error codes or exceptions.
What it means for something to return a Returns<T>
How Error works and how to work with them.
Methods of checking a Returns contains an error, ways to handle this error conditions such as

check and handle value_or(),
check and handle,
Propagate up using SJ2_RETURN_ON_ERROR()
SJ2_RETURN_VALUE_ON_ERROR()
try(expression).catch({});

Due to #1372, Returns has been removed from SJSU-Dev2 and has been replaced with exception handling. Thus this is no longer needed.


Attaching volume without frontend

In volume revert or volume automatic restoration process, we don't want to expose Longhorn volumes to prevent users from accessing these pending volumes. Hence Longhorn should be capable of attaching a volume without frontend set.
The new field DisableFrontend is added for the attach call for this. DisableFrontend will be set/confirmed each time before volume attach.
There are 4 kinds of attaching and we need to consider DisableFrontend for each case:

Users can attach a volume via  Longhorn UI. Here DisableFrontend is decided by the input.
Volume controller of longhorn manager will attach restored volumes automatically. Here DisableFrontend should be true.
Volume controller will automatically re-attach a volume for node reboot. Here DisableFrontend should be false.
Kubernetes CSI handler will attach a volume for the related workload. Here DisableFrontend should be false.

DisableFrontend is false is double negative. EnableFrontend is true by default is the better way.

DisableFrontend is false is double negative. EnableFrontend is true by default is the better way.

How can I set the default value of EnableFrontend for HTTP request?

DisableFrontend is false is double negative. EnableFrontend is true by default is the better way.

How can I set the default value of EnableFrontend for HTTP request?

Hmm, that's why it's problematic sometimes to have two value bool instead of three value bool pointer. Seems there is no good way to do it. I guess we need to stick with DisableFrontend then.

LGTM. Wait for the integration test.

https://github.com/longhorn/longhorn/issues/629


DSC_xGroupResource: Fix for the issue #750

Pull Request (PR) description

This PR implements proposed workaround for the issue 750

This Pull Request (PR) fixes the following issues

Fixes #750

Task list

[x] Added an entry to the change log under the Unreleased section of the
file CHANGELOG.md. Entry should say what was changed and how that
affects users (if applicable), and reference the issue being resolved
(if applicable).
[ ] Resource documentation added/updated in README.md.
[ ] Resource parameter descriptions added/updated in README.md, schema.mof
and comment-based help.
[x] Comment-based help added/updated.
[x] Localization strings added/updated in all localization files as appropriate.
[ ] Examples appropriately added/updated.
[ ] Unit tests added/updated. See DSC Community Testing Guidelines.
[ ] Integration tests added/updated (where possible). See DSC Community Testing Guidelines.
[ ] New/changed code adheres to DSC Community Style Guidelines.

This change is

Just wanted to point out that all merits go to https://github.com/SDedik as he is the original provider of the workaround.

Hi @danielmiu - thanks for submitting this! It looks like the CI is failing due to the pipelines not being updated to remove the old WS 2016 images. I've created an issue to get this resolved. Will try and do this later on today (it's a simple enough issue): https://github.com/dsccommunity/xPSDesiredStateConfiguration/issues/752
You'll then need to rebase onto main once it's merged. Sorry about that.

I've created the PR to fix the pipeline: https://github.com/dsccommunity/xPSDesiredStateConfiguration/pull/753
Once merged you can rebase onto main and it should fix the CI.

The PR to fix CI has been merged. This PR can nbe rebased now.

Done, hope I didn't do a mess will rebasing :)

@danielmiu, really strange: it looks like it's rebased fine, but the azure-pipelines.yml is compared against the old one before I made the CI fix. Did you fetch main from upstream before you rebased?

Yes, I did. Would it be cleaner if I just create a new PR? There aren’t that many changes required to fix the issue.

Hi @danielmiu - maybe. If you're happy to?


Support formData in server validation

This is an incomplete PR. Please feel free to take it all the way. I just thought it would be more helpful than an issue 😅

I think in many cases you'll want formData.get("whatever") instead of the field's current value, since validation is async and the error message will show the wrong value while the next validation runs. This could solve that nicely!

Good call @chaance - looks like there's a bit of a bug in re-generating the custom error message using the new value while old validations are pending.  Going to file a separate issue for that

^^ https://github.com/brophdawg11/remix-validity-state/issues/20

Just released this in 0.6.0 👍

Thank you!


The training code not deal with paired data yet?

Hello, nice work!~
Look like the code not read text infor together with image yet, right?

nope it does! will document in readme soon


Webtracker quick links

Quick links to webtracker for 1day/week/month/year

This should ideally be in runelite/runelite.net repo

ye not gunna lie wasnt 100% where to put this but figured it was related enough =p


Create the user side Hour submissions mock-up page

Please do work for this task in a branch called issue-98.
This page will ask the user how many hours the user plans to volunteer for the specific event.
This event must have been vetted by org.

Forgot to make the branch, the changes are already in main


Files contain windows line endings (crlf) which are incompatible with bash

When following the instructions, I encountered numerous errors relating to windows style line endings in the .env file, terraform files and bash scripts.
It was necessary to execute dos2unix against all files in the project in order to resolve these issues.

#33

#33 resolves


Param hotfix

Previously, only single model parameter spaces were fully supported by ngen-cal.
This feature makes it possible to calibrate a multi-bmi model with ngen by allowing multiple parameter sets from different models to be combined into a single search space with a unique (ish) index.

[!NOTE]
Parameters with the exact same name between two models will be exposed as two parameters in the parameter space, but will always share the same value.

I don't think this works at least for dds in the uniform case b.c. this does not guarantee unique index values. When dds_update selects a random subset of parameters, if two of the parameters share the same name (e.g. 2 bmi modules have calib param with same name) the following code throw.
https://github.com/NOAA-OWP/ngen-cal/blob/0f5843d713e76fb0a23eef6e25e4d75d789b2f7d/python/ngen_cal/src/ngen/cal/search.py#L77-L94


Access UserProperties on ServiceBusTrigger when IsBatched is true

I'm using the ServiceBusTrigger on a function with Azure Functions 5, I've therefor had to use a string due to the binding limitations and my binding looks like this;
public async Task RunAsync([ServiceBusTrigger(SERVICE_BUS_QUEUE_NAME, Connection = "ServiceBusConnectionString")] string message, IDictionary<string, object> userProperties)
I want to take advantage of batching so I also pass IsBatched = true and changed string message to string[] messages but I'm unsure from reading source code how I'm meant to get the userProperties for each of the messages ?

@tommymonk, I apologize for the delay here.
You should be able to access all metadata including userProperties using FunctionContext.BindingData such as --
public static void Run([ServiceBusTrigger("<topic>", "<sub>", IsBatched = true)] string[] mySbMsg, FunctionContext context)
{
    string userPropertiesArraySerialized = context.BindingContext.BindingData["userPropertiesArray"];
}

Note that, at the moment, it will be a serialized string of array with all the properties.
Please let us know if this solves your issue. Thanks!

@ankitkumarr your proposal seems to work, strange though that I seem to get drips and drabs, infrequent batches with less than 5 items usually event though there are plenty in the queue and MaxMessageCount is set to 1000


pull request for e2e test at 01/19/2017 18:15:12

:white_check_mark: Validation status: passed
For more details, please refer to the build report.
Note: If you changed an existing file name or deleted a file, broken links in other files to the deleted or renamed file are listed only in the full build report.


UI improvements for Android

Remove the background of the status bar:

Before

After

Remove the background of the gestures indicator:

Before

After

Thanks a lot for the contribution!!

I think my Flutter version is too new. If I use the home_weight 0.5.0, I will get the following error:
Launching lib/main.dart on iPhone 15 in debug mode...
Xcode build done.                                           16.2s
Failed to build iOS app
Error (Xcode): ../../.pub-cache/hosted/pub.dev/home_widget-0.5.0/lib/src/home_widget.dart:176:11: Error: No named parameter with the name 'size'.

Could not build the application for the simulator.
Error launching application on iPhone 15.

Exited (1).


Error: No dependency factory available for this dependency type: MultiEntryDependency

><EMAIL_ADDRESS>dev C:\localhost\csgo
> cross-env NODE_OPTIONS='--inspect' next

Debugger listening on ws://<IP_ADDRESS>:9229/09daed7d-7fde-432b-b57f-f9776fcecd38
For help, see: https://nodejs.org/en/docs/inspector
[ wait ]  starting the development server ...
[ info ]  waiting on http://localhost:3000 ...
[ ready ] compiled successfully - ready on http://localhost:3000
[ event ] build page: /next/dist/pages/_error
[ wait ]  compiling ...
Error: No dependency factory available for this dependency type: MultiEntryDependency
    at Compilation._addModuleChain (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1057:10)
    at Compilation.addEntry (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1164:8)
    at C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:2:168
    at new Promise (<anonymous>)
    at addEntry (C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:2:58)
    at C:\localhost\csgo\node_modules\next\dist\server\on-demand-entry-handler.js:3:129
    at async Promise.all (index 0)
(node:3676) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'addChunk' of null
    at Object.connectChunkAndModule (C:\localhost\csgo\node_modules\webpack\lib\GraphHelpers.js:35:13)
    at Compilation.seal (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1308:17)
    at C:\localhost\csgo\node_modules\webpack\lib\Compiler.js:675:18
    at C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1261:4
    at AsyncSeriesHook.eval [as callAsync] (eval at create (C:\localhost\csgo\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonym
ous>:13:1)
    at AsyncSeriesHook.lazyCompileHook (C:\localhost\csgo\node_modules\tapable\lib\Hook.js:154:20)
    at Compilation.finish (C:\localhost\csgo\node_modules\webpack\lib\Compilation.js:1253:28)
    at C:\localhost\csgo\node_modules\webpack\lib\Compiler.js:672:17
    at eval (eval at create (C:\localhost\csgo\node_modules\tapable\lib\HookCodeFactory.js:33:10), <anonymous>:11:1)
(node:3676) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async fu
nction without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled p
romise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (
rejection id: 2)
(node:3676) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not han
dled will terminate the Node.js process with a non-zero exit code.
[ event ] build page: /support
[ event ] build page: /support

This issue contains no relevant information to even remotely derive the issue. What's your entry, ....

I will try to create a separate repository and isolate the problem as much as possible

Did this get fixed?


Add shim for defineComponent for better backwards compatibility

Summary
Fixes #
This PR adds a shim for defineComponent.
This means that extensions built with the newer shell will be able to be loaded into older versions of Rancher (2.8.0, 2.8.1, 2.8.2, 2.8.3 and 2.7).
The main benefit of defineComponent is in the typing - the actual implementation simply returns the options it is passed.
Note: The AsyncButton uses the inject function from vue - this is the only other use of function exports from Vue, so to be complete, we would need to replace the use of inject there (temporarily) - it is not easy to shim the inject function.
This change doesn't need to go into a Rancher release as such - it needs to be published into a shell version, which will then mean extensions built with that shell will work in older versions if they use components declared with defineComponent.
The implementation is a WebPack plugin - during compilation we process the abstract syntax tree looking at import statements - any from vue for defineComponent are updated to refer to a small shim, rather than the vue module.
Areas or cases that should be tested

Areas which could experience regressions

Screenshot/Video

Checklist

[ ] The PR is linked to an issue and the linked issue has a Milestone, or no issue is needed
[ ] The PR has a Milestone
[ ] The PR template has been filled out
[ ] The PR has been self reviewed
[ ] The PR has a reviewer assigned
[ ] The PR has automated tests or clear instructions for manual tests and the linked issue has appropriate QA labels, or tests are not needed
[ ] The PR has reviewed with UX and tested in light and dark mode, or there are no UX changes

After discussion, to work around this issue, the recommendation is to compile extensions with the Vue library embedded when compatibility is required.


White screen

System Details
OS : WINDOWS 11 23H2
VERSION THORIUM : LATEST
Problem
White screen when trying to open and close instantly
Screenshots
https://yanko.uploads.systems/💸/80jstk6k.mp4

fix?

Same as here ?


Add flatten-array exercise

Summary of changes:

Add flatten-array exercise and test cases
Update config.json to have flatten-array entry

Thank you @mcmillhj!


Localized time-formats with Prompts.time()?

Bot Info

SDK Platform:  Node.js
SDK Version:

Issue Description

In french, Prompts.time doesn't work with Aujourd’hui but works well with Aujourd'hui.

(the difference is in the characters ’ ' )
Unfortunately, the first version (Aujourd’hui) is suggested by default on ios 11.

In french, Prompts.time request a english format date (MM/DD/YYYY) instead of french format date (DD/MM/YYYY)

Could you fix this bug please ?
Thanks
Code Example
builder.Prompts.time(session, "...");
Reproduction Steps

In French ("fr")
builder.Prompts.time(session, "...");
type 01/02/2017

Expected Behavior
results.response.resolution.start should be Wed Feb 01 2017
Actual Results
results.response.resolution.start is Mon Jan 02 2017

@jschristophe What version of botbuilder produces the error?

@jschristophe It's not a "bug", its just not a feature. Currently, Prompts.time() expects input to be in en-US format.
Feel free to submit a PR with the desired time localization capabilities. Contributions welcome!

@nwhitmont I respectfully disagree. As stated in the docs Prompts.time() uses the Chrono library. Chrono allows input in other languages (see https://github.com/wanasit/chrono/tree/master/src/parsers).
Why is Prompts.time() not making use of these localizations which already exist and sit there ready to be used? For me this seems to be a flawed or incomplete inclusion of Chrono and I therefore would consider this a bug. A bug - I may add - that makes Prompts.time() completely useless for the vast majority of mankind.


Convert Windows registry queries to use winreg module

Python 3 adds a winreg module to the standard library to perform Windows registry queries using native APIs.
This change converts the rez registry queries to use the winreg API instead of executing cmd.exe and/or powershell and parsing their output.

This may also fix #1467

Hi @nrusch , thanks for submitting this PR. We require all contributors to sign a CLA. You can look at the comment above from EasyCLA (https://github.com/AcademySoftwareFoundation/rez/pull/1780#issuecomment-2195487061) and follow the instructions. Let us know if you hit any problems.

Yes, I'm aware of the CLA requirement. We are working on getting our Netflix corporate CLA working, so I'm waiting for a follow-up from people higher up the chain.

OK, the CLA should be resolved now.

Hi @nrusch thanks for this PR, we're also really interested in having this merged !
I was having issues with how powershell plugin queries the registry to get the standard_system_paths. It is much slower than what is currently done in windows.get_syspaths_from_registry for an identical result (on my end).
Now using winreg seems an even better option so here's a little bump for the tsc members :)

Thank you @samson-jerome for the great feedback and trying it out! We are planning on merging this before our next release, which should hopefully happen in the next 2-3 weeks.


[Task]: Update Java version used by the runner to a newer version

What needs to happen?
Java container build is based on Apache Beam Java 8 base image.
https://github.com/apache/beam/blob/3a1b64106657346f436bc9011d894ca90408a69e/playground/backend/containers/java/Dockerfile#L55
Update it to a newer Java version (e.g. beam_java11_sdk)
Issue Priority
Priority: 3 (nice-to-have improvement)
Issue Components

[ ] Component: Python SDK
[ ] Component: Java SDK
[ ] Component: Go SDK
[ ] Component: Typescript SDK
[ ] Component: IO connector
[ ] Component: Beam examples
[X] Component: Beam playground
[ ] Component: Beam katas
[ ] Component: Website
[ ] Component: Spark Runner
[ ] Component: Flink Runner
[ ] Component: Samza Runner
[ ] Component: Twister2 Runner
[ ] Component: Hazelcast Jet Runner
[ ] Component: Google Cloud Dataflow Runner

.take-issue