Skip to content

Instantly share code, notes, and snippets.

@DutchGhost
Created December 16, 2019 22:42
Show Gist options
  • Select an option

  • Save DutchGhost/8c2c9220cb5dd01dca2ed321ae45b46e to your computer and use it in GitHub Desktop.

Select an option

Save DutchGhost/8c2c9220cb5dd01dca2ed321ae45b46e to your computer and use it in GitHub Desktop.
Const lines iterator
#![feature(const_mut_refs)]
#![feature(const_fn)]
#![feature(const_if_match)]
#![feature(const_loop)]
#![feature(const_raw_ptr_deref)]
#![feature(const_fn_union)]
#![feature(const_raw_ptr_to_usize_cast)]
#![feature(const_saturating_int_methods)]
use std::marker::PhantomData;
struct RawLines<'a> {
ptr: usize,
len: usize,
_mark: PhantomData<&'a [u8]>
}
#[derive(Copy, Clone)]
#[repr(C)]
struct Fat {
ptr: *const u8,
len: usize,
}
#[repr(C)]
union Bytes<'a> {
fat: Fat,
bytes: &'a [u8]
}
impl <'a> RawLines<'a> {
pub const fn new(b: &'a [u8]) -> Self {
Self {
ptr: unsafe { b.as_ptr() as usize },
len: b.len(),
_mark: PhantomData
}
}
const fn is_empty(&self) -> bool {
self.len == 0
}
const fn as_ptr(&self) -> *const u8 {
self.ptr as *const _
}
const fn next(&mut self) -> Option<&'a [u8]> {
if self.is_empty() { return None }
let mut len = 0;
let start = self.ptr as *const u8;
// && is short circuit. if self is empty,
// it won't do the deref. Hopefully.
while !self.is_empty() && unsafe { *(self.as_ptr()) } != b'\n' {
self.ptr += 1;
self.len -= 1;
len += 1;
}
let ret = unsafe { Some(Bytes { fat: Fat { ptr: start, len }}.bytes) };
self.ptr += 1;
self.len = self.len.saturating_sub(1);
ret
}
}
fn main() {
let mut lines = RawLines::new(b"foo\nbar\n");
dbg!(lines.next());
dbg!(lines.next());
dbg!(lines.next());
dbg!(lines.next());
dbg!(b"foo");
dbg!(b"bar");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment