add basic tinyptr code
This commit is contained in:
parent
c0fcfe9dbb
commit
3a3162a1a3
9 changed files with 440 additions and 15 deletions
15
.drone.yml
15
.drone.yml
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: docker
|
|
||||||
name: notify-hydra
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Notify hydra
|
|
||||||
image: nixery.dev/shell/curl
|
|
||||||
commands:
|
|
||||||
- curl --get --data-urlencode "jobsets=darkkirb:rkb1-firmware" https://hydra.chir.rs/api/push
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
branch:
|
|
||||||
- main
|
|
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -565,6 +565,10 @@ dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tinyptr"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
args@{
|
args@{
|
||||||
release ? true,
|
release ? true,
|
||||||
rootFeatures ? [
|
rootFeatures ? [
|
||||||
|
"tinyptr/default"
|
||||||
"rkbfirm/default"
|
"rkbfirm/default"
|
||||||
],
|
],
|
||||||
rustPackages,
|
rustPackages,
|
||||||
|
@ -41,6 +42,7 @@ in
|
||||||
{
|
{
|
||||||
cargo2nixVersion = "0.11.0";
|
cargo2nixVersion = "0.11.0";
|
||||||
workspace = {
|
workspace = {
|
||||||
|
tinyptr = rustPackages.unknown.tinyptr."0.1.0";
|
||||||
rkbfirm = rustPackages.unknown.rkbfirm."0.1.0";
|
rkbfirm = rustPackages.unknown.rkbfirm."0.1.0";
|
||||||
};
|
};
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".aho-corasick."0.7.18" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".aho-corasick."0.7.18" = overridableMkRustCrate (profileName: rec {
|
||||||
|
@ -801,6 +803,13 @@ in
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
"unknown".tinyptr."0.1.0" = overridableMkRustCrate (profileName: rec {
|
||||||
|
name = "tinyptr";
|
||||||
|
version = "0.1.0";
|
||||||
|
registry = "unknown";
|
||||||
|
src = fetchCrateLocal (workspaceSrc + "/lib/tinyptr");
|
||||||
|
});
|
||||||
|
|
||||||
"registry+https://github.com/rust-lang/crates.io-index".unicode-ident."1.0.1" = overridableMkRustCrate (profileName: rec {
|
"registry+https://github.com/rust-lang/crates.io-index".unicode-ident."1.0.1" = overridableMkRustCrate (profileName: rec {
|
||||||
name = "unicode-ident";
|
name = "unicode-ident";
|
||||||
version = "1.0.1";
|
version = "1.0.1";
|
||||||
|
|
|
@ -3,6 +3,10 @@ name = "rkbfirm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"lib/tinyptr"
|
||||||
|
]
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
cargo2nix.packages.${system}.cargo2nix
|
cargo2nix.packages.${system}.cargo2nix
|
||||||
elf2uf2-rs
|
elf2uf2-rs
|
||||||
cargo-embed
|
cargo-embed
|
||||||
|
llvmPackages_latest.bintools
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
packages = rec {
|
packages = rec {
|
||||||
|
|
8
lib/tinyptr/Cargo.toml
Normal file
8
lib/tinyptr/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "tinyptr"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
123
lib/tinyptr/src/lib.rs
Normal file
123
lib/tinyptr/src/lib.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
//! 16 bit pointer library
|
||||||
|
//!
|
||||||
|
//! This library provides small pointers with a range of 64 kiB. This is useful for memory-limited
|
||||||
|
//! microcontrollers.
|
||||||
|
//!
|
||||||
|
//! It uses a const generic parameter to set the base address of the pointer. This allows multiple
|
||||||
|
//! small memory pools to coexist.
|
||||||
|
#![feature(coerce_unsized)]
|
||||||
|
#![feature(mixed_integer_ops)]
|
||||||
|
#![feature(never_type)]
|
||||||
|
#![feature(ptr_metadata)]
|
||||||
|
#![feature(slice_ptr_get)]
|
||||||
|
#![feature(slice_ptr_len)]
|
||||||
|
#![feature(strict_provenance)]
|
||||||
|
#![feature(unsize)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
use core::hash::Hash;
|
||||||
|
|
||||||
|
pub mod ptr;
|
||||||
|
|
||||||
|
/// Trait that defines valid destination types for a pointer.
|
||||||
|
pub trait Pointable {
|
||||||
|
/// The pointer metadata.
|
||||||
|
type PointerMeta;
|
||||||
|
/// The tiny version of the pointer metadata.
|
||||||
|
type PointerMetaTiny: Copy + Eq + Ord + Hash;
|
||||||
|
/// Conversion error.
|
||||||
|
type ConversionError: core::fmt::Display + core::fmt::Debug + Clone;
|
||||||
|
|
||||||
|
/// Try reduce the pointer metadata to a tiny version.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// This function returns an error if the pointer metadata does not fit into a tiny version.
|
||||||
|
fn try_tiny(meta: Self::PointerMeta) -> Result<Self::PointerMetaTiny, Self::ConversionError>;
|
||||||
|
/// Reduce the pointer metadata to a tiny version.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// This function panics if it cannot convert the pointer metadata to a tiny version.
|
||||||
|
fn tiny(meta: Self::PointerMeta) -> Self::PointerMetaTiny {
|
||||||
|
Self::try_tiny(meta).unwrap()
|
||||||
|
}
|
||||||
|
/// Reduce the pointer metadata to a tiny version, without checking
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// This function is unsafe because it does not check if the pointer metadata fits into a tiny version.
|
||||||
|
unsafe fn tiny_unchecked(meta: Self::PointerMeta) -> Self::PointerMetaTiny {
|
||||||
|
Self::tiny(meta)
|
||||||
|
}
|
||||||
|
/// Convert a tiny version of the pointer metadata to the full version.
|
||||||
|
fn huge(meta: Self::PointerMetaTiny) -> Self::PointerMeta;
|
||||||
|
|
||||||
|
/// Returns an address and the pointer metadata for a pointer
|
||||||
|
fn extract_parts(ptr: *const Self) -> (usize, Self::PointerMeta);
|
||||||
|
|
||||||
|
/// Returns a pointer to an address in a specific address space
|
||||||
|
fn create_ptr(base_ptr: *const (), address: usize, meta: Self::PointerMeta) -> *const Self;
|
||||||
|
|
||||||
|
/// Returns a mutable pointer to an address in a specific address space
|
||||||
|
fn create_ptr_mut(base_ptr: *mut (), address: usize, meta: Self::PointerMeta) -> *mut Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> Pointable for T {
|
||||||
|
type PointerMeta = ();
|
||||||
|
type PointerMetaTiny = ();
|
||||||
|
type ConversionError = !;
|
||||||
|
|
||||||
|
fn try_tiny(_: ()) -> Result<(), !> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn tiny(_: ()) -> () {}
|
||||||
|
fn huge(_: ()) -> () {}
|
||||||
|
|
||||||
|
fn extract_parts(ptr: *const Self) -> (usize, ()) {
|
||||||
|
(ptr.addr(), ())
|
||||||
|
}
|
||||||
|
fn create_ptr(base_ptr: *const (), address: usize, _: ()) -> *const Self {
|
||||||
|
base_ptr.with_addr(address).cast()
|
||||||
|
}
|
||||||
|
fn create_ptr_mut(base_ptr: *mut (), address: usize, _: ()) -> *mut Self {
|
||||||
|
base_ptr.with_addr(address).cast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Sized> Pointable for [T] {
|
||||||
|
type PointerMeta = usize;
|
||||||
|
type PointerMetaTiny = u16;
|
||||||
|
type ConversionError = <u16 as TryFrom<usize>>::Error;
|
||||||
|
|
||||||
|
fn try_tiny(meta: usize) -> Result<u16, Self::ConversionError> {
|
||||||
|
meta.try_into()
|
||||||
|
}
|
||||||
|
unsafe fn tiny_unchecked(meta: usize) -> u16 {
|
||||||
|
meta as u16
|
||||||
|
}
|
||||||
|
fn huge(meta: u16) -> usize {
|
||||||
|
meta.into()
|
||||||
|
}
|
||||||
|
fn extract_parts(ptr: *const Self) -> (usize, usize) {
|
||||||
|
(ptr.as_ptr().addr(), ptr.len())
|
||||||
|
}
|
||||||
|
fn create_ptr(base_ptr: *const (), address: usize, meta: usize) -> *const Self {
|
||||||
|
core::ptr::from_raw_parts(base_ptr.with_addr(address), meta)
|
||||||
|
}
|
||||||
|
fn create_ptr_mut(base_ptr: *mut (), address: usize, meta: usize) -> *mut Self {
|
||||||
|
core::ptr::from_raw_parts_mut(base_ptr.with_addr(address), meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn base_ptr<const BASE: usize>() -> *const () {
|
||||||
|
core::ptr::from_exposed_addr(BASE)
|
||||||
|
}
|
||||||
|
pub(crate) fn base_ptr_mut<const BASE: usize>() -> *mut () {
|
||||||
|
core::ptr::from_exposed_addr_mut(BASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PointerConversionError<T: ?Sized + Pointable> {
|
||||||
|
/// The pointer is not in 16 bit address space
|
||||||
|
NotInAddressSpace(<u16 as TryFrom<usize>>::Error),
|
||||||
|
/// The pointer metadata cannot be reduced in size
|
||||||
|
CannotReduceMeta(<T as Pointable>::ConversionError),
|
||||||
|
}
|
286
lib/tinyptr/src/ptr/const_ptr.rs
Normal file
286
lib/tinyptr/src/ptr/const_ptr.rs
Normal file
|
@ -0,0 +1,286 @@
|
||||||
|
//! Constant pointer
|
||||||
|
|
||||||
|
use core::{marker::{PhantomData, Unsize}, ops::CoerceUnsized, cmp::Ordering, fmt, hash::{Hash, Hasher}};
|
||||||
|
|
||||||
|
use crate::{base_ptr, Pointable, PointerConversionError};
|
||||||
|
|
||||||
|
/// A tiny constant pointer
|
||||||
|
pub struct ConstPtr<T: Pointable + ?Sized, const BASE: usize> {
|
||||||
|
pub(crate) ptr: u16,
|
||||||
|
pub(crate) meta: <T as Pointable>::PointerMetaTiny,
|
||||||
|
pub(crate) _marker: PhantomData<*const T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> ConstPtr<T, BASE> {
|
||||||
|
/// Create a new constant pointer from raw parts
|
||||||
|
pub const fn from_raw_parts(ptr: u16, meta: <T as Pointable>::PointerMetaTiny) -> Self {
|
||||||
|
Self {
|
||||||
|
ptr,
|
||||||
|
meta,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Creates a tiny pointer unchecked
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// This is unsafe because the address of the pointer may change.
|
||||||
|
pub unsafe fn new_unchecked(ptr: *const T) -> Self {
|
||||||
|
let (addr, meta) = T::extract_parts(ptr);
|
||||||
|
let addr = if ptr.is_null() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
addr.wrapping_sub(BASE)
|
||||||
|
};
|
||||||
|
Self::from_raw_parts(addr as u16, T::tiny_unchecked(meta))
|
||||||
|
}
|
||||||
|
/// Tries to create a tiny pointer from a pointer
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns an error if the pointer does not fit in the address space
|
||||||
|
pub fn new(ptr: *const T) -> Result<Self, PointerConversionError<T>> {
|
||||||
|
let (addr, meta) = T::extract_parts(ptr);
|
||||||
|
let addr = if ptr.is_null() {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
addr.wrapping_sub(BASE)
|
||||||
|
};
|
||||||
|
let addr = addr
|
||||||
|
.try_into()
|
||||||
|
.map_err(PointerConversionError::NotInAddressSpace)?;
|
||||||
|
let meta = T::try_tiny(meta).map_err(PointerConversionError::CannotReduceMeta)?;
|
||||||
|
Ok(Self::from_raw_parts(addr, meta))
|
||||||
|
}
|
||||||
|
/// Widens the pointer
|
||||||
|
pub fn wide(self) -> *const T {
|
||||||
|
let addr = if self.ptr == 0 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
usize::from(self.ptr).wrapping_add(BASE)
|
||||||
|
};
|
||||||
|
T::create_ptr(base_ptr::<BASE>(), addr, T::huge(self.meta))
|
||||||
|
}
|
||||||
|
/// Returns `true` if the pointer is null
|
||||||
|
pub const fn is_null(self) -> bool {
|
||||||
|
self.ptr == 0
|
||||||
|
}
|
||||||
|
/// Casts to a pointer of another type
|
||||||
|
pub const fn cast<U: Pointable<PointerMetaTiny = ()>>(self) -> ConstPtr<U, BASE>
|
||||||
|
where
|
||||||
|
T: Pointable<PointerMetaTiny = ()>,
|
||||||
|
{
|
||||||
|
ConstPtr::from_raw_parts(self.ptr, self.meta)
|
||||||
|
}
|
||||||
|
/// Use the pointer value in a new pointer of another type
|
||||||
|
pub const fn with_metadata_of<U: Pointable + ?Sized>(
|
||||||
|
self,
|
||||||
|
val: ConstPtr<U, BASE>,
|
||||||
|
) -> ConstPtr<U, BASE> {
|
||||||
|
ConstPtr::from_raw_parts(self.ptr, val.meta)
|
||||||
|
}
|
||||||
|
// TODO: as_mut
|
||||||
|
/// Gets the address portion of the pointer
|
||||||
|
pub const fn addr(self) -> u16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.ptr
|
||||||
|
}
|
||||||
|
/// Gets the address portion of the pointer and exposeses the provenenance part
|
||||||
|
pub const fn expose_addr(self) -> u16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.ptr
|
||||||
|
}
|
||||||
|
/// Creates a new pointer with the given address
|
||||||
|
pub const fn with_addr(self, addr: u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
Self::from_raw_parts(addr, self.meta)
|
||||||
|
}
|
||||||
|
/// Creates a new pointer by mapping self’s address to a new one
|
||||||
|
pub fn map_addr(self, f: impl FnOnce(u16) -> u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.with_addr(f(self.addr()))
|
||||||
|
}
|
||||||
|
/// Decompose a pointer into its address and metadata
|
||||||
|
pub fn to_raw_parts(self) -> (ConstPtr<(), BASE>, <T as Pointable>::PointerMetaTiny) {
|
||||||
|
(ConstPtr::from_raw_parts(self.ptr, ()), self.meta)
|
||||||
|
}
|
||||||
|
// TODO: as_ref
|
||||||
|
// TODO: as_ref_unchecked
|
||||||
|
// TODO: as_uninit_ref
|
||||||
|
/// Calculates the offset from a pointer
|
||||||
|
pub const unsafe fn offset(self, count: i16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wrapping_offset(count)
|
||||||
|
}
|
||||||
|
/// Calculates the offset from a pointer using wrapping arithmetic
|
||||||
|
pub const fn wrapping_offset(mut self, count: i16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.ptr = self
|
||||||
|
.ptr
|
||||||
|
.wrapping_add_signed(count.wrapping_mul(core::mem::size_of::<T>() as i16));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
/// Calculates the distance between two pointers
|
||||||
|
pub const unsafe fn offset_from(self, origin: Self) -> i16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wrapping_offset_from(origin)
|
||||||
|
}
|
||||||
|
/// Calculates the distance between two pointers using wrapping arithmetic
|
||||||
|
pub const fn wrapping_offset_from(self, origin: Self) -> i16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
(origin.ptr as i16)
|
||||||
|
.wrapping_sub(self.ptr as i16)
|
||||||
|
.wrapping_div(core::mem::size_of::<T>() as i16)
|
||||||
|
}
|
||||||
|
/// calculates the distance between two pointers where it is known that self is equal or
|
||||||
|
/// greater than origin
|
||||||
|
pub unsafe fn sub_ptr(self, origin: Self) -> u16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
u16::try_from(self.wrapping_offset_from(origin)).unwrap_unchecked()
|
||||||
|
}
|
||||||
|
/// Calculates the offset from a pointer
|
||||||
|
pub const unsafe fn add(self, count: u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.offset(count as i16)
|
||||||
|
}
|
||||||
|
/// Calculates the offset from a pointer
|
||||||
|
pub const unsafe fn sub(self, count: u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.offset((count as i16).wrapping_neg())
|
||||||
|
}
|
||||||
|
/// Calculates the offset from a pointer using wrapping arithmetic
|
||||||
|
pub const fn wrapping_add(self, count: u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wrapping_offset(count as i16)
|
||||||
|
}
|
||||||
|
/// Calculates the offset from a pointer using wrapping arithmetic
|
||||||
|
pub const fn wrapping_sub(self, count: u16) -> Self
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wrapping_offset((count as i16).wrapping_neg())
|
||||||
|
}
|
||||||
|
/// Reads the value from self without moving it. this leaves the memory in self unchanged.
|
||||||
|
pub unsafe fn read(self) -> T
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wide().read()
|
||||||
|
}
|
||||||
|
/// Performs a volatile read of the value from self without moving it. this leaves the memory in self unchanged.
|
||||||
|
pub unsafe fn read_volatile(self) -> T
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wide().read_volatile()
|
||||||
|
}
|
||||||
|
/// Reads the value from self without moving it. this leaves the memory in self unchanged.
|
||||||
|
pub unsafe fn read_unaligned(self) -> T
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
self.wide().read_unaligned()
|
||||||
|
}
|
||||||
|
// TODO: copy_to
|
||||||
|
// TODO: copy_to_nonoverlapping
|
||||||
|
pub const fn align_offset(self, align: u16) -> u16
|
||||||
|
where
|
||||||
|
T: Sized,
|
||||||
|
{
|
||||||
|
if !align.is_power_of_two() {
|
||||||
|
panic!("align must be a power of two");
|
||||||
|
}
|
||||||
|
(self.ptr.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1))
|
||||||
|
.wrapping_sub(self.ptr)
|
||||||
|
.wrapping_div(core::mem::size_of::<T>() as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable<PointerMetaTiny = ()>, const BASE: usize> ConstPtr<[T], BASE> {
|
||||||
|
pub const fn len(self) -> u16 {
|
||||||
|
self.meta
|
||||||
|
}
|
||||||
|
pub const fn as_ptr(self) -> ConstPtr<T, BASE> {
|
||||||
|
ConstPtr::from_raw_parts(self.ptr, ())
|
||||||
|
}
|
||||||
|
// TODO: as_uninit_slice
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> PartialEq for ConstPtr<T, BASE>
|
||||||
|
{
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
(self.ptr == other.ptr) && (self.meta == other.meta)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> Eq for ConstPtr<T, BASE> {}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> Ord for ConstPtr<T, BASE>
|
||||||
|
{
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
self.ptr.cmp(&other.ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> PartialOrd for ConstPtr<T, BASE>
|
||||||
|
{
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized + Unsize<U>, U: Pointable, const BASE: usize> CoerceUnsized<ConstPtr<U, BASE>> for ConstPtr<T, BASE>
|
||||||
|
where <T as Pointable>::PointerMetaTiny: CoerceUnsized<<U as Pointable>::PointerMetaTiny>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> Clone for ConstPtr<T, BASE> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> Copy for ConstPtr<T, BASE> {}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> fmt::Debug for ConstPtr<T, BASE>
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> Hash for ConstPtr<T, BASE> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_usize(BASE);
|
||||||
|
state.write_u16(self.ptr);
|
||||||
|
self.meta.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Pointable + ?Sized, const BASE: usize> fmt::Pointer for ConstPtr<T, BASE>
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
fmt::Pointer::fmt(&self.wide(), f)
|
||||||
|
}
|
||||||
|
}
|
5
lib/tinyptr/src/ptr/mod.rs
Normal file
5
lib/tinyptr/src/ptr/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
//! Raw pointers
|
||||||
|
|
||||||
|
mod const_ptr;
|
||||||
|
#[doc(inline)]
|
||||||
|
pub use const_ptr::*;
|
Loading…
Reference in a new issue