number_encoding/
sequences.rs

1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Bit sequence number system
16//!
17//! This permits to convert between variable-length bit sequences (i.e. `[bool]`) and fixed-length
18//! bit sequences (i.e. `usize`).
19
20#[cfg(feature = "alloc")]
21use alloc::vec;
22#[cfg(feature = "alloc")]
23use alloc::vec::Vec;
24
25/// Maximum sequence length.
26pub const MAX_LENGTH: usize = usize::BITS as usize - 1;
27
28/// Maximum sequence value.
29///
30/// Sequences above this value are invalid.
31pub const MAX_SEQUENCE: usize = usize::MAX - 1;
32
33/// Returns the sequence length.
34///
35/// # Panics
36///
37/// Panics in debug mode if `s > MAX_SEQUENCE`.
38pub fn decode_len(s: usize) -> usize {
39    debug_assert!(s <= MAX_SEQUENCE, "Failed precondition");
40    MAX_LENGTH - (s + 1).leading_zeros() as usize
41}
42
43#[test]
44fn decode_len_ok() {
45    fn test(s: usize, n: usize) {
46        assert_eq!(decode_len(s), n, "s={s}");
47    }
48    test(0, 0);
49    test(1, 1);
50    test(2, 1);
51    test(3, 2);
52    test(6, 2);
53    test(7, 3);
54    test(14, 3);
55}
56
57/// Writes the sequence of a value to a slice.
58///
59/// The written sequence can be encoded with [`encode`] to get back `s`.
60///
61/// ```rust
62/// # use number_encoding::sequences::{decode_len, decode_mut, encode};
63/// # let s = 13;
64/// let n = decode_len(s);
65/// let mut xs = vec![false; n];
66/// decode_mut(s, &mut xs);
67/// assert_eq!(encode(&xs), s);
68/// ```
69///
70/// See [`decode`] for a version that allocates a vector for the sequence.
71///
72/// # Panics
73///
74/// Panics in debug mode if `s > MAX_SEQUENCE` or `xs.len() != decode_len(s)`.
75pub fn decode_mut(s: usize, xs: &mut [bool]) {
76    debug_assert!(s <= MAX_SEQUENCE, "Failed precondition");
77    let n = decode_len(s);
78    debug_assert_eq!(xs.len(), n, "Failed precondition");
79    for (i, x) in xs.iter_mut().rev().enumerate() {
80        *x = (s + 1) & 1 << i != 0;
81    }
82}
83
84/// Returns the sequence of a value.
85///
86/// The returned sequence can be encoded with [`encode`] to get back `s`.
87///
88/// ```rust
89/// # use number_encoding::sequences::{decode, encode};
90/// let s = 13;
91/// let xs = decode(s);
92/// assert_eq!(encode(&xs), s);
93/// ```
94///
95/// See [`decode_mut`] for a version that writes the sequence to a provided slice.
96///
97/// # Panics
98///
99/// Panics in debug mode if `s > MAX_SEQUENCE`.
100///
101/// # Examples
102///
103/// ```rust
104/// # use number_encoding::sequences::decode;
105/// assert_eq!(decode(0), &[]);
106/// assert_eq!(decode(1), &[false]);
107/// assert_eq!(decode(2), &[true]);
108/// assert_eq!(decode(13), &[true, true, false]);
109/// ```
110#[cfg(feature = "alloc")]
111pub fn decode(s: usize) -> Vec<bool> {
112    let n = decode_len(s);
113    let mut xs = vec![false; n];
114    decode_mut(s, &mut xs);
115    xs
116}
117
118#[test]
119fn decode_ok() {
120    fn test(s: usize, xs: &[bool]) {
121        assert_eq!(decode(s), xs, "s={s} xs={xs:?}");
122    }
123    test(0, &[]);
124    test(1, &[false]);
125    test(2, &[true]);
126    test(3, &[false, false]);
127    test(4, &[false, true]);
128    test(5, &[true, false]);
129    test(6, &[true, true]);
130    test(7, &[false, false, false]);
131    test(8, &[false, false, true]);
132    test(9, &[false, true, false]);
133    test(10, &[false, true, true]);
134    test(11, &[true, false, false]);
135    test(12, &[true, false, true]);
136    test(13, &[true, true, false]);
137    test(14, &[true, true, true]);
138}
139
140/// Returns the value of a sequence.
141///
142/// The returned value can be decoded with [`decode`] to get back `xs`.
143///
144/// ```rust
145/// # use number_encoding::sequences::{decode, encode};
146/// # let xs = &[true, true, false];
147/// let s = encode(xs);
148/// assert_eq!(decode(s), xs);
149/// ```
150///
151/// # Panics
152///
153/// Panics in debug mode if `xs.len() > MAX_LENGTH`.
154///
155/// # Examples
156///
157/// ```rust
158/// # use number_encoding::sequences::encode;
159/// assert_eq!(encode(&[]), 0);
160/// assert_eq!(encode(&[false]), 1);
161/// assert_eq!(encode(&[true]), 2);
162/// assert_eq!(encode(&[true, true, false]), 13);
163/// ```
164pub fn encode(xs: &[bool]) -> usize {
165    debug_assert!(xs.len() <= MAX_LENGTH, "Failed precondition");
166    let mut s = 0;
167    for &x in xs {
168        s = 2 * s + 1 + x as usize;
169    }
170    s
171}
172
173#[test]
174fn encode_ok() {
175    fn test(xs: &[bool], s: usize) {
176        assert_eq!(encode(xs), s, "xs={xs:?}");
177    }
178    test(&[], 0);
179    test(&[false], 1);
180    test(&[true], 2);
181    test(&[false, false], 3);
182    test(&[false, true], 4);
183    test(&[true, false], 5);
184    test(&[true, true], 6);
185    test(&[false, false, false], 7);
186    test(&[false, false, true], 8);
187    test(&[false, true, false], 9);
188    test(&[false, true, true], 10);
189    test(&[true, false, false], 11);
190    test(&[true, false, true], 12);
191    test(&[true, true, false], 13);
192    test(&[true, true, true], 14);
193}