Skip to content

Commit

Permalink
- adjust the PgNode trait a bit
Browse files Browse the repository at this point in the history
- implement Rust's Display trait for all Node types
  • Loading branch information
eeeebbbbrrrr committed Nov 16, 2020
1 parent 8354093 commit eda0d55
Show file tree
Hide file tree
Showing 6 changed files with 19,238 additions and 1,606 deletions.
27 changes: 22 additions & 5 deletions pgx-pg-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
quote! {
use crate as pg_sys;
use pgx_macros::*;
use crate::PgNode;
}
),
format!("Unable to write bindings file for pg{}", major_version)
Expand Down Expand Up @@ -261,11 +262,27 @@ fn impl_pg_node(items: &Vec<syn::Item>) -> Result<Vec<syn::Item>, Box<dyn Error
for node_struct in node_set.into_iter() {
let struct_name = &node_struct.struct_.ident;

let impl_item: syn::Item = syn::parse2(quote! {
impl pg_sys::PgNode for #struct_name { }
})?;

pgnode_impls.push((struct_name.to_string(), impl_item));
// impl the PgNode trait for all nodes
pgnode_impls.push((
struct_name.to_string(),
syn::parse2(quote! {
impl pg_sys::PgNode for #struct_name {
type NodeType = #struct_name;
}
})?,
));

// impl Rust's Display trait for all nodes
pgnode_impls.push((
struct_name.to_string(),
syn::parse2(quote! {
impl std::fmt::Display for #struct_name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", crate::node_to_string_for_display(self.as_node_ptr() as *mut crate::Node))
}
}
})?,
));
}

// sort the pgnode impls by their struct name so that we have a consistent ordering in our bindings output
Expand Down
26 changes: 24 additions & 2 deletions pgx-pg-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,31 @@ pub use internal::pg12::*;
#[cfg(feature = "pg13")]
pub use internal::pg13::*;

/// A trait applied to all of Postgres' `pg_sys::Node` types and its subtypes
pub trait PgNode {
fn as_node(&self) -> *mut Self {
self as *const _ as *mut Self
type NodeType;

/// Represent this node as a mutable pointer of its type
#[inline]
fn as_node_ptr(&self) -> *mut Self::NodeType {
self as *const _ as *mut Self::NodeType
}
}

/// implementation function for `impl Display for $NodeType`
pub(crate) fn node_to_string_for_display(node: *mut crate::Node) -> String {
unsafe {
// crate::nodeToString() will never return a null pointer
let node_to_string = crate::nodeToString(node as *mut std::ffi::c_void);

let result = match std::ffi::CStr::from_ptr(node_to_string).to_str() {
Ok(cstr) => cstr.to_string(),
Err(e) => format!("<ffi error: {:?}>", e),
};

crate::pfree(node_to_string as *mut std::ffi::c_void);

result
}
}

Expand Down
Loading

0 comments on commit eda0d55

Please sign in to comment.