1use etk_ops::Immediate;
2
3use num_bigint::{BigInt, Sign};
4
5use snafu::{Backtrace, Snafu};
6
7use std::convert::TryFrom;
8use std::fmt::{self, Debug};
9
10use super::expression::{Expression, Terminal};
11use super::macros::ExpressionMacroInvocation;
12
13#[derive(Snafu, Debug)]
15#[snafu(context(suffix(Context)))]
16pub struct TryFromSliceError {
17 backtrace: Backtrace,
18}
19
20impl From<std::convert::Infallible> for TryFromSliceError {
21 fn from(e: std::convert::Infallible) -> Self {
22 match e {}
23 }
24}
25
26#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
28pub struct Imm {
29 pub tree: Expression,
31}
32
33impl Imm {
34 pub fn with_label<S: Into<String>>(s: S) -> Self {
36 Terminal::Label(s.into()).into()
37 }
38
39 pub fn with_variable<S: Into<String>>(s: S) -> Self {
41 Terminal::Variable(s.into()).into()
42 }
43
44 pub fn with_expression(e: Expression) -> Self {
46 e.into()
47 }
48
49 pub fn with_macro(m: ExpressionMacroInvocation) -> Self {
51 Expression::Macro(m).into()
52 }
53}
54
55impl From<Vec<u8>> for Imm {
56 fn from(konst: Vec<u8>) -> Self {
57 Imm::from(Terminal::Number(BigInt::from_bytes_be(Sign::Plus, &konst)))
58 }
59}
60
61impl fmt::Display for Imm {
62 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
63 write!(f, "{}", self.tree)
64 }
65}
66
67macro_rules! impl_from {
68 ($ii:literal;) => {
69 impl From<[u8; $ii]> for Imm {
70 fn from(konst: [u8; $ii]) -> Self {
71 Imm::from(Terminal::Number(BigInt::from_bytes_be(
72 Sign::Plus,
73 &konst,
74 )))
75 }
76 }
77 };
78
79 ($ii:literal; $ty:ty $(, $rest:ty)* $(,)*) => {
80 impl From<$ty> for Imm {
81 fn from(x: $ty) -> Self {
82 Imm::from(Terminal::Number(x.into()))
83 }
84 }
85
86 impl_from!($ii; $($rest,)*);
87 }
88}
89
90macro_rules! impl_try_from_slice {
91 ($ii:literal) => {
92 impl TryFrom<&[u8]> for Imm {
93 type Error = TryFromSliceError;
94
95 fn try_from(x: &[u8]) -> Result<Self, Self::Error> {
96 if x.len() > $ii {
97 return TryFromSliceContext.fail();
98 }
99
100 Ok(Imm::from(Terminal::Number(BigInt::from_bytes_be(
101 Sign::Plus,
102 x,
103 ))))
104 }
105 }
106 };
107}
108
109impl_from!(1;);
110impl_from!(2;);
111impl_from!(3;);
112impl_from!(4;);
113impl_from!(5;);
114impl_from!(6;);
115impl_from!(7;);
116impl_from!(8;);
117impl_from!(9;);
118impl_from!(10;);
119impl_from!(11;);
120impl_from!(12;);
121impl_from!(13;);
122impl_from!(14;);
123impl_from!(15;);
124impl_from!(16;);
125impl_from!(17;);
126impl_from!(18;);
127impl_from!(19;);
128impl_from!(20;);
129impl_from!(21;);
130impl_from!(22;);
131impl_from!(23;);
132impl_from!(24;);
133impl_from!(25;);
134impl_from!(26;);
135impl_from!(27;);
136impl_from!(28;);
137impl_from!(29;);
138impl_from!(30;);
139impl_from!(31;);
140impl_from!(32; u8, u16, u32, u64, u128);
141
142impl_try_from_slice!(32);
143
144impl From<Expression> for Imm {
145 fn from(tree: Expression) -> Self {
146 Self { tree }
147 }
148}
149
150impl From<Terminal> for Imm {
151 fn from(terminal: Terminal) -> Self {
152 Expression::Terminal(terminal).into()
153 }
154}
155
156impl<const N: usize> Immediate<N> for Imm {}