1use crate::{atom::Atom, noun::Noun, Rc};
2use std::{
3 collections::hash_map::DefaultHasher,
4 fmt::{Display, Error, Formatter},
5 hash::{Hash, Hasher},
6 mem::MaybeUninit,
7};
8
9pub mod axes {
10 pub fn cap(axis: usize) -> usize {
11 match axis {
12 0 => panic!("axis 0 is invalid"),
13 1 => panic!("axis 1 is invalid"),
14 2 => 2,
15 3 => 3,
16 _ => cap(axis / 2),
17 }
18 }
19
20 pub fn mas(axis: usize) -> usize {
21 match axis {
22 0 | 1 => panic!("axis 0 or 1 is invalid"),
23 2 | 3 => 1,
24 _ => {
25 let recur = mas(axis / 2);
26 (axis % 2) + (recur * 2)
27 }
28 }
29 }
30 pub fn peg(a: usize, b: usize) -> usize {
31 if a == 0 || b == 0 {
32 panic!("axis 0 is invalid");
33 }
34 match b {
35 1 => a,
36 2 => 2 * a,
37 3 => 2 * a + 1,
38 _ => {
39 let recur = peg(a, b / 2);
40 (b % 2) + (recur * 2)
41 }
42 }
43 }
44}
45
46#[derive(Clone, Debug, Eq, Hash, PartialEq)]
74pub struct Cell {
75 head: Rc<Noun>,
76 tail: Rc<Noun>,
77}
78
79impl Cell {
80 fn new(head: Rc<Noun>, tail: Rc<Noun>) -> Self {
82 Self { head, tail }
83 }
84
85 pub fn head(&self) -> Rc<Noun> {
87 self.head.clone()
88 }
89
90 pub fn head_ref(&self) -> &Noun {
92 &self.head
93 }
94
95 pub fn tail(&self) -> Rc<Noun> {
97 self.tail.clone()
98 }
99
100 pub fn tail_ref(&self) -> &Noun {
102 &self.tail
103 }
104
105 pub fn hash(&self) -> u64 {
107 let mut hasher = DefaultHasher::new();
108 hasher.write_u64((*self.head()).hash());
109 hasher.write_u64((*self.tail()).hash());
110 hasher.finish()
111 }
112
113 pub fn to_array<const N: usize>(&self) -> Option<[Rc<Noun>; N]> {
138 debug_assert!(N >= 2);
139 let mut nouns: [MaybeUninit<Rc<Noun>>; N] = unsafe { MaybeUninit::uninit().assume_init() };
141 nouns[0] = MaybeUninit::new(self.head());
142 let mut noun = self.tail();
143 for (i, n) in nouns.iter_mut().enumerate().take(N).skip(1) {
144 match *noun {
145 Noun::Atom(_) if i < N - 1 => return None,
146 Noun::Cell(ref cell) if i < N - 1 => {
147 *n = MaybeUninit::new(cell.head());
148 noun = cell.tail();
149 }
150 _ => *n = MaybeUninit::new(noun.clone()),
151 }
152 }
153 let nouns = unsafe { nouns.as_ptr().cast::<[Rc<Noun>; N]>().read() };
156 Some(nouns)
157 }
158
159 pub fn to_vec(&self) -> Vec<Rc<Noun>> {
183 let mut nouns = Vec::new();
184 nouns.push(self.head());
185 let mut noun = self.tail();
186 while let Noun::Cell(cell) = &*noun {
187 nouns.push(cell.head());
188 noun = cell.tail();
189 }
190 nouns.push(noun);
191 nouns
192 }
193
194 pub fn into_parts(self) -> (Rc<Noun>, Rc<Noun>) {
196 (self.head, self.tail)
197 }
198
199 pub fn as_noun(&self) -> Noun {
200 Noun::Cell(self.clone())
201 }
202
203 pub fn into_noun(self) -> Noun {
204 Noun::Cell(self)
205 }
206
207 pub fn in_rc(&self) -> Rc<Noun> {
208 Rc::new(self.as_noun())
209 }
210 pub fn slot(&self, axis: usize) -> Option<Rc<Noun>> {
225 match axis {
226 0 => None,
227 1 => Some(Rc::new(self.to_owned().as_noun())),
228 _ => {
229 let nex = axes::cap(axis);
230 let mas = axes::mas(axis);
231 println!("nex: {}", nex);
232 println!("mas: {}", mas);
233 match nex {
234 2 => {
235 let res = self.head();
236 if mas == 1 {
237 Some(res)
238 } else {
239 res.as_cell().and_then(|c| c.slot(mas))
240 }
241 }
242 3 => {
243 let res = self.tail();
244 if mas == 1 {
245 Some(res)
246 } else {
247 res.as_cell().and_then(|c| c.slot(mas))
248 }
249 }
250 _ => panic!("axis {} is invalid", axis),
251 }
252 }
253 }
254 }
255}
256
257impl Display for Cell {
258 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
259 write!(f, "[")?;
263 match (&*self.head(), &*self.tail()) {
264 (head, Noun::Atom(tail)) => write!(f, "{} {}", head, tail)?,
265 (head, _) => {
266 write!(f, "{} ", head)?;
267 let mut tail = self.tail();
268 while let Noun::Cell(cell) = &*tail {
269 write!(f, "{} ", cell.head())?;
270 tail = cell.tail();
271 }
272 write!(f, "{}", tail)?;
273 }
274 }
275 write!(f, "]")
276 }
277}
278
279macro_rules! cell_from_array {
281 ($array:expr) => {{
282 debug_assert!($array.len() >= 2);
283 let (mut remaining, pair) = $array.split_at($array.len() - 2);
284 let mut cell = {
285 let head: &Rc<Noun> = &pair[0];
286 let tail: &Rc<Noun> = &pair[1];
287 Cell::new(head.clone(), tail.clone())
288 };
289 while !remaining.is_empty() {
290 let split = remaining.split_at(remaining.len() - 1);
291 remaining = split.0;
292 let single = split.1;
293 cell = Cell::new(single[0].clone(), Rc::new(Noun::from(cell)));
294 }
295 cell
296 }};
297}
298
299macro_rules! impl_from_array_for_cell {
300 (n = $n:expr) => {
301 impl_from_array_for_cell!([Atom; $n]);
302 impl_from_array_for_cell!([Cell; $n]);
303 impl_from_array_for_cell!([Noun; $n]);
304 impl_from_array_for_cell!([Rc<Noun>; $n]);
305 impl_from_array_for_cell!([&str; $n]);
306 impl_from_array_for_cell!([String; $n]);
307 impl_from_array_for_cell!([u8; $n]);
308 impl_from_array_for_cell!([u16; $n]);
309 impl_from_array_for_cell!([u32; $n]);
310 impl_from_array_for_cell!([u64; $n]);
311 impl_from_array_for_cell!([u128; $n]);
312 impl_from_array_for_cell!([usize; $n]);
313 impl_from_array_for_cell!([Vec<u8>; $n]);
314 };
315 ([Atom; $len:expr]) => {
316 impl From<[Atom; $len]> for Cell {
317 fn from(atoms: [Atom; $len]) -> Self {
318 let atoms = atoms.map(|a| Rc::new(Noun::from(a)));
319 cell_from_array!(atoms)
320 }
321 }
322 };
323 ([Cell; $len:expr]) => {
324 impl From<[Cell; $len]> for Cell {
325 fn from(cells: [Self; $len]) -> Self {
326 let cells = cells.map(|c| Rc::new(Noun::from(c)));
327 cell_from_array!(cells)
328 }
329 }
330 };
331 ([Noun; $len:expr]) => {
332 impl From<[Noun; $len]> for Cell {
333 fn from(nouns: [Noun; $len]) -> Self {
334 let nouns = nouns.map(|n| Rc::new(n));
335 cell_from_array!(nouns)
336 }
337 }
338 };
339 ([Rc<Noun>; $len:expr]) => {
340 impl From<[Rc<Noun>; $len]> for Cell {
341 fn from(nouns: [Rc<Noun>; $len]) -> Self {
342 cell_from_array!(nouns)
343 }
344 }
345 };
346 ([$atom_src:ty; $len:expr]) => {
347 impl From<[$atom_src; $len]> for Cell {
348 fn from(atom_srcs: [$atom_src; $len]) -> Self {
349 let atom_srcs = atom_srcs.map(|a| Rc::new(Noun::from(Atom::from(a))));
350 cell_from_array!(atom_srcs)
351 }
352 }
353 };
354}
355
356impl_from_array_for_cell!(n = 2);
357impl_from_array_for_cell!(n = 3);
358impl_from_array_for_cell!(n = 4);
359impl_from_array_for_cell!(n = 5);
360impl_from_array_for_cell!(n = 6);
361impl_from_array_for_cell!(n = 7);
362impl_from_array_for_cell!(n = 8);
363impl_from_array_for_cell!(n = 9);
364impl_from_array_for_cell!(n = 10);
365impl_from_array_for_cell!(n = 11);
366impl_from_array_for_cell!(n = 12);
367impl_from_array_for_cell!(n = 13);
368impl_from_array_for_cell!(n = 14);
369impl_from_array_for_cell!(n = 15);
370impl_from_array_for_cell!(n = 16);
371impl_from_array_for_cell!(n = 17);
372impl_from_array_for_cell!(n = 18);
373impl_from_array_for_cell!(n = 19);
374impl_from_array_for_cell!(n = 20);
375impl_from_array_for_cell!(n = 21);
376impl_from_array_for_cell!(n = 22);
377impl_from_array_for_cell!(n = 23);
378impl_from_array_for_cell!(n = 24);
379impl_from_array_for_cell!(n = 25);
380impl_from_array_for_cell!(n = 26);
381impl_from_array_for_cell!(n = 27);
382impl_from_array_for_cell!(n = 28);
383impl_from_array_for_cell!(n = 29);
384impl_from_array_for_cell!(n = 30);
385
386impl From<Vec<Rc<Noun>>> for Cell {
387 fn from(nouns: Vec<Rc<Noun>>) -> Self {
388 cell_from_array!(nouns)
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use super::*;
395
396 #[test]
397 fn to_array() {
398 {
399 let cell = Cell::from([
400 Noun::from(Atom::from("request")),
401 Noun::from(Atom::from(0u8)),
402 Noun::from(Atom::from("POST")),
403 Noun::from(Atom::from("http://eth-mainnet.urbit.org:8545")),
404 Noun::from(Cell::from([
405 Noun::from(Cell::from([
406 Atom::from("Content-Type"),
407 Atom::from("application/json"),
408 ])),
409 Noun::from(Atom::from(0u8)),
410 ])),
411 Noun::from(Atom::from(0u8)),
412 Noun::from(Atom::from(78u8)),
413 Noun::from(Atom::from(
414 r#"[{"params":[],"id":"block number","jsonrpc":"2.0","method":"eth_blockNumber"}]"#,
415 )),
416 ]);
417 let [tag, req_num, method, uri, headers, body] = cell.to_array::<6>().expect("as list");
418 if let (Noun::Atom(tag), Noun::Atom(req_num), Noun::Atom(method), Noun::Atom(uri)) =
419 (&*tag, &*req_num, &*method, &*uri)
420 {
421 assert_eq!(tag, "request");
422 assert_eq!(*req_num, 0u8);
423 assert_eq!(method, "POST");
424 assert_eq!(uri, "http://eth-mainnet.urbit.org:8545");
425 } else {
426 panic!("unexpected cell");
427 }
428 if let Noun::Cell(headers) = &*headers {
429 if let Noun::Cell(header) = &*headers.head() {
430 if let (Noun::Atom(key), Noun::Atom(val)) = (&*header.head(), &*header.tail()) {
431 assert_eq!(key, "Content-Type");
432 assert_eq!(val, "application/json");
433 } else {
434 panic!("unexpected cell");
435 }
436 } else {
437 panic!("unexpected atom");
438 }
439 if let Noun::Atom(null) = &*headers.tail() {
440 assert_eq!(*null, 0u8);
441 } else {
442 panic!("unexpected cell");
443 }
444 } else {
445 panic!("unexpected atom");
446 }
447 if let Noun::Cell(body) = &*body {
448 if let Noun::Atom(null) = &*body.head() {
449 assert_eq!(*null, 0u8);
450 } else {
451 panic!("unexpected cell");
452 }
453 if let Noun::Cell(body) = &*body.tail() {
454 if let (Noun::Atom(body_len), Noun::Atom(body)) = (&*body.head(), &*body.tail())
455 {
456 assert_eq!(*body_len, 78u8);
457 assert_eq!(
458 body,
459 r#"[{"params":[],"id":"block number","jsonrpc":"2.0","method":"eth_blockNumber"}]"#
460 );
461 } else {
462 panic!("unexpected cell");
463 }
464 } else {
465 panic!("unexpected atom");
466 }
467 } else {
468 panic!("unexpected atom");
469 }
470 }
471 }
472
473 #[test]
474 fn from_vec() {
475 {
476 let _0 = Rc::<Noun>::from(Atom::from(0u8));
477 let _2 = Rc::<Noun>::from(Atom::from(2u8));
478 let _8 = Rc::<Noun>::from(Atom::from(8u8));
479 let _32 = Rc::<Noun>::from(Atom::from(32u8));
480 let _128 = Rc::<Noun>::from(Atom::from(128u8));
481 let cell = Cell::from(vec![
482 _0.clone(),
483 _2.clone(),
484 _8.clone(),
485 _32.clone(),
486 _128.clone(),
487 ]);
488
489 let [a, b, c, d, e] = cell.to_array::<5>().expect("cell to array");
490 assert_eq!(a, _0);
491 assert_eq!(b, _2);
492 assert_eq!(c, _8);
493 assert_eq!(d, _32);
494 assert_eq!(e, _128);
495 }
496 }
497}