add libio from ARTIQ
This commit is contained in:
parent
cb24b82e68
commit
6454f994af
8
src/Cargo.lock
generated
8
src/Cargo.lock
generated
@ -151,6 +151,13 @@ dependencies = [
|
||||
"proc-macro-nested",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "io"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libasync"
|
||||
version = "0.0.0"
|
||||
@ -333,6 +340,7 @@ dependencies = [
|
||||
"cslice",
|
||||
"dyld",
|
||||
"futures",
|
||||
"io",
|
||||
"libasync",
|
||||
"libboard_zynq",
|
||||
"libcortex_a9",
|
||||
|
@ -1,6 +1,7 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"libdyld",
|
||||
"libio",
|
||||
"runtime",
|
||||
"szl"
|
||||
]
|
||||
|
@ -9,7 +9,7 @@ all: ../build/firmware/armv7-none-eabihf/release/szl
|
||||
mkdir -p ../build
|
||||
python zc706.py -r ../build/pl.rs -V $(VARIANT)
|
||||
|
||||
../build/firmware/armv7-none-eabihf/release/runtime: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml libdyld/* libdyld/src/* runtime/* runtime/src/* ../build/pl.rs
|
||||
../build/firmware/armv7-none-eabihf/release/runtime: .cargo/* armv7-none-eabihf.json Cargo.lock Cargo.toml libdyld/* libdyld/src/* libio/* libio/src/* runtime/* runtime/src/* ../build/pl.rs
|
||||
XBUILD_SYSROOT_PATH=`pwd`/../build/sysroot cargo xbuild --release -p runtime --target-dir ../build/firmware
|
||||
|
||||
../build/szl-payload.bin.lzma: ../build/firmware/armv7-none-eabihf/release/runtime
|
||||
|
13
src/libio/Cargo.toml
Normal file
13
src/libio/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
authors = ["M-Labs"]
|
||||
name = "io"
|
||||
version = "0.1.0"
|
||||
|
||||
[lib]
|
||||
name = "io"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
|
||||
[features]
|
||||
alloc = []
|
86
src/libio/src/cursor.rs
Normal file
86
src/libio/src/cursor.rs
Normal file
@ -0,0 +1,86 @@
|
||||
use {Read, Write};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Cursor<T> {
|
||||
inner: T,
|
||||
pos: usize
|
||||
}
|
||||
|
||||
impl<T> Cursor<T> {
|
||||
#[inline]
|
||||
pub fn new(inner: T) -> Cursor<T> {
|
||||
Cursor { inner, pos: 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> T {
|
||||
self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_ref(&self) -> &T {
|
||||
&self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.inner
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn position(&self) -> usize {
|
||||
self.pos
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&mut self, pos: usize) {
|
||||
self.pos = pos
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AsRef<[u8]>> Read for Cursor<T> {
|
||||
type ReadError = !;
|
||||
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
|
||||
let data = &self.inner.as_ref()[self.pos..];
|
||||
let len = buf.len().min(data.len());
|
||||
buf[..len].copy_from_slice(&data[..len]);
|
||||
self.pos += len;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for Cursor<&'a mut [u8]> {
|
||||
type WriteError = !;
|
||||
type FlushError = !;
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
|
||||
let data = &mut self.inner[self.pos..];
|
||||
let len = buf.len().min(data.len());
|
||||
data[..len].copy_from_slice(&buf[..len]);
|
||||
self.pos += len;
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Write for Cursor<::alloc::vec::Vec<u8>> {
|
||||
type WriteError = !;
|
||||
type FlushError = !;
|
||||
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
|
||||
self.inner.extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
137
src/libio/src/lib.rs
Normal file
137
src/libio/src/lib.rs
Normal file
@ -0,0 +1,137 @@
|
||||
#![no_std]
|
||||
#![feature(never_type)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
extern crate byteorder;
|
||||
|
||||
mod cursor;
|
||||
mod proto;
|
||||
|
||||
pub use cursor::Cursor;
|
||||
pub use proto::{ProtoRead, ProtoWrite};
|
||||
#[cfg(feature = "alloc")]
|
||||
pub use proto::ReadStringError;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Error<T> {
|
||||
UnexpectedEnd,
|
||||
Other(T)
|
||||
}
|
||||
|
||||
impl<T> From<T> for Error<T> {
|
||||
fn from(value: T) -> Error<T> {
|
||||
Error::Other(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Read {
|
||||
type ReadError;
|
||||
|
||||
/// Pull some bytes from this source into the specified buffer, returning
|
||||
/// how many bytes were read.
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError>;
|
||||
|
||||
/// Read the exact number of bytes required to fill `buf`.
|
||||
fn read_exact(&mut self, mut buf: &mut [u8]) -> Result<(), Error<Self::ReadError>> {
|
||||
while !buf.is_empty() {
|
||||
let read_bytes = self.read(buf)?;
|
||||
if read_bytes == 0 {
|
||||
return Err(Error::UnexpectedEnd)
|
||||
}
|
||||
|
||||
buf = &mut { buf }[read_bytes..];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Read> Read for &'a mut T {
|
||||
type ReadError = T::ReadError;
|
||||
|
||||
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::ReadError> {
|
||||
T::read(self, buf)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Write {
|
||||
type WriteError;
|
||||
type FlushError;
|
||||
|
||||
/// Write a buffer into this object, returning how many bytes were written.
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError>;
|
||||
|
||||
/// Flush this output stream, ensuring that all intermediately buffered contents
|
||||
/// reach their destination.
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError>;
|
||||
|
||||
/// Attempts to write an entire buffer into `self`.
|
||||
fn write_all(&mut self, mut buf: &[u8]) -> Result<(), Error<Self::WriteError>> {
|
||||
while buf.len() > 0 {
|
||||
let written_bytes = self.write(buf)?;
|
||||
if written_bytes == 0 {
|
||||
return Err(Error::UnexpectedEnd)
|
||||
}
|
||||
|
||||
buf = &buf[written_bytes..];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Hints the writer how much bytes will be written after call to this function.
|
||||
///
|
||||
/// At least `min` bytes should be written after the call to this function and
|
||||
/// if `max` is `Some(x)` than at most `x` bytes should be written.
|
||||
fn size_hint(&mut self, _min: usize, _max: Option<usize>) {}
|
||||
}
|
||||
|
||||
impl<'a, T: Write> Write for &'a mut T {
|
||||
type WriteError = T::WriteError;
|
||||
type FlushError = T::FlushError;
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
|
||||
T::write(self, buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError> {
|
||||
T::flush(self)
|
||||
}
|
||||
|
||||
fn size_hint(&mut self, min: usize, max: Option<usize>) {
|
||||
T::size_hint(self, min, max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Write for &'a mut [u8] {
|
||||
type WriteError = !;
|
||||
type FlushError = !;
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
|
||||
let len = buf.len().min(self.len());
|
||||
self[..len].copy_from_slice(&buf[..len]);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> Write for alloc::vec::Vec<u8> {
|
||||
type WriteError = !;
|
||||
type FlushError = !;
|
||||
|
||||
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::WriteError> {
|
||||
self.extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&mut self) -> Result<(), Self::FlushError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
162
src/libio/src/proto.rs
Normal file
162
src/libio/src/proto.rs
Normal file
@ -0,0 +1,162 @@
|
||||
#[cfg(feature = "alloc")]
|
||||
use core::str::Utf8Error;
|
||||
use byteorder::{ByteOrder, NetworkEndian};
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::vec;
|
||||
use alloc::string::String;
|
||||
|
||||
use ::{Read, Write, Error as IoError};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ReadStringError<T> {
|
||||
Utf8(Utf8Error),
|
||||
Other(T)
|
||||
}
|
||||
|
||||
pub trait ProtoRead {
|
||||
type ReadError;
|
||||
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError>;
|
||||
|
||||
#[inline]
|
||||
fn read_u8(&mut self) -> Result<u8, Self::ReadError> {
|
||||
let mut bytes = [0; 1];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(bytes[0])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_u16(&mut self) -> Result<u16, Self::ReadError> {
|
||||
let mut bytes = [0; 2];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u16(&bytes))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_u32(&mut self) -> Result<u32, Self::ReadError> {
|
||||
let mut bytes = [0; 4];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u32(&bytes))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_u64(&mut self) -> Result<u64, Self::ReadError> {
|
||||
let mut bytes = [0; 8];
|
||||
self.read_exact(&mut bytes)?;
|
||||
Ok(NetworkEndian::read_u64(&bytes))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn read_bool(&mut self) -> Result<bool, Self::ReadError> {
|
||||
Ok(self.read_u8()? != 0)
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline]
|
||||
fn read_bytes(&mut self) -> Result<::alloc::vec::Vec<u8>, Self::ReadError> {
|
||||
let length = self.read_u32()?;
|
||||
let mut value = vec![0; length as usize];
|
||||
self.read_exact(&mut value)?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[inline]
|
||||
fn read_string(&mut self) -> Result<::alloc::string::String, ReadStringError<Self::ReadError>> {
|
||||
let bytes = self.read_bytes().map_err(ReadStringError::Other)?;
|
||||
String::from_utf8(bytes).map_err(|err| ReadStringError::Utf8(err.utf8_error()))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ProtoWrite {
|
||||
type WriteError;
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError>;
|
||||
|
||||
#[inline]
|
||||
fn write_u8(&mut self, value: u8) -> Result<(), Self::WriteError> {
|
||||
let bytes = [value; 1];
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_i8(&mut self, value: i8) -> Result<(), Self::WriteError> {
|
||||
let bytes = [value as u8; 1];
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_u16(&mut self, value: u16) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 2];
|
||||
NetworkEndian::write_u16(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_i16(&mut self, value: i16) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 2];
|
||||
NetworkEndian::write_i16(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_u32(&mut self, value: u32) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 4];
|
||||
NetworkEndian::write_u32(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_i32(&mut self, value: i32) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 4];
|
||||
NetworkEndian::write_i32(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_u64(&mut self, value: u64) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 8];
|
||||
NetworkEndian::write_u64(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_i64(&mut self, value: i64) -> Result<(), Self::WriteError> {
|
||||
let mut bytes = [0; 8];
|
||||
NetworkEndian::write_i64(&mut bytes, value);
|
||||
self.write_all(&bytes)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_bool(&mut self, value: bool) -> Result<(), Self::WriteError> {
|
||||
self.write_u8(value as u8)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_bytes(&mut self, value: &[u8]) -> Result<(), Self::WriteError> {
|
||||
self.write_u32(value.len() as u32)?;
|
||||
self.write_all(value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_string(&mut self, value: &str) -> Result<(), Self::WriteError> {
|
||||
self.write_bytes(value.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ProtoRead for T where T: Read + ?Sized {
|
||||
type ReadError = IoError<T::ReadError>;
|
||||
|
||||
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Self::ReadError> {
|
||||
T::read_exact(self, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ProtoWrite for T where T: Write + ?Sized {
|
||||
type WriteError = IoError<T::WriteError>;
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::WriteError> {
|
||||
T::write_all(self, buf)
|
||||
}
|
||||
}
|
@ -21,3 +21,4 @@ libsupport_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
dyld = { path = "../libdyld" }
|
||||
io = { path = "../libio", features = ["alloc"] }
|
||||
|
@ -5,6 +5,7 @@ use core::cell::RefCell;
|
||||
use libboard_zynq::smoltcp;
|
||||
use libasync::smoltcp::TcpStream;
|
||||
|
||||
// TODO: use byteorder, make it more like libio
|
||||
|
||||
pub type Result<T> = core::result::Result<T, smoltcp::Error>;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user