dtolnay / serde-yaml

Strongly typed YAML library for Rust
Apache License 2.0
965 stars 164 forks source link

Deserializer only acknowledges first line of YAML #406

Closed butterflyhigh closed 10 months ago

butterflyhigh commented 10 months ago

I am trying to deserialize a YAML file into a struct.

The YAML file (it's long, and the problem appears on line 1, so I truncated it):

name: New Project
comment: ""
output_dir: Vocal
cache_dir: UCache
ustx_version: "0.6"
resolution: 480
bpm: 120
beat_per_bar: 4
...

The struct:

#[derive(Deserialize, Debug)]
struct UstxFile {
    name: String,
    comment: String,
    output_dir: String,
    cache_dir: String,
    ustx_version: f32,
    resolution: isize,
    bpm: isize,
    beat_per_bar: isize,
...

The error message: Error: Error("missing fieldcomment", line: 1, column: 2)

I submitted the file into yamllint.com, and it seems to be a valid YAML file, so I believe this is a bug. Thank you for your time.

dtolnay commented 10 months ago

I was not able to reproduce this. After fixing the type of ustx_version from f32 to String, it deserializes correctly into:

UstxFile {
    name: "New Project",
    comment: "",
    output_dir: "Vocal",
    cache_dir: "UCache",
    ustx_version: "0.6",
    resolution: 480,
    bpm: 120,
    beat_per_bar: 4,
}

If you are stuck getting the same thing to work, I would recommend taking your issue to any of the resources shown in https://www.rust-lang.org/community. This library is one of the most widely used Rust libraries and plenty of people will be able to provide guidance about it.

butterflyhigh commented 10 months ago

I think I truncated out whatever was causing the error by accident. When I just use the shortened version, it works fine. Sorry about that.

The full file:

Long ``` name: New Project comment: "" output_dir: Vocal cache_dir: UCache ustx_version: "0.6" resolution: 480 bpm: 120 beat_per_bar: 4 beat_unit: 4 expressions: dyn: name: dynamics (curve) abbr: dyn type: Curve min: -240 max: 120 default_value: 0 is_flag: false flag: "" pitd: name: pitch deviation (curve) abbr: pitd type: Curve min: -1200 max: 1200 default_value: 0 is_flag: false flag: "" clr: name: voice color abbr: clr type: Options min: 0 max: -1 default_value: 0 is_flag: false options: [] eng: name: resampler engine abbr: eng type: Options min: 0 max: 1 default_value: 0 is_flag: false options: - "" - worldline vel: name: velocity abbr: vel type: Numerical min: 0 max: 200 default_value: 100 is_flag: false flag: "" vol: name: volume abbr: vol type: Numerical min: 0 max: 200 default_value: 100 is_flag: false flag: "" atk: name: attack abbr: atk type: Numerical min: 0 max: 200 default_value: 100 is_flag: false flag: "" dec: name: decay abbr: dec type: Numerical min: 0 max: 100 default_value: 0 is_flag: false flag: "" gen: name: gender abbr: gen type: Numerical min: -100 max: 100 default_value: 0 is_flag: true flag: g genc: name: gender (curve) abbr: genc type: Curve min: -100 max: 100 default_value: 0 is_flag: false flag: "" bre: name: breath abbr: bre type: Numerical min: 0 max: 100 default_value: 0 is_flag: true flag: B brec: name: breathiness (curve) abbr: brec type: Curve min: -100 max: 100 default_value: 0 is_flag: false flag: "" lpf: name: lowpass abbr: lpf type: Numerical min: 0 max: 100 default_value: 0 is_flag: true flag: H mod: name: modulation abbr: mod type: Numerical min: 0 max: 100 default_value: 0 is_flag: false flag: "" alt: name: alternate abbr: alt type: Numerical min: 0 max: 16 default_value: 0 is_flag: false flag: "" shft: name: tone shift abbr: shft type: Numerical min: -36 max: 36 default_value: 0 is_flag: false flag: "" shfc: name: tone shift (curve) abbr: shfc type: Curve min: -1200 max: 1200 default_value: 0 is_flag: false flag: "" tenc: name: tension (curve) abbr: tenc type: Curve min: -100 max: 100 default_value: 0 is_flag: false flag: "" voic: name: voicing (curve) abbr: voic type: Curve min: 0 max: 100 default_value: 100 is_flag: false flag: "" exp_selectors: - dyn - pitd - clr - eng - vel exp_primary: 0 exp_secondary: 1 key: 0 time_signatures: - bar_position: 0 beat_per_bar: 4 beat_unit: 4 tempos: - position: 0 bpm: 120 tracks: - singer: DefokoVCV phonemizer: OpenUtau.Plugin.Builtin.JapaneseVCVPhonemizer renderer_settings: renderer: WORLDLINE-R track_name: Track1 track_color: Blue mute: false solo: false volume: 0 pan: 0 voice_color_names: - "" voice_parts: - name: New Part comment: "" track_no: 0 position: 1920 notes: - position: 960 duration: 480 tone: 63 lyric: do pitch: data: - x: -25 y: 0 shape: io - x: 25 y: 0 shape: io snap_first: true vibrato: length: 0 period: 95 depth: 61.9 in: 25 out: 25 shift: 0 drift: 0 vol_link: 0 phoneme_expressions: [] phoneme_overrides: [] - position: 1440 duration: 480 tone: 65 lyric: re pitch: data: - x: -25 y: -20 shape: io - x: 25 y: 0 shape: io snap_first: true vibrato: length: 0 period: 95 depth: 61.9 in: 25 out: 25 shift: 0 drift: 0 vol_link: 0 phoneme_expressions: [] phoneme_overrides: [] - position: 1920 duration: 480 tone: 67 lyric: mi pitch: data: - x: -25 y: -20 shape: io - x: 25 y: 0 shape: io snap_first: true vibrato: length: 0 period: 95 depth: 61.9 in: 25 out: 25 shift: 0 drift: 0 vol_link: 0 phoneme_expressions: [] phoneme_overrides: [] curves: [] wave_parts: [] ```

The full struct(s):

#[derive(Deserialize, Debug)]
struct UstxFile {
    name: String,
    comment: String,
    output_dir: String,
    cache_dir: String,
    ustx_version: String,
    resolution: isize,
    bpm: isize,
    beat_per_bar: isize,
    beat_unit: isize,
    expressions: Vec<Expression>,
    exp_selectors: Vec<String>,
    exp_primary: isize,
    exp_secondary: isize,
    key: isize,
    time_signatures: Vec<TimeSig>,
    tempos: Vec<Tempo>,
    tracks: Vec<Track>
}

#[derive(Deserialize, Debug)]
struct Part {
    name: String,
    comment: String,
    track_no: isize,
    position: isize,
}

#[derive(Deserialize, Debug)]
struct Note {
    position: isize,
    duration: isize,
    tone: isize,
    lyric: String,
    pitch: PitchData,
    vibrato: Vibrato,
    phoneme_expressions: Vec<PhonemeExpression>
}

#[derive(Deserialize, Debug)]
struct PhonemeOverride {
    index: usize,
    overlap_delta: f64
}

#[derive(Deserialize, Debug)]
struct PhonemeExpression {
    index: usize,
    abbr: String,
    value: isize
}

#[derive(Deserialize, Debug)]
struct Vibrato {
    length: isize, 
    period: isize, 
    depth: isize, 
    fade_in: isize, 
    fade_out: isize,
    shift: isize, 
    drift: isize, 
    vol_link: isize
}

#[derive(Deserialize, Debug)]
struct Pitch {
    data: Vec<PitchData>,
    snap_first: bool
}

#[derive(Deserialize, Debug)]
struct PitchData {
    x: f64,
    y: f64,
    shape: String
}

#[derive(Deserialize, Debug)]
struct Track {
    singer: String,
    phonemizer: String,
    renderer_settings: RendererSettings,
    track_name: String,
    track_color: String,
    mute: bool,
    solo: bool,
    volume: f64,
    pan: f64,
    voice_color_names: Vec<String>
}

#[derive(Deserialize, Debug)]
struct RendererSettings {

}

#[derive(Deserialize, Debug)]
struct Expression {
    name: String,
    abbr: String,
    value_type: String, // change this to enum
    min: isize,
    max: isize,
    default_value: isize,
    is_flag: bool,
    flag: String
}

#[derive(Deserialize, Debug)]
struct TimeSig {
    bar_position: isize,
    beat_per_bar: isize,
    beat_unit: isize,
}

#[derive(Deserialize, Debug)]
struct Tempo {
    position: isize,
    bpm: isize
}

Apologies for the confusion/