Skip to content

[Bug] documentation / functionality to generate correct c++ code for generics when using serde-name#37

Description

@johnperry-math

馃悰 Bug

If you need to generate C++ code for a generic, documentation needs more information on how to obtain correct code, or serde-generate needs to generate valid code for C++ generics when using recommended procedure

To reproduce

Extended from the example in serde-name, recommended in serde-reflection docs.

use std::path::PathBuf;

use serde::{Deserialize, Serialize};
use serde_generate::SourceInstaller;
use serde_name::{DeserializeNameAdapter, SerializeNameAdapter};
use serde_reflection::{FormatHolder, Samples, Tracer, TracerConfig};

#[derive(Serialize, Deserialize)]
#[serde(remote = "Foo")] // Generates Foo::(de)serialize instead of implementing Serde traits.
struct Foo<T> {
    data: T,
}

impl<'de, T> Deserialize<'de> for Foo<T>
where
    T: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::de::Deserializer<'de>,
    {
        Foo::deserialize(DeserializeNameAdapter::new(
            deserializer,
            std::any::type_name::<Self>(),
        ))
    }
}

impl<T> Serialize for Foo<T>
where
    T: Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::ser::Serializer,
    {
        Foo::serialize(
            self,
            SerializeNameAdapter::new(serializer, std::any::type_name::<Self>()),
        )
    }
}

fn main() {
    // Testing the Deserialize implementation
    assert!(serde_name::trace_name::<Foo<u64>>()
        .unwrap()
        .ends_with("Foo<u64>"));

    // Testing the Serialize implementation
    use serde_reflection::*;
    let mut tracer = Tracer::new(TracerConfig::default());
    let mut samples = Samples::new();
    let (mut ident, _) = tracer
        .trace_value(&mut samples, &Foo { data: 1u64 })
        .unwrap();
    ident.normalize().unwrap();
    assert!(matches!(ident, Format::TypeName(s) if s.ends_with("Foo<u64>")));
    let registry = tracer.registry().unwrap();
    let config = serde_generate::CodeGeneratorConfig::new("generic_to_cpp".to_string())
        .with_encodings(vec![serde_generate::Encoding::Bincode]);
    let installer = serde_generate::cpp::Installer::new(PathBuf::from("a_new_lib"));
    installer.install_module(&config, &registry).unwrap();
    installer.install_bincode_runtime().unwrap();
    installer.install_serde_runtime().unwrap();
}

Generated C++ code

#pragma once

#include "serde.hpp"
#include "bincode.hpp"

namespace generic_to_cpp {

    struct generic_to_cpp::Foo<u64> {
        uint64_t data;
// and more like this

馃槩

Expected C++ code

  • ideally, something like
#include "serde.hpp"
#include "bincode.hpp"

namespace generic_to_cpp {

    template <typename T>
    struct Foo{
        T data;
// etc.
}
  • Otherwise, an example that shows how to build on the example in serde-name to obtain valid C++ code for the instantiated type.

System information

Please complete the following information:

  • Serde Reflection version 0.3.6
  • Rust version 1.74.0

Additional context

I've also tried this at least with trace_type.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions