Skip to content

Commit c369040

Browse files
authored
Merge pull request #20 from programble/nonzero
Use NonZeroUsize inside NodeId
2 parents 1f26cae + dac8df3 commit c369040

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

src/iter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,15 @@ impl<'a, T: 'a> ExactSizeIterator for Nodes<'a, T> { }
8080
impl<'a, T: 'a> Iterator for Nodes<'a, T> {
8181
type Item = NodeRef<'a, T>;
8282
fn next(&mut self) -> Option<Self::Item> {
83-
self.iter.next().map(|i| unsafe { self.tree.get_unchecked(NodeId(i)) })
83+
self.iter.next().map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) })
8484
}
8585
fn size_hint(&self) -> (usize, Option<usize>) {
8686
self.iter.size_hint()
8787
}
8888
}
8989
impl<'a, T: 'a> DoubleEndedIterator for Nodes<'a, T> {
9090
fn next_back(&mut self) -> Option<Self::Item> {
91-
self.iter.next_back().map(|i| unsafe { self.tree.get_unchecked(NodeId(i)) })
91+
self.iter.next_back().map(|i| unsafe { self.tree.get_unchecked(NodeId::from_index(i)) })
9292
}
9393
}
9494

src/lib.rs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
)]
3737

3838
use std::fmt::{self, Debug, Formatter};
39+
use std::num::NonZeroUsize;
3940

4041
/// Vec-backed ID-tree.
4142
///
@@ -49,7 +50,20 @@ pub struct Tree<T> {
4950
///
5051
/// Index into a `Tree`-internal `Vec`.
5152
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
52-
pub struct NodeId(usize);
53+
pub struct NodeId(NonZeroUsize);
54+
55+
impl NodeId {
56+
// Safety: `n` must not equal `usize::MAX`.
57+
// (This is never the case for `Vec::len()`, that would mean it owns
58+
// the entire address space without leaving space for even the its pointer.)
59+
unsafe fn from_index(n: usize) -> Self {
60+
NodeId(NonZeroUsize::new_unchecked(n + 1))
61+
}
62+
63+
fn to_index(self) -> usize {
64+
self.0.get() - 1
65+
}
66+
}
5367

5468
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
5569
struct Node<T> {
@@ -60,6 +74,13 @@ struct Node<T> {
6074
value: T,
6175
}
6276

77+
fn _static_assert_size_of_node() {
78+
// "Instanciating" the generic `transmute` function without calling it
79+
// still triggers the magic compile-time check
80+
// that input and output types have the same `size_of()`.
81+
let _ = std::mem::transmute::<Node<()>, [usize; 5]>;
82+
}
83+
6384
impl<T> Node<T> {
6485
fn new(value: T) -> Self {
6586
Node {
@@ -125,21 +146,21 @@ impl<T> Tree<T> {
125146

126147
/// Returns a reference to the specified node.
127148
pub fn get(&self, id: NodeId) -> Option<NodeRef<T>> {
128-
self.vec.get(id.0).map(|node| NodeRef { id, node, tree: self })
149+
self.vec.get(id.to_index()).map(|node| NodeRef { id, node, tree: self })
129150
}
130151

131152
/// Returns a mutator of the specified node.
132153
pub fn get_mut(&mut self, id: NodeId) -> Option<NodeMut<T>> {
133-
let exists = self.vec.get(id.0).map(|_| ());
154+
let exists = self.vec.get(id.to_index()).map(|_| ());
134155
exists.map(move |_| NodeMut { id, tree: self })
135156
}
136157

137158
unsafe fn node(&self, id: NodeId) -> &Node<T> {
138-
self.vec.get_unchecked(id.0)
159+
self.vec.get_unchecked(id.to_index())
139160
}
140161

141162
unsafe fn node_mut(&mut self, id: NodeId) -> &mut Node<T> {
142-
self.vec.get_unchecked_mut(id.0)
163+
self.vec.get_unchecked_mut(id.to_index())
143164
}
144165

145166
/// Returns a reference to the specified node.
@@ -154,17 +175,17 @@ impl<T> Tree<T> {
154175

155176
/// Returns a reference to the root node.
156177
pub fn root(&self) -> NodeRef<T> {
157-
unsafe { self.get_unchecked(NodeId(0)) }
178+
unsafe { self.get_unchecked(NodeId::from_index(0)) }
158179
}
159180

160181
/// Returns a mutator of the root node.
161182
pub fn root_mut(&mut self) -> NodeMut<T> {
162-
unsafe { self.get_unchecked_mut(NodeId(0)) }
183+
unsafe { self.get_unchecked_mut(NodeId::from_index(0)) }
163184
}
164185

165186
/// Creates an orphan node.
166187
pub fn orphan(&mut self, value: T) -> NodeMut<T> {
167-
let id = NodeId(self.vec.len());
188+
let id = unsafe { NodeId::from_index(self.vec.len()) };
168189
self.vec.push(Node::new(value));
169190
unsafe { self.get_unchecked_mut(id) }
170191
}

0 commit comments

Comments
 (0)