Skip to main content

zerodds_corba_giop/
flags.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! GIOP Flags-Octet — Spec §15.4.1.
5//!
6//! GIOP 1.0 nutzt das 7. Header-Byte als reines `byte_order`-Octet
7//! (0=BE, 1=LE). Ab GIOP 1.1 ist es ein Bitfield:
8//!
9//! * Bit 0 — `byte_order` (0=BE, 1=LE).
10//! * Bit 1 — `fragment_bit` (1 = mehr Fragments folgen).
11//! * Bits 2..7 — reserviert (Spec §15.4.1: "set to 0").
12
13use zerodds_cdr::Endianness;
14
15/// GIOP-Flags-Octet (Spec §15.4.1 ab GIOP 1.1; in GIOP 1.0 nur
16/// `byte_order_bit` benutzt).
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
18pub struct Flags(pub u8);
19
20impl Flags {
21    /// Bit 0 — `byte_order` (1 = Little-Endian).
22    pub const BYTE_ORDER_BIT: u8 = 0b0000_0001;
23    /// Bit 1 — `fragment_bit` (1 = mehr Fragments folgen).
24    pub const FRAGMENT_BIT: u8 = 0b0000_0010;
25
26    /// Konstruiert Flags aus einer [`Endianness`].
27    #[must_use]
28    pub const fn from_endianness(e: Endianness) -> Self {
29        match e {
30            Endianness::Big => Self(0),
31            Endianness::Little => Self(Self::BYTE_ORDER_BIT),
32        }
33    }
34
35    /// Liefert die [`Endianness`] aus dem Bit-0.
36    #[must_use]
37    pub const fn endianness(self) -> Endianness {
38        if self.0 & Self::BYTE_ORDER_BIT != 0 {
39            Endianness::Little
40        } else {
41            Endianness::Big
42        }
43    }
44
45    /// `true` wenn das Fragment-Bit gesetzt ist.
46    #[must_use]
47    pub const fn has_more_fragments(self) -> bool {
48        self.0 & Self::FRAGMENT_BIT != 0
49    }
50
51    /// Setzt das Fragment-Bit.
52    #[must_use]
53    pub const fn with_fragment(mut self, more: bool) -> Self {
54        if more {
55            self.0 |= Self::FRAGMENT_BIT;
56        } else {
57            self.0 &= !Self::FRAGMENT_BIT;
58        }
59        self
60    }
61}
62
63#[cfg(test)]
64#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn from_endianness_round_trip() {
70        assert_eq!(Flags::from_endianness(Endianness::Big).0, 0);
71        assert_eq!(
72            Flags::from_endianness(Endianness::Little).0,
73            Flags::BYTE_ORDER_BIT
74        );
75        assert_eq!(
76            Flags::from_endianness(Endianness::Little).endianness(),
77            Endianness::Little
78        );
79    }
80
81    #[test]
82    fn fragment_bit_default_off() {
83        assert!(!Flags::default().has_more_fragments());
84    }
85
86    #[test]
87    fn with_fragment_sets_and_clears_bit() {
88        let f = Flags::default().with_fragment(true);
89        assert!(f.has_more_fragments());
90        let g = f.with_fragment(false);
91        assert!(!g.has_more_fragments());
92    }
93
94    #[test]
95    fn fragment_bit_value_matches_spec() {
96        // Spec §15.4.1: Bit 1 = 0x02.
97        assert_eq!(Flags::FRAGMENT_BIT, 0x02);
98    }
99
100    #[test]
101    fn byte_order_bit_value_matches_spec() {
102        // Spec §15.4.1: Bit 0 = 0x01.
103        assert_eq!(Flags::BYTE_ORDER_BIT, 0x01);
104    }
105
106    #[test]
107    fn fragment_and_byte_order_can_combine() {
108        let f = Flags(Flags::BYTE_ORDER_BIT | Flags::FRAGMENT_BIT);
109        assert_eq!(f.endianness(), Endianness::Little);
110        assert!(f.has_more_fragments());
111    }
112}