Created
August 12, 2025 16:23
-
-
Save InfiniteCoder01/23b5056883988e186d8fe7baf58d41f2 to your computer and use it in GitHub Desktop.
Nigel's challenge of converting Rust to C in the most painful way possible
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <stddef.h> | |
#include <stdbool.h> | |
// Option implementation | |
#define option(T) option_ ## T | |
#define option_method(T, M) option_ ## T ## _ ## M | |
#define option_genimpl(T) \ | |
typedef struct { \ | |
bool tag; \ | |
T value; \ | |
} option(T); \ | |
\ | |
option(T) option_method(T, some) (T value) {\ | |
return (option(T)) { \ | |
.tag = true, \ | |
.value = value, \ | |
}; \ | |
}\ | |
\ | |
option(T) option_method(T, none) () {\ | |
return (option(T)) { \ | |
.tag = false, \ | |
}; \ | |
}\ | |
\ | |
bool option_method(T, eq) (\ | |
option(T) lhs,\ | |
option(T) rhs\ | |
) {\ | |
if (lhs.tag != rhs.tag) return false;\ | |
if (lhs.tag) return lhs.value == rhs.value;\ | |
return true;\ | |
} | |
option_genimpl(size_t); | |
// Trait impl | |
#define impl_assoc(T, S, A) T ## _ ## S ## _ ## A | |
#define impl_assoc2(T, S, A) impl_assoc(T, S, A) | |
// Peekable | |
#define peekable(T, I) peekable_ ## T ## _ ## I | |
#define peekable_method(T, I, M) peekable_ ## T ## _ ## I ## _ ## M | |
#define peekable_genimpl(T, I) \ | |
typedef struct { \ | |
T iter; \ | |
option(I) peeked; \ | |
} peekable(T, I);\ | |
\ | |
option(I) peekable_method(T, I, peek)(peekable(T, I) *self) {\ | |
if (!self->peeked.tag) {\ | |
self->peeked = impl_assoc(simple_iterator, T, next)(&self->iter);\ | |
}\ | |
\ | |
return self->peeked;\ | |
}\ | |
\ | |
option(I) impl_assoc2(simple_iterator, peekable(T, I), next)(peekable(T, I) *self) {\ | |
if (self->peeked.tag) {\ | |
option(I) tmp = self->peeked;\ | |
self->peeked = option_method(I, none)();\ | |
return tmp;\ | |
} else {\ | |
return impl_assoc(simple_iterator, T, next)(&self->iter);\ | |
}\ | |
}\ | |
\ | |
typedef I impl_assoc2(simple_iterator, peekable(T, I), item);\ | |
\ | |
peekable(T, I) iter_peekable(T iter) {\ | |
return (peekable(T, I)) {\ | |
.iter = iter,\ | |
.peeked = option_method(I, none)(),\ | |
};\ | |
} | |
// Iota implementation | |
typedef struct { | |
size_t field0; | |
} iota; | |
iota iota_new() { | |
return (iota) { | |
.field0 = 0, | |
}; | |
} | |
option_size_t impl_assoc(simple_iterator, iota, next)(iota *self) { | |
size_t prev = self->field0; | |
self->field0 = prev + 1; | |
return option_size_t_some(prev); | |
} | |
typedef size_t impl_assoc(simple_iterator, iota, item); | |
peekable_genimpl(iota, size_t) | |
// Main | |
#include <stdio.h> | |
int main() { | |
iota iota = iota_new(); | |
assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(0))); | |
assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(1))); | |
assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(2))); | |
assert(option_size_t_eq(impl_assoc(simple_iterator, iota, next)(&iota), option_size_t_some(3))); | |
peekable(iota, size_t) peekable_iota = iter_peekable(iota); | |
assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4))); | |
assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4))); | |
assert(option_size_t_eq(peekable_method(iota, size_t, peek)(&peekable_iota), option_size_t_some(4))); | |
assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(4))); | |
assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(5))); | |
assert(option_size_t_eq(impl_assoc2(simple_iterator, peekable(iota, size_t), next)(&peekable_iota), option_size_t_some(6))); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pub trait SimpleIterator { | |
type Item; | |
fn next(&mut self) -> Option<Self::Item>; | |
fn peekable(self) -> Peekable<Self, Self::Item> | |
where | |
Self: Sized, | |
{ | |
Peekable { | |
iter: self, | |
peeked: None, | |
} | |
} | |
} | |
pub struct Peekable<T, I> { | |
iter: T, | |
peeked: Option<I>, | |
} | |
impl<I: Clone, T: SimpleIterator<Item = I>> Peekable<T, I> { | |
pub fn peek(&mut self) -> Option<I> { | |
if self.peeked.is_none() { | |
self.peeked = self.iter.next(); | |
} | |
self.peeked.clone() | |
} | |
} | |
impl<I, T: SimpleIterator<Item = I>> SimpleIterator for Peekable<T, I> { | |
type Item = T::Item; | |
fn next(&mut self) -> Option<T::Item> { | |
match &self.peeked { | |
Some(_) => std::mem::replace(&mut self.peeked, None), | |
None => self.iter.next(), | |
} | |
} | |
} | |
pub struct Iota(usize); | |
impl Iota { | |
pub fn new() -> Self { | |
Iota(0) | |
} | |
} | |
impl SimpleIterator for Iota { | |
type Item = usize; | |
fn next(&mut self) -> Option<usize> { | |
let prev = self.0; | |
self.0 = prev + 1; | |
Some(prev) | |
} | |
} | |
fn main() { | |
let mut iota = Iota::new(); | |
assert_eq!(iota.next(), Some(0)); | |
assert_eq!(iota.next(), Some(1)); | |
assert_eq!(iota.next(), Some(2)); | |
assert_eq!(iota.next(), Some(3)); | |
let mut peekable_iota = iota.peekable(); | |
assert_eq!(peekable_iota.peek(), Some(4)); | |
assert_eq!(peekable_iota.peek(), Some(4)); | |
assert_eq!(peekable_iota.peek(), Some(4)); | |
assert_eq!(peekable_iota.next(), Some(4)); | |
assert_eq!(peekable_iota.next(), Some(5)); | |
assert_eq!(peekable_iota.next(), Some(6)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
nice