Skip to main content

FixedDigitCount

Enum FixedDigitCount 

Source
pub enum FixedDigitCount {
    Declared,
    ValuePrecision,
    ValueStringDigits,
}
Expand description

Whether a fixed<P,S>’s digit count comes from the declaration or from the value.

CORBA 3.3 part 2 §9.3.2.8 defines the wire form and nothing else: packed binary-coded decimal, two digits to the octet, most significant first, the low nibble of the last octet the sign — 0xC for positive or zero and 0xD for negative — with a leading zero nibble prepended when the nibble count is odd. IDL 4.2 §7.4.1.4.4.3.4 rule (42) gives the syntax and caps P at 31. XTypes 1.3 has no fixed-point type at all, which is why the rule is borrowed by name. What neither clause says is how many digits go on the wire, and the four implementations that write one split two and two.

§Two on each side, which is what makes it an axis

the digit countmeasured on
omniORB 4.3.3the declared Pfixed-basic, fixed-scales, fixed-scale-equals-digits, array-1d-fixed, sequence-fixed, both orders
this projectthe declared Pthe same rows, byte for byte with omniORB
JacORBthe value’s precisionthe same rows; docs/corba-column.md §3 traced it to BigDecimal.precision()
ACE/TAO 2.5.24the digits of the string the value was parsed fromACE_CDR::Fixed’s own CDR operator; tao_idl refuses the corpus’s fixed IDL so TAO has no recorded row, and its runtime was measured directly in unspecified_constructs.md §3
OpenDDS 3.34the declared Pits serializer writes OpenDDS::FaceTypes::Fixed_T<P,S>, (P + 2) / 2 octets, not through ACE_CDR::Fixed’s operator: 0.00 under fixed<5,2> is 00000c, 7 is 00700c (measured 2026-10-07 through the FACE mapping)

Judgement 3’s threshold, met: two independent implementations on each side, and both were in a position to answer differently — a front end that carried fixed<9,3> as far as a serialiser and then wrote the value’s digits chose to.

§The octets

fixed-basic, fixed<9,3>, amount = 123456.789 and debt = -000000.001, plain-cdr1 big endian:

ours    123456789c 00000000 1d ab
theirs  123456789c       1d ab

Only a value with leading zeros differs. fixed-scales and fixed-scale-equals-digits are byte-identical across omniORB, JacORB and this project, which is what makes the cause exact rather than inferred: fixed<31,10> holding thirty significant digits pads to sixteen octets under both readings, and fixed<4,4> holding four pads to three under both.

§The value’s precision is BigDecimal.precision()

The digit string with its leading zeros removed, and at least one digit: new BigDecimal("0.00").precision() is 1 in Java, so a zero goes out as the single nibble 0 and the sign, one octet 0c. That is the same “at least one” the C++ and Rust sides need, and it is why the rule is stated as max(significant, 1) rather than as “strip the leading zeros”.

§It is decodable, and the estimate said it was not

docs/open-rows-breakdown.md cause K states that “the declared count is the only decodable half: a reader must know the octet count from the type before it reads the value”. That is wrong, and the clause says why: a digit nibble is 0 to 9 and a sign nibble is 0xA to 0xF, so the field ends at the first octet whose low nibble is at least 0xA. The count of nibbles is even by construction, so the sign is always a low nibble and never a high one. A reader of this form scans; all three columns do, and crates/wire-probe/tests/fixed_digit_count.rs::the_value_precision_form_reads_back is that as a test over the recorded JacORB rows.

§It is a planner setting

Unlike MapEntryOrder and UnionLabelMatch. A fixed’s extent is ceil((P + 1) / 2) octets under Self::Declared and depends on the value under Self::ValuePrecision and Self::ValueStringDigits, so the type stops being fixed-size and every member behind it moves. It is in LayoutKey::offset_key for that reason, and the_extent_is_unbounded_under_the_value is the claim as a test.

