Skip to main content

oxihuman_export/
cbor_export.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5//! CBOR (Concise Binary Object Representation) encoding stub.
6
7/// CBOR major types.
8#[allow(dead_code)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum CborMajor {
11    Uint = 0,
12    NInt = 1,
13    Bytes = 2,
14    Text = 3,
15    Array = 4,
16    Map = 5,
17    Tag = 6,
18    Simple = 7,
19}
20
21/// Encode a CBOR header byte.
22#[allow(dead_code)]
23pub fn cbor_header(major: CborMajor, additional: u8) -> u8 {
24    ((major as u8) << 5) | (additional & 0x1F)
25}
26
27/// Encode an unsigned integer as CBOR.
28#[allow(dead_code)]
29pub fn encode_uint(val: u64) -> Vec<u8> {
30    cbor_encode_head(CborMajor::Uint, val)
31}
32
33/// Encode a text string as CBOR.
34#[allow(dead_code)]
35pub fn encode_text(s: &str) -> Vec<u8> {
36    let mut out = cbor_encode_head(CborMajor::Text, s.len() as u64);
37    out.extend_from_slice(s.as_bytes());
38    out
39}
40
41/// Encode a byte string as CBOR.
42#[allow(dead_code)]
43pub fn encode_bytes(data: &[u8]) -> Vec<u8> {
44    let mut out = cbor_encode_head(CborMajor::Bytes, data.len() as u64);
45    out.extend_from_slice(data);
46    out
47}
48
49/// Encode CBOR array header with n elements.
50#[allow(dead_code)]
51pub fn encode_array_header(n: usize) -> Vec<u8> {
52    cbor_encode_head(CborMajor::Array, n as u64)
53}
54
55/// Encode CBOR map header with n pairs.
56#[allow(dead_code)]
57pub fn encode_map_header(n: usize) -> Vec<u8> {
58    cbor_encode_head(CborMajor::Map, n as u64)
59}
60
61/// Encode a CBOR boolean.
62#[allow(dead_code)]
63pub fn encode_bool(val: bool) -> Vec<u8> {
64    vec![cbor_header(CborMajor::Simple, if val { 21 } else { 20 })]
65}
66
67/// Encode CBOR null.
68#[allow(dead_code)]
69pub fn encode_null() -> Vec<u8> {
70    vec![cbor_header(CborMajor::Simple, 22)]
71}
72
73/// Encode a 32-bit float as CBOR (major 7, additional 26).
74#[allow(dead_code)]
75pub fn encode_f32(val: f32) -> Vec<u8> {
76    let mut out = vec![cbor_header(CborMajor::Simple, 26)];
77    out.extend_from_slice(&val.to_bits().to_be_bytes());
78    out
79}
80
81/// Byte length of a CBOR-encoded uint.
82#[allow(dead_code)]
83pub fn uint_byte_len(val: u64) -> usize {
84    encode_uint(val).len()
85}
86
87fn cbor_encode_head(major: CborMajor, val: u64) -> Vec<u8> {
88    if val <= 23 {
89        vec![cbor_header(major, val as u8)]
90    } else if val <= 0xFF {
91        vec![cbor_header(major, 24), val as u8]
92    } else if val <= 0xFFFF {
93        let bytes = (val as u16).to_be_bytes();
94        vec![cbor_header(major, 25), bytes[0], bytes[1]]
95    } else if val <= 0xFFFF_FFFF {
96        let bytes = (val as u32).to_be_bytes();
97        let mut out = vec![cbor_header(major, 26)];
98        out.extend_from_slice(&bytes);
99        out
100    } else {
101        let bytes = val.to_be_bytes();
102        let mut out = vec![cbor_header(major, 27)];
103        out.extend_from_slice(&bytes);
104        out
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn encode_uint_small() {
114        let b = encode_uint(0);
115        assert_eq!(b.len(), 1);
116        assert_eq!(b[0], 0x00);
117    }
118
119    #[test]
120    fn encode_uint_23() {
121        let b = encode_uint(23);
122        assert_eq!(b.len(), 1);
123        assert_eq!(b[0], 23);
124    }
125
126    #[test]
127    fn encode_uint_24() {
128        let b = encode_uint(24);
129        assert_eq!(b.len(), 2);
130        assert_eq!(b[0], cbor_header(CborMajor::Uint, 24));
131    }
132
133    #[test]
134    fn encode_text_hello() {
135        let b = encode_text("hi");
136        assert_eq!(b.len(), 3);
137        assert_eq!(b[1..], b"hi"[..]);
138    }
139
140    #[test]
141    fn encode_bytes_nonempty() {
142        let b = encode_bytes(&[0xDE, 0xAD]);
143        assert_eq!(b.len(), 3);
144    }
145
146    #[test]
147    fn encode_bool_true() {
148        let b = encode_bool(true);
149        assert_eq!(b[0], cbor_header(CborMajor::Simple, 21));
150    }
151
152    #[test]
153    fn encode_bool_false() {
154        let b = encode_bool(false);
155        assert_eq!(b[0], cbor_header(CborMajor::Simple, 20));
156    }
157
158    #[test]
159    fn encode_null_one_byte() {
160        let b = encode_null();
161        assert_eq!(b.len(), 1);
162    }
163
164    #[test]
165    fn encode_f32_five_bytes() {
166        let b = encode_f32(1.0);
167        assert_eq!(b.len(), 5);
168    }
169
170    #[test]
171    fn array_header_correct() {
172        let b = encode_array_header(3);
173        assert_eq!(b[0], cbor_header(CborMajor::Array, 3));
174    }
175}