endi-1.1.0/.cargo_vcs_info.json0000644000000001360000000000100117520ustar { "git": { "sha1": "606b266d07d19597216957c62c5a84637ce38123" }, "path_in_vcs": "" }endi-1.1.0/.github/workflows/release.yml000064400000000000000000000004341046102023000163030ustar 00000000000000name: Release on: push: tags: - "*.*.*" jobs: release: runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.ref }} - uses: spenserblack/actions-tag-to-release@main endi-1.1.0/.github/workflows/rust.yml000064400000000000000000000017671046102023000156720ustar 00000000000000name: Lint & Test on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] env: RUSTFLAGS: -D warnings steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: stable components: rustfmt - uses: Swatinem/rust-cache@v2 - name: Test run: cargo test lint: runs-on: ubuntu-latest env: RUSTFLAGS: -D warnings RUST_BACKTRACE: full RUST_LOG: trace MSRV: 1.60.0 steps: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ env.MSRV }} components: clippy, rustfmt - uses: Swatinem/rust-cache@v2 - name: Check formatting run: cargo fmt -- --check - name: Catch common mistakes and unwrap calls run: cargo clippy -- -D warnings endi-1.1.0/.gitignore000064400000000000000000000000241046102023000125260ustar 00000000000000/target /Cargo.lock endi-1.1.0/Cargo.toml0000644000000016410000000000100077520ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.60" name = "endi" version = "1.1.0" authors = ["Zeeshan Ali Khan "] description = "A simple endian-handling library" readme = "README.md" keywords = [ "byte", "endian", "big-endian", "little-endian", "endianness", ] categories = [ "encoding", "parsing", "no-std", ] license = "MIT" repository = "https://github.com/zeenix/endi" [features] default = ["std"] std = [] endi-1.1.0/Cargo.toml.orig000064400000000000000000000007641046102023000134400ustar 00000000000000[package] name = "endi" version = "1.1.0" description = "A simple endian-handling library" authors = ["Zeeshan Ali Khan "] repository = "https://github.com/zeenix/endi" categories = ["encoding", "parsing", "no-std"] keywords = ["byte", "endian", "big-endian", "little-endian", "endianness"] license = "MIT" rust-version = "1.60" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] default = ["std"] std = [] endi-1.1.0/LICENSE-MIT000064400000000000000000000017771046102023000122120ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. endi-1.1.0/README.md000064400000000000000000000025271046102023000120270ustar 00000000000000# endi [![Build Status](https://github.com/zeenix/endi/actions/workflows/rust.yml/badge.svg)](https://github.com/zeenix/endi/actions/workflows/rust.yml) [![API Documentation](https://docs.rs/endi/badge.svg)](https://docs.rs/endi/) [![crates.io](https://img.shields.io/crates/v/endi)](https://crates.io/crates/endi) Yet another endian handling library for Rust. The approach is very similar to that of `byteordered` crate with its `Endianness` enum, except that `endi` is much simpler and doesn't depend on `byteorder` (or anything at all). ## Usage The main type is `Endian` enum which can be either `Big` or `Little`. It provides various methods to read and write integers of different sizes and endianness. ```rust use endi::{Endian, ReadBytes, WriteBytes}; let mut buf = [0u8; 4]; for endian in [Endian::Little, Endian::Big] { endian.write_u32(&mut buf, 0xAB_BA_FE_EF); assert_eq!(endian.read_u32(&buf), 0xAB_BA_FE_EF); // Using the `ReadBytes` and `WriteBytes` traits: let mut cursor = std::io::Cursor::new(&mut buf[..]); cursor.write_u32(endian, 0xAB_BA_FE_EF).unwrap(); cursor.set_position(0); assert_eq!(cursor.read_u32(endian).unwrap(), 0xAB_BA_FE_EF); } ``` ## nostd You can disable `std` by disabling the default `std` feature. This will disable the `ReadBytes` and `WriteBytes` traits. ## License [MIT](LICENSE-MIT) endi-1.1.0/src/endian.rs000064400000000000000000000210761046102023000131430ustar 00000000000000/// The endian of the data. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Endian { /// Little endian. Little, /// Big endian. Big, } /// Alias for [`Endian::Little`]. pub const LE: Endian = Endian::Little; /// Alias for [`Endian::Big`]. pub const BE: Endian = Endian::Big; /// Same as the return value of [`Endian::native`]. pub const NATIVE_ENDIAN: Endian = Endian::native(); /// Alias for [`Endian::Big`]. pub const NETWORK_ENDIAN: Endian = Endian::Big; macro_rules! impl_read_method { ($type:ty, $method:ident, $size:literal) => { #[doc = concat!("Read a `", stringify!($type), "` from a byte slice.\n\n", "# Panics\n\n", "Panics if the slice is smaller than ", stringify!($size), " bytes.")] #[inline] pub fn $method(self, buf: &[u8]) -> $type { match self { Self::Little => <$type>::from_le_bytes(buf[..$size].try_into().unwrap()), Self::Big => <$type>::from_be_bytes(buf[..$size].try_into().unwrap()), } } }; } macro_rules! impl_write_method { ($type:ty, $method:ident, $size:literal) => { #[doc = concat!("Write a `", stringify!($type), "` into a mutable byte slice.\n\n", "# Panics\n\n", "Panics if the slice is smaller than ", stringify!($size), " bytes.")] #[inline] pub fn $method(self, buf: &mut [u8], n: $type) { match self { Self::Little => buf[..$size].copy_from_slice(&n.to_le_bytes()), Self::Big => buf[..$size].copy_from_slice(&n.to_be_bytes()), } } }; } impl Endian { /// The native endian. #[inline] pub const fn native() -> Self { #[cfg(target_endian = "little")] { Self::Little } #[cfg(target_endian = "big")] { Self::Big } } // Reading. // Unsigned integers impl_read_method!(u8, read_u8, 1); impl_read_method!(u16, read_u16, 2); impl_read_method!(u32, read_u32, 4); impl_read_method!(u64, read_u64, 8); impl_read_method!(u128, read_u128, 16); // Signed integers impl_read_method!(i8, read_i8, 1); impl_read_method!(i16, read_i16, 2); impl_read_method!(i32, read_i32, 4); impl_read_method!(i64, read_i64, 8); impl_read_method!(i128, read_i128, 16); // Floating point numbers impl_read_method!(f32, read_f32, 4); impl_read_method!(f64, read_f64, 8); // Writing. // Unsigned integers impl_write_method!(u8, write_u8, 1); impl_write_method!(u16, write_u16, 2); impl_write_method!(u32, write_u32, 4); impl_write_method!(u64, write_u64, 8); impl_write_method!(u128, write_u128, 16); // Signed integers impl_write_method!(i8, write_i8, 1); impl_write_method!(i16, write_i16, 2); impl_write_method!(i32, write_i32, 4); impl_write_method!(i64, write_i64, 8); impl_write_method!(i128, write_i128, 16); // Floating point numbers impl_write_method!(f32, write_f32, 4); impl_write_method!(f64, write_f64, 8); } #[cfg(test)] mod tests { use super::*; #[test] fn u8() { let buf = [0x01]; assert_eq!(Endian::Little.read_u8(&buf), 0x01); assert_eq!(Endian::Big.read_u8(&buf), 0x01); let mut buf = [0x00]; Endian::Little.write_u8(&mut buf, 0x01); assert_eq!(buf, [0x01]); Endian::Big.write_u8(&mut buf, 0x01); assert_eq!(buf, [0x01]); } #[test] fn u16() { let buf = [0x01, 0x02]; assert_eq!(Endian::Little.read_u16(&buf), 0x02_01); assert_eq!(Endian::Big.read_u16(&buf), 0x01_02); let mut buf = [0x00, 0x00]; Endian::Little.write_u16(&mut buf, 0x01_02); assert_eq!(buf, [0x02, 0x01]); Endian::Big.write_u16(&mut buf, 0x01_02); assert_eq!(buf, [0x01, 0x02]); } #[test] fn u32() { let buf = [0x01, 0x02, 0x03, 0x04]; assert_eq!(Endian::Little.read_u32(&buf), 0x04_03_02_01); assert_eq!(Endian::Big.read_u32(&buf), 0x01_02_03_04); let mut buf = [0x00, 0x00, 0x00, 0x00]; Endian::Little.write_u32(&mut buf, 0x01_02_03_04); assert_eq!(buf, [0x04, 0x03, 0x02, 0x01]); Endian::Big.write_u32(&mut buf, 0x01_02_03_04); assert_eq!(buf, [0x01, 0x02, 0x03, 0x04]); } #[test] fn u64() { let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; assert_eq!(Endian::Little.read_u64(&buf), 0x08_07_06_05_04_03_02_01); assert_eq!(Endian::Big.read_u64(&buf), 0x01_02_03_04_05_06_07_08); let mut buf = [0x00; 8]; Endian::Little.write_u64(&mut buf, 0x01_02_03_04_05_06_07_08); assert_eq!(buf, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); Endian::Big.write_u64(&mut buf, 0x01_02_03_04_05_06_07_08); assert_eq!(buf, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); } #[test] fn u128() { let buf = [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, ]; assert_eq!( Endian::Little.read_u128(&buf), 0x10_0f_0e_0d_0c_0b_0a_09_08_07_06_05_04_03_02_01 ); assert_eq!( Endian::Big.read_u128(&buf), 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10 ); let mut buf = [0x00; 16]; Endian::Little.write_u128(&mut buf, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10); assert_eq!( buf, [ 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 ] ); Endian::Big.write_u128(&mut buf, 0x01_02_03_04_05_06_07_08_09_0a_0b_0c_0d_0e_0f_10); assert_eq!( buf, [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10 ] ); } #[test] fn i8() { let buf = [0x01]; assert_eq!(Endian::Little.read_i8(&buf), 0x01); assert_eq!(Endian::Big.read_i8(&buf), 0x01); let mut buf = [0x00]; Endian::Little.write_i8(&mut buf, 0x01); assert_eq!(buf, [0x01]); Endian::Big.write_i8(&mut buf, 0x01); assert_eq!(buf, [0x01]); } #[test] fn i16() { let buf = [0x01, 0x02]; assert_eq!(Endian::Little.read_i16(&buf), 0x02_01); assert_eq!(Endian::Big.read_i16(&buf), 0x01_02); let mut buf = [0x00, 0x00]; Endian::Little.write_i16(&mut buf, 0x01_02); assert_eq!(buf, [0x02, 0x01]); Endian::Big.write_i16(&mut buf, 0x01_02); assert_eq!(buf, [0x01, 0x02]); } #[test] fn i32() { let buf = [0x01, 0x02, 0x03, 0x04]; assert_eq!(Endian::Little.read_i32(&buf), 0x04_03_02_01); assert_eq!(Endian::Big.read_i32(&buf), 0x01_02_03_04); let mut buf = [0x00, 0x00, 0x00, 0x00]; Endian::Little.write_i32(&mut buf, 0x01_02_03_04); assert_eq!(buf, [0x04, 0x03, 0x02, 0x01]); Endian::Big.write_i32(&mut buf, 0x01_02_03_04); assert_eq!(buf, [0x01, 0x02, 0x03, 0x04]); } #[test] fn i64() { let buf = [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; assert_eq!(Endian::Little.read_i64(&buf), 0x08_07_06_05_04_03_02_01); assert_eq!(Endian::Big.read_i64(&buf), 0x01_02_03_04_05_06_07_08); let mut buf = [0x00; 8]; Endian::Little.write_i64(&mut buf, 0x01_02_03_04_05_06_07_08); assert_eq!(buf, [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]); Endian::Big.write_i64(&mut buf, 0x01_02_03_04_05_06_07_08); assert_eq!(buf, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]); } #[test] fn f32() { let buf = [0x00, 0x00, 0x80, 0x3f]; assert_eq!(Endian::Little.read_f32(&buf), 1.0); assert_eq!(Endian::Big.read_f32(&buf), 4.6006e-41); let mut buf = [0x00; 4]; Endian::Little.write_f32(&mut buf, 1.0); assert_eq!(buf, [0x00, 0x00, 0x80, 0x3f]); Endian::Big.write_f32(&mut buf, 1.0); assert_eq!(buf, [0x3f, 0x80, 0x00, 0x00]); } #[test] fn f64() { let buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x3f]; assert_eq!(Endian::Little.read_f64(&buf), 0.124755859375); assert_eq!(Endian::Big.read_f64(&buf), 7.7951696e-317); let mut buf = [0x00; 8]; Endian::Little.write_f64(&mut buf, 0.124755859375); assert_eq!(buf, [0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x3f]); Endian::Big.write_f64(&mut buf, 1.0); assert_eq!(buf, [0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]); } } endi-1.1.0/src/io.rs000064400000000000000000000064301046102023000123110ustar 00000000000000use std::io::{Read, Result, Write}; use crate::Endian; macro_rules! decl_read_method { ($type:ty, $method:ident) => { #[doc = concat!("Read a `", stringify!($type), "`.")] fn $method(&mut self, endian: Endian) -> Result<$type>; }; } /// A trait for reading bytes. /// /// This is implemented for all types that implement [`Read`]. pub trait ReadBytes { decl_read_method!(u8, read_u8); decl_read_method!(u16, read_u16); decl_read_method!(u32, read_u32); decl_read_method!(u64, read_u64); decl_read_method!(u128, read_u128); decl_read_method!(i8, read_i8); decl_read_method!(i16, read_i16); decl_read_method!(i32, read_i32); decl_read_method!(i64, read_i64); decl_read_method!(i128, read_i128); decl_read_method!(f32, read_f32); decl_read_method!(f64, read_f64); } macro_rules! impl_read_method { ($type:ty, $method:ident, $size:literal) => { #[inline] fn $method(&mut self, endian: Endian) -> Result<$type> { let mut buf = [0; $size]; self.read_exact(&mut buf)?; Ok(endian.$method(&buf)) } }; } impl ReadBytes for R { impl_read_method!(u8, read_u8, 1); impl_read_method!(u16, read_u16, 2); impl_read_method!(u32, read_u32, 4); impl_read_method!(u64, read_u64, 8); impl_read_method!(u128, read_u128, 16); impl_read_method!(i8, read_i8, 1); impl_read_method!(i16, read_i16, 2); impl_read_method!(i32, read_i32, 4); impl_read_method!(i64, read_i64, 8); impl_read_method!(i128, read_i128, 16); impl_read_method!(f32, read_f32, 4); impl_read_method!(f64, read_f64, 8); } macro_rules! decl_write_method { ($type:ty, $method:ident) => { #[doc = concat!("Write a `", stringify!($type), "`.")] fn $method(&mut self, endian: Endian, n: $type) -> Result<()>; }; } /// A trait for writing bytes. /// /// This is implemented for all types that implement [`Write`]. pub trait WriteBytes { decl_write_method!(u8, write_u8); decl_write_method!(u16, write_u16); decl_write_method!(u32, write_u32); decl_write_method!(u64, write_u64); decl_write_method!(u128, write_u128); decl_write_method!(i8, write_i8); decl_write_method!(i16, write_i16); decl_write_method!(i32, write_i32); decl_write_method!(i64, write_i64); decl_write_method!(i128, write_i128); decl_write_method!(f32, write_f32); decl_write_method!(f64, write_f64); } macro_rules! impl_write_method { ($type:ty, $method:ident, $size:literal) => { #[inline] fn $method(&mut self, endian: Endian, n: $type) -> Result<()> { let mut buf = [0; $size]; endian.$method(&mut buf, n); self.write_all(&buf) } }; } impl WriteBytes for W { impl_write_method!(u8, write_u8, 1); impl_write_method!(u16, write_u16, 2); impl_write_method!(u32, write_u32, 4); impl_write_method!(u64, write_u64, 8); impl_write_method!(u128, write_u128, 16); impl_write_method!(i8, write_i8, 1); impl_write_method!(i16, write_i16, 2); impl_write_method!(i32, write_i32, 4); impl_write_method!(i64, write_i64, 8); impl_write_method!(i128, write_i128, 16); impl_write_method!(f32, write_f32, 4); impl_write_method!(f64, write_f64, 8); } endi-1.1.0/src/lib.rs000064400000000000000000000005121046102023000124430ustar 00000000000000#![allow(clippy::unusual_byte_groupings)] #![deny(rust_2018_idioms)] #![doc = include_str!("../README.md")] #![doc(test(attr(warn(unused), deny(warnings))))] mod endian; pub use endian::{Endian, BE, LE, NATIVE_ENDIAN, NETWORK_ENDIAN}; #[cfg(feature = "std")] mod io; #[cfg(feature = "std")] pub use io::{ReadBytes, WriteBytes};