I want to customize the output of a struct called FooOut but I don't want to change the debug output of the internal field FooIn which is inside FooOut. Consider the Rust code:
#[derive(Default)]
struct FooOut {
num1: u32,
num2: u32,
obj: FooIn,
}
#[derive(Debug, Default)]
struct FooIn {
bval: bool,
list: Vec<u32>,
}
impl std::fmt::Debug for FooOut {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "FooOut {{ sum: {}, num1: {}, num2: {}, obj: {} }}",
self.num1 + self.num2,
self.num1,
self.num2,
self.obj) // self.obj is not working without implementing it too
}
}
In the above code, I am trying to customize the debug output of FooOut (by adding sum), but I don't want to customize/reimplement the debug output of FooIn. Is there any way to do that?
Instead of manually constructing the debug string yourself, I recommend that you use Formatter::debug_struct (or one of its sibling functions) instead:
impl std::fmt::Debug for FooOut {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("FooOut")
.field("sum", &(self.num1 + self.num2))
.field("num1", &self.num1)
.field("num2", &self.num2)
.field("obj", &self.obj)
.finish()
}
}
Playground example
This is what #[derive(Debug)] is using to build the default debug string for an object. This also has the added advantage that you get both the compact debug string with {:?} and the alternative, expanded debug string with {:#?}.
( Adding Alex Larionov's comment as the answer. )
Instead of using {} for FooIn, I need to use {:?} to use the debug output of FooIn
impl std::fmt::Debug for FooOut {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "FooOut {{ sum: {}, num1: {}, num2: {}, obj: {:?} }}",
self.num1 + self.num2,
self.num1,
self.num2,
self.obj)
}
}
Related
I need to to use custom implementations of Serialize and Deserialize, but i could not figure out how to do something like #[serde(flatten)] does, does anyone know?
Note: i know i could completely re-write the full implementation of the lower elements into the higher one, but the lower elements implement Serialize (and Deserialize), so i am searching for a way to add that to something like serialize_struct.
#[derive(Debug, Serialize, Deserialize, PartialEq)]
struct Nested {
somefield2: String,
}
#[derive(Debug, PartialEq)]
struct TopLevel {
somefield1: usize,
nested: Nested,
}
impl Serialize for TopLevel {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// How to do this properly?
let mut do_struct = serializer.serialize_struct("Named", 2)?;
do_struct.serialize_field("somefield1", &self.somefield1)?;
// how to add everything from "self.nested" as the same level as this one?
// JSON example: { somefield1: 0, somefield2: 0 }
return do_struct.end();
}
}
impl<'de> Deserialize<'de> for TopLevel {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
// Same question as in "Serialize", how to do this properly in here?
// Here is currently no example code, because i try to figure out "Serialize" first
todo!();
}
}
Versions used:
serde: 1.0.133
rust: 1.58.1
Note: i have already read Implementing Serialize and tried to search issues / stackoverflow but could not find anything related to that.
You could try doing something like this for Serialize and something similar for Deserialize:
struct FakeStructFlatteningSerializer<'a, SS: SerializeStruct>(&'a mut SS);
impl Serializer<'a, SS: SerializeStruct> for FakeStructFlatteningSerializer<'a, SS> {
type Ok = ();
type Error = SS::Error;
type SerializeStruct = FakeStructFlatteningSerializeStruct<'a, SS>;
// return Impossible for everything else
fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct, Self::Error> {
// ignore name and len!
Ok(FakeStructFlatteningSerializeStruct(self.0))
}
}
struct FakeStructFlatteningSerializeStruct<'a, SS: SerializeStruct>(&'a mut SS);
impl<'a, SS: SerializeStruct> SerializeStruct for FakeStructFlatteningSerializeStruct<'a, SS> {
type Ok = ();
type Error = SS::Error;
fn serialize_field<T: Serialize + ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> {
self.0.serialize_field(key, value)
}
fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> {
self.0.skip_field(key)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
// ignore!
Ok(())
}
}
impl Serialize for TopLevel {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// len needs to include the flattened fields
let mut do_struct = serializer.serialize_struct("Named", 3)?;
do_struct.serialize_field("somefield1", &self.somefield1)?;
self.nested.serialize(FakeStructFlatteningSerializer(&mut do_struct));
return do_struct.end();
}
}
You could alternatively try to figure out how Serde does it; this might be where: https://github.com/serde-rs/serde/blob/dc0c0dcba17dd8732cd8721a7ef556afcb04c6c0/serde_derive/src/ser.rs#L953-L1037, https://github.com/serde-rs/serde/blob/fb2fe409c8f7ad6c95e3096e5e9ede865c8cfb49/serde_derive/src/de.rs#L2560-L2578
In rust, I want in my impl fmt::Display for MainStruct, to be able to print another struct.
#[derive(Clone, Default)]
pub struct MainStruct {
pub child: Option<ChildStruct>
}
#[derive(Clone, Default)]
pub struct ChildStruct {
pub field: String
}
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child)
}
}
impl std::fmt::Display for ChildStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "ChildStruct: field:{}", self.field)
}
}
I have tried with the default {} formatter, and with the {:?} formatter, but without any success.
The Problem is that Option<T> has not implemented the Display trait. So you have to get the value out of the option. The easiest to do so is .unwrap(). This however panics if the option is None. (other methods for unpacking are expect, match, …)
If you use .unwrap() the value is moved out of the Option. So the Option would now be invalid as it would not contain anything anymore. The compiler prevents this with an error cannot move out of 'self.child'.
So what you actually want is a reference that does not consume the child. So you want &T or &mut T from the Option. You can do that by using the .as_ref() to convert Option<T> to Option<&T>. Then if you do .unwrap() on that the compiler wont complain anymore as you just copy a &T pointer.
so your code compiles if you change the following:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child:{}", self.child.as_ref().unwrap())
}
}
Since Option does not implement Display, you have to write some logic yourself to handle two possible cases. The simplest way might be to just match on the Option explicitly:
impl std::fmt::Display for MainStruct {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "MainStruct: child: ")?;
match self.child.as_ref() {
Some(child) => write!(f, "Some({})", child),
None => write!(f, "None"),
}
}
}
Here's the playground with a short test case.
It is considered good practice to #[derive(Debug)] for most structs you create to aid in debugging. However, this is not possible if your struct contains a type without Debug, such as traits. But if the trait is under my control, is there something I can do to let users' implementations of said trait show up in the debug message?
I could require that people who implement my trait also implement Debug, but I don't like having to add that arbitrary requirement:
trait MyTrait: Debug { ... }
I could just implement Debug for my trait:
trait MyTrait { ... }
impl Debug for MyTrait {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "MyTrait {{ ... }}")
}
}
This doesn't allow implementations to override Debug - it's almost as if the function is not virtual. How can I make this work?
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct A {
a: Box<Data>,
}
trait Data {}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data{{ ... }}")
}
}
#[derive(Debug)]
struct B(i32);
impl Data for B {}
fn main() {
let a = A{ a: Box::new(B(42)) };
println!("{:?}", a);
}
Outputs:
A { a: Data{ ... } }
What I want:
A { a: B(42) }
I only want the first output when B does not implement Debug.
You can create your own trait method. Types that wish to have enhanced debugging and implement Debug can delegate:
use std::fmt;
use std::fmt::{ Formatter, Debug };
#[derive(Debug)]
struct Container(Box<Data>);
trait Data {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Data {{ ... }}")
}
}
impl Debug for Data {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.debug_fmt(f)
}
}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {
fn debug_fmt(&self, f: &mut Formatter) -> fmt::Result {
self.fmt(f)
}
}
#[derive(Debug)]
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
An alternate solution that requires the unstable specialization feature:
#![feature(specialization)]
use std::fmt;
use std::fmt::{Formatter, Debug};
struct Container<D>(Box<D>) where D: Data;
impl<D> Debug for Container<D>
where D: Data
{
default fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container(Data {{ ... }})")
}
}
impl<D> Debug for Container<D>
where D: Data + Debug
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "Container({:?})", self.0)
}
}
trait Data {}
#[derive(Debug)]
struct Overrides(i32);
impl Data for Overrides {}
struct Defaults(i32);
impl Data for Defaults {}
fn main() {
let a = Container(Box::new(Overrides(42)));
println!("{:?}", a);
let a = Container(Box::new(Defaults(42)));
println!("{:?}", a);
}
Note that this places the burden on the container.
I'm currently in the process of implementing fmt::Display for a struct so that it will print out to the console. However The struct has a field which is a Vec of it's type.
Struct
pub struct Node<'a> {
pub start_tag: &'a str,
pub end_tag: &'a str,
pub content: String,
pub children: Vec<Node<'a>>,
}
Current fmt::Display (invalid)
impl<'a> fmt::Display for Node<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "START TAG: {:?}", self.start_tag);
write!(f, "CONTENT: {:?}", self.content);
for node in self.children {
write!(f, "CHILDREN:\n\t {:?}", node);
}
write!(f, "END TAG: {:?}", self.end_tag);
}
}
Desired Output
START TAG: "Hello"
CONTENT: ""
CHILDREN:
PRINTS CHILDREN WITH INDENT
END TAG: "World"
There is a (somewhat hidden) feature of Debug, you can use the format specifier {:#?} to pretty-print your object (with indents and multiple lines). If you rewrite your struct's elements to have the same order as your requested output and derive the Debug trait
#[derive(Debug)]
pub struct Node<'a> {
pub start_tag: &'a str,
pub content: String,
pub children: Vec<Node<'a>>,
pub end_tag: &'a str,
}
then your output can look like this:
Node {
start_tag: "Hello",
content: "",
children: [
Node {
start_tag: "Foo",
content: "",
children: [],
end_tag: "Bar"
}
],
end_tag: "World"
}
Try it out in the PlayPen
It seems you are confusing Display and Debug.
{:?} uses the Debug trait for formatting. You probably didn't implement Debug on your type, which is why you'd get an error. To use the Display trait, write {} in your format string.
write!(f, "CHILDREN:\n\t {}", node);
I have a linked-list sort of struct, using Option, Rc, and RefCell.
I'd like to implement fmt::Debug for it, but have run into the lovely "cannot move out of borrowed content" error.
use std::fmt;
use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Clone, Debug, Ord, Eq, PartialOrd, PartialEq)]
struct NodeId {id: String}
impl NodeId {
pub fn new(s: &str) -> NodeId { NodeId{id: s.to_string()}}
}
struct NodeInfo {
nodeid: NodeId,
prev: Option<Rc<RefCell<NodeInfo>>>,
next: Option<Rc<RefCell<NodeInfo>>>,
}
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {} {} )", self.nodeid.id,
match self.prev { None => "none".to_string(), Some(ref n) => n.borrow().nodeid.id},
match self.next { None => "none".to_string(), Some(ref n) => "some".to_string()},
)
}
}
fn main() {}
Ideally the debug output would be able to show me the ids of the .next and .previous nodes. But Rust is not allowing access to them. The attempt to .borrow() the content of the RefCell causes the error, but I cannot understand why.
Play with it here: http://is.gd/Sah7sT
Does RefCell::borrow() move the contents?
No. Calling it borrow and having it move would be pretty underhanded! ^_^
The problem is that you are trying to move the id out of your borrowed struct. This is a move because String isn't Copy:
n.borrow().nodeid.id
Instead, use clone to leave the current string where it is, and return a brand-new one:
n.borrow().nodeid.id.clone()
To expand on #Shepmaster's answer (which is absolutely correct), you can avoid having to copy the string in this case, by writing the id of the child nodes directly to the formatter.
I've chosen to use a newtype to avoid repetition:
impl fmt::Debug for NodeInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "NodeInfo( {} {:?} {:?} )", self.nodeid.id, ChildNode(&self.prev), ChildNode(&self.next))
}
}
struct ChildNode<'a>(&'a Option<Rc<RefCell<NodeInfo>>>);
impl<'a> fmt::Debug for ChildNode<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.0 {
Some(ref n) => write!(f, "{}", n.borrow().nodeid.id),
None => write!(f, "None"),
}
}
}