Skip to content

Instantly share code, notes, and snippets.

@InfiniteCoder01
Created August 12, 2025 16:23
Show Gist options
  • Save InfiniteCoder01/23b5056883988e186d8fe7baf58d41f2 to your computer and use it in GitHub Desktop.
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
#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)));
}
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));
}
@nigelwithrow
Copy link

nice

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment