Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Derive: Lists requires child type to implement FromStr and Display, which are not implemented #7

Open
tobz1000 opened this issue Sep 8, 2020 · 3 comments

Comments

@tobz1000
Copy link

tobz1000 commented Sep 8, 2020

Attempting to generate types for this .xsd:
https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/os/schemas/edm.xsd

I get the compile errors:

error[E0277]: the trait bound `TPath: std::str::FromStr` is not satisfied
  --> src\main.rs:15:17
   |
15 | #[derive(Debug, XmlSchema)]
   |                 ^^^^^^^^^ the trait `std::str::FromStr` is not implemented for `TPath`
   |
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0599]: no method named `to_string` found for reference `&TPath` in the current scope
  --> src\main.rs:15:17
   |
15 | #[derive(Debug, XmlSchema)]
   |                 ^^^^^^^^^
   |                 |
   |                 method not found in `&TPath`
   |                 doesn't satisfy `TPath: std::fmt::Display`
   |                 doesn't satisfy `TPath: std::string::ToString`
   |
   = note: the method `to_string` exists but the following trait bounds were not satisfied:
           `TPath: std::fmt::Display`
           which is required by `TPath: std::string::ToString`
           `&TPath: std::fmt::Display`
           which is required by `&TPath: std::string::ToString`
   = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

The relevant generated code looks like (note the .parse() and .to_string()):

#[derive(Clone, Debug, Default, PartialEq)]
pub struct TEnumMemberList {
    items: Vec<TPath>,
}
impl YaDeserialize for TEnumMemberList {
    fn deserialize<R: Read>(reader: &mut yaserde::de::Deserializer<R>) -> Result<Self, String> {
        loop {
            match reader.next_event()? {
                xml::reader::XmlEvent::StartElement { .. } => {}
                xml::reader::XmlEvent::Characters(ref text_content) => {
                    let items: Vec<TPath> = text_content
                        .split(' ')
                        .map(|item| item.to_owned())
                        .map(|item| item.parse().unwrap())
                        .collect();
                    return Ok(TEnumMemberList { items });
                }
                _ => {
                    break;
                }
            }
        }
        Err("Unable to parse attribute".to_string())
    }
}
impl YaSerialize for TEnumMemberList {
    fn serialize<W: Write>(&self, writer: &mut yaserde::ser::Serializer<W>) -> Result<(), String> {
        let content = self
            .items
            .iter()
            .map(|item| item.to_string())
            .collect::<Vec<String>>()
            .join(" ");
        let data_event = xml::writer::XmlEvent::characters(&content);
        writer.write(data_event).map_err(|e| e.to_string())?;
        Ok(())
    }
    fn serialize_attributes(
        &self,
        mut source_attributes: Vec<xml::attribute::OwnedAttribute>,
        mut source_namespace: xml::namespace::Namespace,
    ) -> Result<
        (
            Vec<xml::attribute::OwnedAttribute>,
            xml::namespace::Namespace,
        ),
        String,
    > {
        Ok((source_attributes, source_namespace))
    }
}
pub struct TPath {
    #[yaserde(text)]
    pub content: std::string::String,
}

Here is the code I'm using to derive, in case there's something wrong with it:

#[macro_use]
extern crate yaserde_derive;

use std::io::prelude::*;
use xml_schema_derive::XmlSchema;
use yaserde::{YaDeserialize, YaSerialize};

#[derive(Debug, XmlSchema)]
#[xml_schema(
    source = "https://docs.oasis-open.org/odata/odata-csdl-xml/v4.01/os/schemas/edm.xsd",
    target_prefix = "edm"
)]
struct EntityDataModel;
@MarcAntoine-Arnaud
Copy link
Contributor

Hello @tobz1000 ,

I think it's a prefix issue, I have to look on it in details.
In this case, TPath is defined locally but it's referenced with the prefix edm that is defined at the beginning xmlns:edm="http://docs.oasis-open.org/odata/ns/edm"

I think it's possible that xml-schema does not handle correctly that.
I'll test that when I have more time ...

Marc-Antoine

@NelDav
Copy link
Contributor

NelDav commented Oct 20, 2020

I have the same Issue with slightly differences. The error message only tells me that std::fmt::Display is not implemented.
Furthermore, I do not define any prefix.
Only want to let you know, that the issue varies in different cases.

Unfortunately I cannot provide the whole schema file, but I try to provide the relevant parts if you need.

I get the following error message:

error: proc-macro derive panicked
 --> src\main.rs:9:17
  |
9 | #[derive(Debug, XmlSchema)] 
  |                 ^^^^^^^^^
  |
  = help: message: not implemented
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: `StorageType` doesn't implement `std::fmt::Display`
 --> src\main.rs:9:17
  |
9 | #[derive(Debug, XmlSchema)] 
  |                 ^^^^^^^^^ `StorageType` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `StorageType`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: required because of the requirements on the impl of `std::fmt::Display` for `&StorageType`
  = note: required by `std::fmt::Display::fmt`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

My code is nearly the same, you provided on the cargo site:

#[macro_use]
extern crate yaserde_derive;

use std::io::prelude::*;
use xml_schema_derive::XmlSchema;
use yaserde::{YaDeserialize, YaSerialize};

#[derive(Debug, XmlSchema)] 
#[xml_schema(source = "target/feat/Schema.xsd")]
struct MySchema;

Note, that I do not define any target_prefix because if I do #[xml_schema(source = "target/feat/Schema.xsd", target_prefix = "xs")], I get the following error:

error: proc-macro derive panicked
 --> src\main.rs:8:17
  |
8 | #[derive(Debug, XmlSchema)] 
  |                 ^^^^^^^^^
  |
  = help: message: a prefix attribute, but no target namespace is defined, please remove the prefix parameter

@NelDav
Copy link
Contributor

NelDav commented Oct 21, 2020

After some further research I think the problem is that the macro #[yaserde(rename = "Storage")] needs the implementation of std::fmt::Display to serialize the struct StorageType.
I don't know how #[yaserde(rename = "Storage")] is intendet to work, so I don't know if there is a bug in yaserde or in xml-schema.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants