Skip to content

Commit 826800c

Browse files
author
Grant Wuerker
committed
library2
1 parent fd274c9 commit 826800c

File tree

12 files changed

+1242
-0
lines changed

12 files changed

+1242
-0
lines changed

Diff for: crates/library2/Cargo.toml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "fe-library2"
3+
version = "0.23.0"
4+
authors = ["The Fe Developers <[email protected]>"]
5+
edition = "2021"
6+
license = "Apache-2.0"
7+
repository = "https://github.com/ethereum/fe"
8+
9+
[dependencies]
10+
include_dir = "0.7.2"
11+
common = { path = "../common2", package = "fe-common2" }

Diff for: crates/library2/build.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("cargo:rerun-if-changed=./std");
3+
}

Diff for: crates/library2/src/lib.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::collections::BTreeSet;
2+
3+
pub use ::include_dir;
4+
use common::{
5+
input::{IngotKind, Version},
6+
InputDb, InputFile, InputIngot,
7+
};
8+
use include_dir::{include_dir, Dir};
9+
10+
pub const STD: Dir = include_dir!("$CARGO_MANIFEST_DIR/std");
11+
12+
fn std_src_input_files(db: &mut dyn InputDb, ingot: InputIngot) -> BTreeSet<InputFile> {
13+
static_dir_files(&STD)
14+
.into_iter()
15+
.map(|(path, content)| InputFile::new(db, ingot, path.into(), content.into()))
16+
.collect()
17+
}
18+
19+
pub fn std_lib_input_ingot(db: &mut dyn InputDb) -> InputIngot {
20+
let ingot = InputIngot::new(
21+
db,
22+
"std",
23+
IngotKind::Std,
24+
Version::new(0, 0, 0),
25+
BTreeSet::default(),
26+
);
27+
28+
let input_files = std_src_input_files(db, ingot);
29+
ingot.set_files(db, input_files);
30+
ingot
31+
}
32+
33+
// pub fn std_src_files() -> Vec<(&'static str, &'static str)> {
34+
// static_dir_files(STD.get_dir("src").unwrap())
35+
// }
36+
37+
pub fn static_dir_files(dir: &'static Dir) -> Vec<(&'static str, &'static str)> {
38+
fn add_files(dir: &'static Dir, accum: &mut Vec<(&'static str, &'static str)>) {
39+
accum.extend(dir.files().map(|file| {
40+
(
41+
file.path().to_str().unwrap(),
42+
file.contents_utf8().expect("non-utf8 static file"),
43+
)
44+
}));
45+
46+
for sub_dir in dir.dirs() {
47+
add_files(sub_dir, accum)
48+
}
49+
}
50+
51+
let mut files = vec![];
52+
add_files(dir, &mut files);
53+
files
54+
}

Diff for: crates/library2/std/src/buf.fe

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
use ingot::evm
2+
use ingot::math
3+
4+
unsafe fn avail() -> u256 {
5+
let ptr: u256 = evm::mload(offset: 64)
6+
7+
if ptr == 0x00 {
8+
return 96
9+
} else {
10+
return ptr
11+
}
12+
}
13+
14+
unsafe fn alloc(len: u256) -> u256 {
15+
let ptr: u256 = avail()
16+
evm::mstore(offset: 64, value: ptr + len)
17+
return ptr
18+
}
19+
20+
struct Cursor {
21+
cur: u256
22+
len: u256
23+
24+
pub fn new(len: u256) -> Self {
25+
return Cursor(cur: 0, len)
26+
}
27+
28+
/// Increment the value of `cur` by `len` and return the value of `cur` before being incremented.
29+
/// Reverts if the cursor is advanced beyond the given length.
30+
pub fn advance(mut self, len: u256) -> u256 {
31+
let cur: u256 = self.cur
32+
assert cur + len < self.len + 1
33+
self.cur += len
34+
return cur
35+
}
36+
37+
/// Length of the cursor remaining.
38+
pub fn remainder(self) -> u256 {
39+
return self.len - self.cur
40+
}
41+
}
42+
43+
/// EVM memory buffer abstraction.
44+
pub struct MemoryBuffer {
45+
offset: u256
46+
len: u256
47+
48+
pub fn new(len: u256) -> Self {
49+
unsafe {
50+
return MemoryBuffer(offset: alloc(len: len + 30), len)
51+
}
52+
}
53+
54+
pub fn from_u8(value: u8) -> Self {
55+
let mut buf: MemoryBuffer = MemoryBuffer::new(len: 1)
56+
let mut writer: MemoryBufferWriter = buf.writer()
57+
writer.write(value)
58+
return buf
59+
}
60+
61+
/// Length of the buffer in bytes.
62+
pub fn len(self) -> u256 {
63+
return self.len
64+
}
65+
66+
/// The start of the buffer in EVM memory.
67+
pub fn offset(self) -> u256 {
68+
return self.offset
69+
}
70+
71+
/// Returns a new buffer reader.
72+
pub fn reader(self) -> MemoryBufferReader {
73+
return MemoryBufferReader::new(buf: self)
74+
}
75+
76+
/// Returns a new buffer writer.
77+
pub fn writer(mut self) -> MemoryBufferWriter {
78+
return MemoryBufferWriter::new(buf: self)
79+
}
80+
}
81+
82+
/// Memory buffer writer abstraction.
83+
pub struct MemoryBufferWriter {
84+
buf: MemoryBuffer
85+
cur: Cursor
86+
87+
/// Returns a new writer for the given buffer.
88+
pub fn new(mut buf: MemoryBuffer) -> Self {
89+
return MemoryBufferWriter(
90+
buf,
91+
cur: Cursor::new(len: buf.len())
92+
)
93+
}
94+
95+
/// The number of bytes remaining to be written.
96+
pub fn remainder(self) -> u256 {
97+
return self.cur.remainder()
98+
}
99+
100+
pub fn write_offset(mut self, len: u256) -> u256 {
101+
return self.buf.offset() + self.cur.advance(len)
102+
}
103+
104+
pub fn write_n(mut self, value: u256, len: u256) {
105+
let offset: u256 = self.write_offset(len)
106+
let shifted_value: u256 = evm::shl(bits: 256 - len * 8, value)
107+
unsafe { evm::mstore(offset, value: shifted_value) }
108+
}
109+
110+
pub fn write_buf(mut self, buf: MemoryBuffer) {
111+
let mut reader: MemoryBufferReader = buf.reader()
112+
113+
while true {
114+
let bytes_remaining: u256 = reader.remainder()
115+
116+
if bytes_remaining >= 32 {
117+
self.write(value: reader.read_u256())
118+
} else if bytes_remaining == 0 {
119+
break
120+
} else {
121+
self.write(value: reader.read_u8())
122+
}
123+
}
124+
}
125+
126+
pub fn write<T: MemoryBufferWrite>(mut self, value: T) {
127+
value.write_buf(writer: self)
128+
}
129+
}
130+
131+
pub trait MemoryBufferWrite {
132+
fn write_buf(self, mut writer: MemoryBufferWriter);
133+
}
134+
135+
impl MemoryBufferWrite for u256 {
136+
fn write_buf(self, mut writer: MemoryBufferWriter) {
137+
let offset: u256 = writer.write_offset(len: 32)
138+
unsafe { evm::mstore(offset, value: self) }
139+
}
140+
}
141+
142+
impl MemoryBufferWrite for u128 {
143+
fn write_buf(self, mut writer: MemoryBufferWriter) {
144+
writer.write_n(value: u256(self), len: 16)
145+
}
146+
}
147+
148+
impl MemoryBufferWrite for u64 {
149+
fn write_buf(self, mut writer: MemoryBufferWriter) {
150+
writer.write_n(value: u256(self), len: 8)
151+
}
152+
}
153+
154+
impl MemoryBufferWrite for u32 {
155+
fn write_buf(self, mut writer: MemoryBufferWriter) {
156+
writer.write_n(value: u256(self), len: 4)
157+
}
158+
}
159+
160+
impl MemoryBufferWrite for u16 {
161+
fn write_buf(self, mut writer: MemoryBufferWriter) {
162+
writer.write_n(value: u256(self), len: 2)
163+
}
164+
}
165+
166+
impl MemoryBufferWrite for u8 {
167+
fn write_buf(self, mut writer: MemoryBufferWriter) {
168+
let offset: u256 = writer.write_offset(len: 1)
169+
unsafe { evm::mstore8(offset, value: self) }
170+
}
171+
}
172+
173+
// This is needed to prevent the `mir_lower_std_lib` to crash the compiler
174+
impl MemoryBufferWrite for () {
175+
fn write_buf(self, mut writer: MemoryBufferWriter) {}
176+
}
177+
178+
/// Memory buffer reader abstraction.
179+
pub struct MemoryBufferReader {
180+
buf: MemoryBuffer
181+
cur: Cursor
182+
183+
/// Returns a new reader for the given buffer.
184+
pub fn new(buf: MemoryBuffer) -> Self {
185+
return MemoryBufferReader(buf, cur: Cursor::new(len: buf.len()))
186+
}
187+
188+
/// The number of bytes remaining to be read.
189+
pub fn remainder(self) -> u256 {
190+
return self.cur.remainder()
191+
}
192+
193+
fn read_offset(mut self, len: u256) -> u256 {
194+
return self.buf.offset() + self.cur.advance(len)
195+
}
196+
197+
fn read_n(mut self, len: u256) -> u256 {
198+
let offset: u256 = self.read_offset(len)
199+
unsafe {
200+
let value: u256 = evm::mload(offset)
201+
return evm::shr(bits: 256 - len * 8, value)
202+
}
203+
}
204+
205+
pub fn read_u8(mut self) -> u8 {
206+
return u8(self.read_n(len: 1))
207+
}
208+
209+
pub fn read_u16(mut self) -> u16 {
210+
return u16(self.read_n(len: 2))
211+
}
212+
213+
pub fn read_u32(mut self) -> u32 {
214+
return u32(self.read_n(len: 4))
215+
}
216+
217+
pub fn read_u64(mut self) -> u64 {
218+
return u64(self.read_n(len: 8))
219+
}
220+
221+
pub fn read_u128(mut self) -> u128 {
222+
return u128(self.read_n(len: 16))
223+
}
224+
225+
pub fn read_u256(mut self) -> u256 {
226+
let offset: u256 = self.read_offset(len: 32)
227+
unsafe {
228+
let value: u256 = evm::mload(offset)
229+
return value
230+
}
231+
}
232+
233+
pub fn read_buf(mut self, len: u256) -> MemoryBuffer {
234+
let mut buf: MemoryBuffer = MemoryBuffer::new(len)
235+
let mut writer: MemoryBufferWriter = buf.writer()
236+
237+
while true {
238+
let bytes_remaining: u256 = writer.remainder()
239+
240+
if bytes_remaining >= 32 {
241+
writer.write(value: self.read_u256())
242+
} else if bytes_remaining == 0 {
243+
break
244+
} else {
245+
writer.write(value: self.read_u8())
246+
}
247+
}
248+
249+
return buf
250+
}
251+
252+
// `T` has not been defined
253+
// pub fn read<T: MemoryBufferRead>(mut self) -> T {
254+
// T::read_buf(writer: self)
255+
// }
256+
}
257+
258+
// pub trait MemoryBufferRead {
259+
// fn read_buf(self, mut reader: MemoryBufferReader) -> Self;
260+
// }
261+
//
262+
// impl MemoryBufferRead for u256 { .. }
263+
// .
264+
// .
265+
// impl MemoryBufferRead for u8 { .. }
266+
267+
/// `MemoryBuffer` wrapper for raw calls to other contracts.
268+
pub struct RawCallBuffer {
269+
input_len: u256
270+
output_len: u256
271+
buf: MemoryBuffer
272+
273+
pub fn new(input_len: u256, output_len: u256) -> Self {
274+
let len: u256 = math::max(input_len, output_len)
275+
let buf: MemoryBuffer = MemoryBuffer::new(len)
276+
277+
return RawCallBuffer(input_len, output_len, buf)
278+
}
279+
280+
pub fn input_len(self) -> u256 {
281+
return self.input_len
282+
}
283+
284+
pub fn output_len(self) -> u256 {
285+
return self.output_len
286+
}
287+
288+
pub fn offset(self) -> u256 {
289+
return self.buf.offset()
290+
}
291+
292+
pub fn reader(self) -> MemoryBufferReader {
293+
return self.buf.reader()
294+
}
295+
296+
pub fn writer(mut self) -> MemoryBufferWriter {
297+
return self.buf.writer()
298+
}
299+
}

0 commit comments

Comments
 (0)