Skip to content

Instantly share code, notes, and snippets.

@haberman
Last active January 3, 2016 17:29
Show Gist options
  • Save haberman/8496516 to your computer and use it in GitHub Desktop.
Save haberman/8496516 to your computer and use it in GitHub Desktop.
Prototype for a scheme for upb Rust wrappers for upb.
// Prototype for a scheme for upb Rust wrappers for upb.
//
// Output (when linked with fakeupb.c):
// C: new()
// C: number() = 1
// Number: 1
// C: setnumber(5)
// C: number() = 5
// Number: 5
// C: freeze() = 1
// C: ref() = 1 -> 2
// C: unref() = 2 -> 1
// C: number() = 5
// Number: 5
// C: unref() = 1 -> 0
struct FieldDef;
#[link(name = "fakeupb")]
extern {
fn upb_fielddef_setnumber(f: *mut FieldDef, number: u32) -> bool;
fn upb_fielddef_number(f: *FieldDef) -> u32;
fn upb_fielddef_new() -> *FieldDef;
fn upb_fielddef_ref(f: *FieldDef);
fn upb_fielddef_unref(f: *FieldDef);
fn upb_fielddef_freeze(f: *FieldDef);
}
/****************************************************************************
* FieldDefFrozenRef
****************************************************************************/
struct FieldDefFrozenRef {
priv ptr: *FieldDef,
}
impl FieldDefFrozenRef {
fn get<'a>(&'a self) -> &'a FieldDef {
unsafe { &*self.ptr }
}
}
impl Clone for FieldDefFrozenRef {
fn clone(&self) -> FieldDefFrozenRef {
unsafe { upb_fielddef_ref(self.ptr); }
FieldDefFrozenRef { ptr: self.ptr }
}
}
impl Drop for FieldDefFrozenRef {
fn drop(&mut self) {
unsafe { upb_fielddef_unref(self.ptr); }
}
}
/****************************************************************************
* FieldDefMutableRef
****************************************************************************/
struct FieldDefMutableRef {
priv ptr: *FieldDef,
}
impl FieldDefMutableRef {
fn get<'a>(&'a self) -> &'a mut FieldDef {
unsafe { std::cast::transmute_mut(&*self.ptr) }
}
fn freeze(self) -> FieldDefFrozenRef {
unsafe {
upb_fielddef_freeze(self.ptr);
upb_fielddef_ref(self.ptr);
}
FieldDefFrozenRef { ptr: self.ptr }
}
}
impl Drop for FieldDefMutableRef {
fn drop(&mut self) {
unsafe { upb_fielddef_unref(self.ptr); }
}
}
// No Clone because the mutable ref should never be cloned.
/****************************************************************************
* FieldDef
****************************************************************************/
impl FieldDef {
fn new() -> FieldDefMutableRef {
let f: *FieldDef = unsafe { upb_fielddef_new() };
FieldDefMutableRef { ptr: f }
}
fn set_number(&mut self, number: u32) -> bool {
unsafe { upb_fielddef_setnumber(self, number) }
}
fn number(&self) -> u32 {
unsafe { upb_fielddef_number(self) }
}
}
fn main() {
let mutable_def = FieldDef::new();
std::io::println(format!("Number: {:u}", mutable_def.get().number()));
mutable_def.get().set_number(5);
std::io::println(format!("Number: {:u}", mutable_def.get().number()));
let frozen_def = mutable_def.freeze();
std::io::println(format!("Number: {:u}", frozen_def.get().number()));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment