Skip to main content

oxihuman_core/
capnproto_stub.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! Cap'n Proto stub.
6
7/// A Cap'n Proto message segment.
8#[derive(Debug, Clone, Default)]
9pub struct CapnSegment {
10    words: Vec<u64>,
11}
12
13impl CapnSegment {
14    /// Create an empty segment.
15    pub fn new() -> Self {
16        Self::default()
17    }
18
19    /// Create a segment with pre-allocated capacity (in 64-bit words).
20    pub fn with_capacity(words: usize) -> Self {
21        CapnSegment {
22            words: Vec::with_capacity(words),
23        }
24    }
25
26    /// Append a 64-bit word.
27    pub fn push_word(&mut self, w: u64) {
28        self.words.push(w);
29    }
30
31    /// Return the number of words.
32    pub fn word_count(&self) -> usize {
33        self.words.len()
34    }
35
36    /// Return the byte length (each word is 8 bytes).
37    pub fn byte_len(&self) -> usize {
38        self.words.len() * 8
39    }
40
41    /// Return a reference to the underlying words.
42    pub fn words(&self) -> &[u64] {
43        &self.words
44    }
45
46    /// Read a word at the given index.
47    pub fn read_word(&self, index: usize) -> Option<u64> {
48        self.words.get(index).copied()
49    }
50}
51
52/// A Cap'n Proto message containing one or more segments.
53#[derive(Debug, Clone, Default)]
54pub struct CapnMessage {
55    segments: Vec<CapnSegment>,
56}
57
58impl CapnMessage {
59    /// Create an empty message.
60    pub fn new() -> Self {
61        Self::default()
62    }
63
64    /// Add a segment to the message.
65    pub fn add_segment(&mut self, seg: CapnSegment) {
66        self.segments.push(seg);
67    }
68
69    /// Return the number of segments.
70    pub fn segment_count(&self) -> usize {
71        self.segments.len()
72    }
73
74    /// Return the total word count across all segments.
75    pub fn total_words(&self) -> usize {
76        self.segments.iter().map(|s| s.word_count()).sum()
77    }
78
79    /// Return the total byte length.
80    pub fn total_bytes(&self) -> usize {
81        self.segments.iter().map(|s| s.byte_len()).sum()
82    }
83
84    /// Access a segment by index.
85    pub fn segment(&self, index: usize) -> Option<&CapnSegment> {
86        self.segments.get(index)
87    }
88}
89
90/// Serialise a message to a flat byte vector (stub: raw word bytes).
91pub fn serialize_message(msg: &CapnMessage) -> Vec<u8> {
92    let mut out = Vec::with_capacity(msg.total_bytes());
93    for seg in &msg.segments {
94        for &word in seg.words() {
95            out.extend_from_slice(&word.to_le_bytes());
96        }
97    }
98    out
99}
100
101/// Compute the traversal limit check (stub: just returns total words).
102pub fn traversal_limit_words(msg: &CapnMessage) -> usize {
103    msg.total_words()
104}
105
106/// Return `true` if the message is empty (no segments or all segments empty).
107pub fn message_is_empty(msg: &CapnMessage) -> bool {
108    msg.total_words() == 0
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn test_segment_empty() {
117        /* new segment is empty */
118        let s = CapnSegment::new();
119        assert_eq!(s.word_count(), 0);
120    }
121
122    #[test]
123    fn test_push_word() {
124        /* push_word increments word count */
125        let mut s = CapnSegment::new();
126        s.push_word(0xDEAD_BEEF_0000_0001);
127        assert_eq!(s.word_count(), 1);
128    }
129
130    #[test]
131    fn test_byte_len() {
132        /* byte_len is 8x word count */
133        let mut s = CapnSegment::new();
134        s.push_word(1);
135        s.push_word(2);
136        assert_eq!(s.byte_len(), 16);
137    }
138
139    #[test]
140    fn test_read_word() {
141        /* read_word retrieves correct value */
142        let mut s = CapnSegment::new();
143        s.push_word(42);
144        assert_eq!(s.read_word(0), Some(42));
145        assert_eq!(s.read_word(1), None);
146    }
147
148    #[test]
149    fn test_message_empty() {
150        /* new message has no segments */
151        let m = CapnMessage::new();
152        assert!(message_is_empty(&m));
153    }
154
155    #[test]
156    fn test_message_add_segment() {
157        /* add_segment increments count */
158        let mut m = CapnMessage::new();
159        m.add_segment(CapnSegment::new());
160        assert_eq!(m.segment_count(), 1);
161    }
162
163    #[test]
164    fn test_total_words() {
165        /* total_words sums across segments */
166        let mut m = CapnMessage::new();
167        let mut s = CapnSegment::new();
168        s.push_word(1);
169        s.push_word(2);
170        m.add_segment(s);
171        assert_eq!(m.total_words(), 2);
172    }
173
174    #[test]
175    fn test_serialize_message() {
176        /* serialised length equals total bytes */
177        let mut m = CapnMessage::new();
178        let mut s = CapnSegment::new();
179        s.push_word(0);
180        m.add_segment(s);
181        let data = serialize_message(&m);
182        assert_eq!(data.len(), m.total_bytes());
183    }
184
185    #[test]
186    fn test_traversal_limit() {
187        /* traversal limit matches total words */
188        let mut m = CapnMessage::new();
189        let mut s = CapnSegment::new();
190        s.push_word(1);
191        m.add_segment(s);
192        assert_eq!(traversal_limit_words(&m), 1);
193    }
194
195    #[test]
196    fn test_segment_access() {
197        /* segment() returns correct segment */
198        let mut m = CapnMessage::new();
199        let mut s = CapnSegment::new();
200        s.push_word(99);
201        m.add_segment(s);
202        assert_eq!(m.segment(0).expect("should succeed").read_word(0), Some(99));
203    }
204}