1use core::fmt;
2use core::fmt::Write as FmtWrite;
3use core::ops::Deref;
4use core::cell::RefCell;
5use core::cell::BorrowError;
6use core::cell::BorrowMutError;
7use core::convert::TryInto;
8
9use crate::ExecutionContext;
10use crate::mm::AllocatorRef;
11use crate::mm::AllocError;
12use crate::mm::Rc;
13use crate::mm::Vector;
14use crate::io::IOError;
15use crate::io::IOPartialError;
16use crate::io::ErrorCode;
17use crate::io::stream::Write;
18use crate::io::stream::SeekFrom;
19use crate::io::stream::Stream;
20use crate::num::fmt as num_fmt;
21
22pub mod expr;
23pub mod eval;
24pub mod content_stream;
25
26#[derive(Debug, PartialEq)]
28pub enum Error<'e> {
29 NotApplicable,
30 Alloc(AllocError),
31 IO(IOError<'e>),
32 Output(IOError<'e>), CellUnavailable, }
35
36impl fmt::Display for Error<'_> {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 Error::NotApplicable => "not applicable".fmt(f),
40 Error::CellUnavailable => "data unavailable due to internal state".fmt(f),
41 Error::Alloc(v) => write!(f, "allocation error ({})", v),
42 Error::IO(v) => write!(f, "I/O error ({})", v),
43 Error::Output(v) => write!(f, "reporting output error ({})", v),
44 }
45 }
46}
47
48impl From<fmt::Error> for Error<'_> {
49 fn from (_: fmt::Error) -> Self {
50 Error::Output(
51 IOError::with_str(
52 ErrorCode::Unsuccessful,
53 "error formatting output"))
54 }
55}
56
57impl From<BorrowError> for Error<'_> {
58 fn from(_: BorrowError) -> Self {
59 Error::CellUnavailable
60 }
61}
62
63impl From<BorrowMutError> for Error<'_> {
64 fn from(_: BorrowMutError) -> Self {
65 Error::CellUnavailable
66 }
67}
68
69impl From<AllocError> for Error<'_> {
70 fn from(e: AllocError) -> Self {
71 Error::Alloc(e)
72 }
73}
74
75impl<T> From<(AllocError, T)> for Error<'_> {
76 fn from(e: (AllocError, T)) -> Self {
77 Error::Alloc(e.0)
78 }
79}
80
81impl<'a> From<IOPartialError<'a>> for Error<'a> {
82 fn from(src: IOPartialError<'a>) -> Self {
83 Error::IO(src.to_error())
84 }
85}
86
87impl<'a> From<IOError<'a>> for Error<'a> {
88 fn from(src: IOError<'a>) -> Self {
89 Error::IO(src)
90 }
91}
92
93pub fn output_byte_slice_as_human_readable_text<'w, 'x>(
94 data: &[u8],
95 out: &mut (dyn Write + 'w),
96 _xc: &mut ExecutionContext<'x>
97) -> Result<(), Error<'x>> {
98 for &b in data {
99 if b == 0x22 || b == 0x5C {
100 write!(out, "\\{}", b as char)?;
101 } else if b >= 0x20_u8 && b <= 0x7E_u8 {
102 write!(out, "{}", b as char)?;
103 } else {
104 write!(out, "\\x{:02X}", b)?;
105 }
106 }
107 Ok(())
108}
109
110pub trait DataCellOpsMut: fmt::Debug {
112
113 fn get_property_mut<'x>(
114 &mut self,
115 _property_name: &str,
116 _xc: &mut ExecutionContext<'x>,
117 ) -> Result<DataCell<'x>, Error<'x>> {
118 Err(Error::NotApplicable)
119 }
120
121 fn output_as_human_readable_mut<'w, 'x>(
122 &mut self,
123 _out: &mut (dyn Write + 'w),
124 _xc: &mut ExecutionContext<'x>,
125 ) -> Result<(), Error<'x>> {
126 Err(Error::NotApplicable)
127 }
128
129}
130
131pub trait DataCellOps: fmt::Debug {
133
134 fn get_property<'x>(
135 &self,
136 _property_name: &str,
137 _xc: &mut ExecutionContext<'x>,
138 ) -> Result<DataCell<'x>, Error<'x>> {
139 Err(Error::NotApplicable)
140 }
141
142 fn output_as_human_readable<'w, 'x>(
143 &self,
144 _out: &mut (dyn Write + 'w),
145 _xc: &mut ExecutionContext<'x>,
146 ) -> Result<(), Error<'x>> {
147 Err(Error::NotApplicable)
148 }
149
150}
151
152impl<T> DataCellOps for RefCell<T>
153where T: DataCellOpsMut {
154
155 fn get_property<'x>(
156 &self,
157 property_name: &str,
158 xc: &mut ExecutionContext<'x>,
159 ) -> Result<DataCell<'x>, Error<'x>> {
160 let mut c = self.try_borrow_mut()?;
161 c.get_property_mut(property_name, xc)
162 }
163
164 fn output_as_human_readable<'w, 'x>(
165 &self,
166 out: &mut (dyn Write + 'w),
167 xc: &mut ExecutionContext<'x>,
168 ) -> Result<(), Error<'x>> {
169 let mut c = self.try_borrow_mut()?;
170 c.output_as_human_readable_mut(out, xc)
171 }
172
173}
174
175impl<'a, T> DataCellOps for Rc<'a, T>
176where T: DataCellOps {
177
178 fn get_property<'x>(
179 &self,
180 property_name: &str,
181 xc: &mut ExecutionContext<'x>,
182 ) -> Result<DataCell<'x>, Error<'x>> {
183 let c = self.as_ref();
184 c.get_property(property_name, xc)
185 }
186
187 fn output_as_human_readable<'w, 'x>(
188 &self,
189 out: &mut (dyn Write + 'w),
190 xc: &mut ExecutionContext<'x>,
191 ) -> Result<(), Error<'x>> {
192 let c = self.as_ref();
193 c.output_as_human_readable(out, xc)
194 }
195
196}
197
198#[derive(Debug)]
200pub struct U64Cell {
201 pub n: u64,
202 pub fmt_pack: num_fmt::MiniNumFmtPack,
203}
204
205impl U64Cell {
206
207 pub fn new(n: u64) -> Self {
208 let fmt_pack = num_fmt::MiniNumFmtPack::default();
209 U64Cell { n, fmt_pack }
210 }
211 pub fn with_fmt(n: u64, fmt_pack: num_fmt::MiniNumFmtPack) -> Self {
212 U64Cell { n, fmt_pack }
213 }
214 pub fn hex(n: u64) -> Self {
215 let fmt_pack = num_fmt::MiniNumFmtPack::new(
216 num_fmt::Radix::new(16).unwrap(),
217 num_fmt::RadixNotation::DefaultPrefix,
218 num_fmt::MinDigitCount::new(2).unwrap(),
219 num_fmt::PositiveSign::Hidden,
220 num_fmt::ZeroSign::Hidden);
221 U64Cell::with_fmt(n, fmt_pack)
222 }
223}
224
225impl DataCellOps for U64Cell {
226
227 fn output_as_human_readable<'w, 'x>(
228 &self,
229 w: &mut (dyn Write + 'w),
230 xc: &mut ExecutionContext<'x>,
231 ) -> Result<(), Error<'x>> {
232 let mut buf = [0_u8; 256];
233 w.write_all(
234 self.fmt_pack.int_fmt(self.n, &mut buf).unwrap().as_bytes(),
235 xc
236 ).map_err(|e| Error::Output(e.to_error()))
237 }
238
239}
240
241#[derive(Debug)]
243pub struct ByteVector<'a>(pub Vector<'a, u8>);
244
245impl<'a> ByteVector<'a> {
246 pub fn from_byte_slice(
247 allocator: AllocatorRef<'a>,
248 data: &[u8]
249 ) -> Result<Self, AllocError> {
250 Vector::from_slice(data, allocator).map(|bv| ByteVector(bv))
251 }
252
253}
254impl<'a> DataCellOpsMut for ByteVector<'a> {
255
256 fn get_property_mut<'x>(
257 &mut self,
258 property_name: &str,
259 _xc: &mut ExecutionContext<'x>,
260 ) -> Result<DataCell<'x>, Error<'x>> {
261 match property_name {
262 "len" | "length" | "count" | "size" => {
263 let v = self.0.len().try_into().unwrap();
264 Ok(DataCell::U64(U64Cell::new(v)))
265 },
266 _ => Err(Error::NotApplicable)
267 }
268 }
269
270 fn output_as_human_readable_mut<'w, 'x>(
271 &mut self,
272 out: &mut (dyn Write + 'w),
273 xc: &mut ExecutionContext<'x>,
274 ) -> Result<(), Error<'x>> {
275 write!(out, "b\"")?;
276 output_byte_slice_as_human_readable_text(self.0.as_slice(), out, xc)?;
277 write!(out, "\"")?;
278 Ok(())
279 }
280
281}
282
283#[derive(Debug)]
285pub struct DCOVector<'a, T: DataCellOps>(pub Vector<'a, T>);
286
287impl<'a, T: DataCellOps> DataCellOpsMut for DCOVector<'a, T> {
288
289 fn get_property_mut<'x>(
290 &mut self,
291 property_name: &str,
292 _xc: &mut ExecutionContext<'x>,
293 ) -> Result<DataCell<'x>, Error<'x>> {
294 match property_name {
295 "len" | "length" | "count" => {
296 let v = self.0.len().try_into().unwrap();
297 Ok(DataCell::U64(U64Cell::new(v)))
298 },
299 _ => Err(Error::NotApplicable)
300 }
301 }
302
303 fn output_as_human_readable_mut<'w, 'x>(
304 &mut self,
305 out: &mut (dyn Write + 'w),
306 xc: &mut ExecutionContext<'x>,
307 ) -> Result<(), Error<'x>> {
308 write!(out, "[")?;
309 for cell in self.0.as_slice() {
310 cell.output_as_human_readable(out, xc)?;
311 }
312 write!(out, "]")?;
313 Ok(())
314 }
315
316}
317
318#[derive(Debug)]
320pub struct RecordDesc<'a> {
321 field_names: &'a [&'a str],
322 record_name: &'a str,
323}
324
325impl<'a> RecordDesc<'a> {
326
327 pub const fn new(
328 record_name: &'a str,
329 field_names: &'a [&'a str],
330 ) -> RecordDesc<'a> {
331 RecordDesc { field_names, record_name }
332 }
333
334 pub fn field_count(&self) -> usize {
335 self.field_names.len()
336 }
337
338 pub fn field_index(&self, name: &str) -> Option<usize> {
339 for (i, n) in self.field_names.iter().enumerate() {
340 if *n == name {
341 return Some(i);
342 }
343 }
344 None
345 }
346}
347
348#[derive(Debug)]
349pub struct Record<'a> {
350 data: Vector<'a, DataCell<'a>>,
351 desc: &'a RecordDesc<'a>,
352}
353
354impl<'a> Record<'a> {
355
356 pub fn new(
357 desc: &'a RecordDesc<'a>,
358 allocator: AllocatorRef<'a>,
359 ) -> Result<Self, AllocError> {
360 let mut data: Vector<'a, DataCell<'a>> = Vector::new(allocator);
361 let n = desc.field_count();
362 data.reserve(n)?;
363 for _i in 0..n {
364 data.push(DataCell::Nothing).unwrap();
365 }
366 Ok(Record { data, desc })
367 }
368
369 pub fn get_fields_mut<'b>(&'b mut self) -> &'b mut [DataCell<'a>] {
370 self.data.as_mut_slice()
371 }
372
373 pub fn set_field(&mut self, name: &str, value: DataCell<'a>) {
374 self.data.as_mut_slice()[self.desc.field_index(name).unwrap()] = value;
375 }
376}
377
378impl<'a> DataCellOpsMut for Record<'a> {
379
380 fn get_property_mut<'x>(
381 &mut self,
382 _property_name: &str,
383 _xc: &mut ExecutionContext<'x>,
384 ) -> Result<DataCell<'x>, Error<'x>> {
385 Err(Error::NotApplicable)
386 }
387
388 fn output_as_human_readable_mut<'w, 'x>(
389 &mut self,
390 out: &mut (dyn Write + 'w),
391 xc: &mut ExecutionContext<'x>,
392 ) -> Result<(), Error<'x>> {
393 out.write_all(self.desc.record_name.as_bytes(), xc)?;
394 out.write_all(b"(", xc)?;
395 let v = self.data.as_slice();
396 let mut first = true;
397 for i in 0..self.desc.field_names.len() {
398 if v[i].is_nothing() { continue; }
399 if first {
400 first = false;
401 } else {
402 out.write_all(b", ", xc)?;
403 }
404 out.write_all(self.desc.field_names[i].as_bytes(), xc)?;
405 out.write_all(b": ", xc)?;
406 v[i].output_as_human_readable(out, xc)?;
407 }
408 out.write_all(b")", xc)?;
409 Ok(())
410 }
411}
412
413#[derive(Debug)]
415pub enum DataCell<'d> {
416 Nothing,
417 U64(U64Cell),
418 ByteVector(Rc<'d, RefCell<ByteVector<'d>>>),
419 StaticId(&'d str),
420 Dyn(Rc<'d, dyn DataCellOps + 'd>),
421 CellVector(Rc<'d, RefCell<DCOVector<'d, DataCell<'d>>>>),
422 Record(Rc<'d, RefCell<Record<'d>>>),
423 ByteStream(Rc<'d, RefCell<dyn Stream + 'd>>),
424}
425
426impl<'d> DataCell<'d> {
427
428 pub fn is_nothing(&self) -> bool {
429 match self {
430 DataCell::Nothing => true,
431 _ => false
432 }
433 }
434
435 pub fn new() -> Self {
436 DataCell::Nothing
437 }
438
439 pub fn from_u64_cell(n: U64Cell) -> Self {
440 DataCell::U64(n)
441 }
442 pub fn from_u64(n: u64) -> Self {
443 Self::from_u64_cell(U64Cell::new(n))
444 }
445
446 pub fn from_static_id(s: &'d str) -> Self {
447 DataCell::StaticId(s)
448 }
449
450 pub fn from_byte_slice(
451 allocator: AllocatorRef<'d>,
452 data: &[u8],
453 ) -> Result<Self, AllocError> {
454 Ok(DataCell::ByteVector(Rc::new(allocator, RefCell::new(ByteVector::from_byte_slice(allocator, data)?))?))
455 }
456}
457
458impl<'d> DataCellOps for DataCell<'d> {
459
460 fn get_property<'x>(
461 &self,
462 property_name: &str,
463 xc: &mut ExecutionContext<'x>,
464 ) -> Result<DataCell<'x>, Error<'x>> {
465 match self {
466 DataCell::U64(v) => v.get_property(property_name, xc),
467 DataCell::ByteVector(v) => v.get_property(property_name, xc),
468 DataCell::CellVector(v) => v.get_property(property_name, xc),
469 DataCell::Dyn(o) => o.get_property(property_name, xc),
470 _ => Err(Error::NotApplicable)
471 }
472 }
473
474 fn output_as_human_readable<'w, 'x>(
475 &self,
476 w: &mut (dyn Write + 'w),
477 xc: &mut ExecutionContext<'x>,
478 ) -> Result<(), Error<'x>> {
479 match self {
480 DataCell::Nothing => Ok(()),
481 DataCell::U64(v) => v.output_as_human_readable(w, xc),
482 DataCell::ByteVector(v) => v.output_as_human_readable(w, xc),
483 DataCell::StaticId(s) => {
484 w.write_all(s.as_bytes(), xc)
485 .map_err(|e| Error::Output(e.to_error()))
486 },
487 DataCell::Dyn(v) => v.deref().output_as_human_readable(w, xc),
488 DataCell::CellVector(v) => v.deref().output_as_human_readable(w, xc),
489 DataCell::Record(v) => v.deref().output_as_human_readable(w, xc),
490 DataCell::ByteStream(_v) => panic!(),
491 }
492 }
493
494}
495
496impl<T: Stream> DataCellOpsMut for T {
497
498 fn get_property_mut<'x>(
499 &mut self,
500 _property_name: &str,
501 _xc: &mut ExecutionContext<'x>,
502 ) -> Result<DataCell<'x>, Error<'x>> {
503 Err(Error::NotApplicable)
504 }
505
506 fn output_as_human_readable_mut<'w, 'x>(
507 &mut self,
508 out: &mut (dyn Write + 'w),
509 xc: &mut ExecutionContext<'x>,
510 ) -> Result<(), Error<'x>> {
511 self.seek(SeekFrom::Start(0), xc)?;
512 out.write_all(b"b\"", xc)?;
513 let mut buf = [0_u8; 1024];
514 loop {
515 let chunk_size = self.read_uninterrupted(&mut buf, xc)?;
516 if chunk_size == 0 { break; }
517 output_byte_slice_as_human_readable_text(&buf[0..chunk_size], out, xc)?;
518 }
519 out.write_all(b"\"", xc)?;
520
521 Ok(())
522 }
523
524}
525
526#[cfg(test)]
527mod tests {
528 use super::*;
529
530 #[derive(Debug)]
531 struct Abc();
532 impl fmt::Display for Abc {
533 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
534 write!(f, "<abc>")
535 }
536 }
537 impl DataCellOps for Abc{}
538
539 #[test]
540 fn data_cell_nothing_get_property() {
541 let mut xc = ExecutionContext::nop();
542 assert_eq!(Error::NotApplicable, DataCell::Nothing.get_property("zilch", &mut xc).unwrap_err());
543 }
544
545 #[test]
546 fn default_get_property() {
547 let mut xc = ExecutionContext::nop();
548 assert_eq!(Error::NotApplicable, Abc().get_property("zilch", &mut xc).unwrap_err());
549 }
550
551 #[test]
552 fn record_human_readable() {
553 use crate::mm::{ Allocator, BumpAllocator };
554 let mut buffer = [0_u8; 1000];
555 let a = BumpAllocator::new(&mut buffer);
556 let mut xc = ExecutionContext::with_allocator_and_logless(a.to_ref());
557 let desc = RecordDesc::new("Rectangle", &["width", "height", "mode"]);
558 let mut r = Record::new(&desc, a.to_ref()).unwrap();
559
560 {
561 let mut o = xc.byte_vector();
562 r.output_as_human_readable_mut(&mut o, &mut xc).unwrap();
563 assert_eq!(core::str::from_utf8(o.as_slice()).unwrap(), "Rectangle()");
564 }
565
566 {
567 r.data.as_mut_slice()[1] = DataCell::from_u64(5);
568 let mut o = xc.byte_vector();
569 r.output_as_human_readable_mut(&mut o, &mut xc).unwrap();
570 assert_eq!(core::str::from_utf8(o.as_slice()).unwrap(),
571 "Rectangle(height: 5)");
572 }
573
574 {
575 r.data.as_mut_slice()[1] = DataCell::from_u64(7);
576 r.data.as_mut_slice()[2] = DataCell::from_static_id("FUNKY");
577 let mut o = xc.byte_vector();
578 r.output_as_human_readable_mut(&mut o, &mut xc).unwrap();
579 assert_eq!(core::str::from_utf8(o.as_slice()).unwrap(),
580 "Rectangle(height: 7, mode: FUNKY)");
581 }
582
583 {
584 r.data.as_mut_slice()[0] = DataCell::from_u64(8);
585 r.data.as_mut_slice()[1] = DataCell::new();
586 r.data.as_mut_slice()[2] = DataCell::from_static_id("CHECKERED");
587 let mut o = xc.byte_vector();
588 r.output_as_human_readable_mut(&mut o, &mut xc).unwrap();
589 assert_eq!(core::str::from_utf8(o.as_slice()).unwrap(),
590 "Rectangle(width: 8, mode: CHECKERED)");
591 }
592
593 {
594 r.data.as_mut_slice()[0] = DataCell::from_u64(9);
595 let nf = num_fmt::MiniNumFmtPack::new(
596 num_fmt::Radix::new(16).unwrap(),
597 num_fmt::RadixNotation::DefaultPrefix,
598 num_fmt::MinDigitCount::new(2).unwrap(),
599 num_fmt::PositiveSign::Plus,
600 num_fmt::ZeroSign::Space);
601 r.data.as_mut_slice()[1] = DataCell::from_u64_cell(U64Cell::with_fmt(10, nf));
602 r.data.as_mut_slice()[2] = DataCell::from_static_id("WEIRDO");
603 let mut o = xc.byte_vector();
604 r.output_as_human_readable_mut(&mut o, &mut xc).unwrap();
605 assert_eq!(core::str::from_utf8(o.as_slice()).unwrap(),
606 "Rectangle(width: 9, height: +0x0A, mode: WEIRDO)");
607 }
608 }
609}
610