§Three readings exist

  1. Declared — P digits, padded to even nibble count. What omniORB 4.3.3 and this project’s default write.
  2. ValuePrecision — the value’s precision with leading and trailing zeros removed, minimum one digit. What JacORB 3.9 writes (BigDecimal.precision()).
  3. ValueStringDigits — the integer digits of the decimal as written, leading zeros included, plus the S fraction digits of the declaration, padded to an odd digit count by adding one leading zero if even. What ACE/TAO 2.5.24’s ACE_CDR::Fixed writes for a decimal with S fraction digits — it counts the digits of the string it was parsed from — which is what OpenDDS’s generated write_fixed calls. The fraction is counted at S and not as written: "7" under fixed<5,2> is 700c, and counting one digit would have kept only its last nibble, 0c.

The three differ on values with fewer digits than the type declares:

declaredvalue stringdigit countDeclaredValuePrecisionValueStringDigits
fixed<5,5>"0.12345"6 (even)557 (0012345)
fixed<5,2>"0.00"3 (odd)513 (000)
fixed<4,2>"12.34"4 (even)445 (01234)
fixed<5,2>"123.45"5 (odd)555 (12345)
fixed<1,0>"7"1 (odd)111 (7)
fixed<5,2>"7"1 + 2 (odd)533 (700)

The ValueStringDigits column is pinned by the recorded ACE values in unspecified_constructs.md §3:

  • fixed<5,5> "0.12345" → 0012345c (7 digits) pins the even→odd padding.
  • fixed<5,2> "0.00" → 000c (3 digits) pins the odd count without padding.
  • fixed<4,2> "12.34" → 01234c (5 digits) pins the even→odd padding.
  • fixed<5,2> "123.45" → 12345c (5 digits) pins the odd count without padding.
  • fixed<1,0> "7" → 7c (1 digit) pins the minimum one digit.
  • The fixed<31,0> row (31 nines) agrees across all three and does not separate them.

Variants§

§

Declared

P digits, whatever the value is — the declaration decides.

The default, and what omniORB 4.3.3 writes.

§

ValuePrecision

As many digits as the value has, and never fewer than one.

What JacORB 3.9 writes. Named for the rule and not for a vendor, because two implementations reached it independently.

§

ValueStringDigits

The integer digits of the decimal as written, leading zeros included, plus the S fraction digits, padded to an odd digit count by adding one leading zero if the count is even.

What ACE/TAO 2.5.24’s ACE_CDR::Fixed writes for a decimal with S fraction digits, through its own CDR operator. Measured in unspecified_constructs.md §3. OpenDDS does not write it: its serializer writes the declared count (see Dialect::fixed_digits).

Implementations§

Source§

impl FixedDigitCount

Source

pub const ALL: [Self; 3]

All three.

Source

pub const FIRST_SIGN_NIBBLE: u8 = 0x0a

The lowest nibble value that is a sign and not a digit.

CORBA 3.3 part 2 §9.3.2.8: a digit is 0 to 9, and every nibble at or above this is a sign. It is what makes the value-precision form self-delimiting, and it is a constant here so the three runtimes cannot each pick their own.

Source

pub const fn is_default(self) -> bool

Whether this is the default.

Source

pub const fn as_str(self) -> &'static str

Short name, for configuration and diagnostics.

Source

pub const fn wire_digits( self, declared: u8, significant: u8, string_digits: u8, ) -> u8

How many digit nibbles a value goes out with.

declared is P; significant is the value’s digit count with its leading zeros removed. The one place the two cross into a wire width. crate::fixed_wire_digits is what call sites use; this is the arithmetic behind it, separated so that the crossing can be tested without a value.

Never zero under any value: a field of no digits could not carry the sign nibble’s pair.

Source

pub fn parse(value: &str) -> Option<Self>

Parse a configuration value.

An unknown value returns None rather than falling back to the default: a typo in a wire-affecting setting must be loud.

Trait Implementations§

Source§

impl Clone for FixedDigitCount

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for FixedDigitCount

Source§

impl Debug for FixedDigitCount

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for FixedDigitCount

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Eq for FixedDigitCount

Source§

impl Hash for FixedDigitCount

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for FixedDigitCount

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for FixedDigitCount

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for FixedDigitCount

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl StructuralPartialEq for FixedDigitCount

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.