@@ -19,53 +19,74 @@ Missing features, test completeness, and more robust documentation may be added
1919
2020#### Decode
2121
22- Decoder's ` decode ` allows us to interact with FIT files directly through their original protocol messages' structure.
22+ Decoder's ` decode ` allows us to interact with FIT files directly through their original protocol messages' structure.
23+ First call will return either Ok(Some(fit)) or Err(err), never Ok(None).
24+ On next call, it may return Ok(None) to indicate that no more FIT sequence in the file.
2325
2426``` rust
25- use rustyfit :: {
26- Decoder ,
27- profile :: {mesgdef, typedef},
28- };
29- use std :: {fs :: File , io :: BufReader };
27+ use rustyfit :: {Decoder , profile :: {mesgdef, typedef}};
28+ use std :: {error :: Error , fs :: File , io :: BufReader };
3029
31- fn main () {
30+ fn main () -> Result <(), Box < dyn Error >> {
3231 let name = " Activity.fit" ;
33- let f = File :: open (name ). unwrap () ;
32+ let f = File :: open (name )? ;
3433 let br = BufReader :: new (f );
3534 let mut dec = Decoder :: new (br );
3635
37- let fit = dec . decode (). unwrap ();
36+ let fit = dec . decode ()? . unwrap (); // First decode call is either Ok(Some(fit)) or Err(err), never Ok(None).
3837
3938 println! (" file_header's data_size: {}" , fit . file_header. data_size);
4039 println! (" messages count: {}" , fit . messages. len ());
41- for field in & fit . messages[0 ]. fields { // first message: file_id
40+ for field in & fit . messages[0 ]. fields {
41+ // first message: file_id
4242 if field . num == mesgdef :: FileId :: TYPE {
4343 println! (" file type: {}" , typedef :: File (field . value. as_u8 ()));
4444 }
4545 }
46+
47+ Ok (())
48+
4649 // # Output:
4750 // file_header's data_size: 94080
4851 // messages count: 3611
4952 // file type: activity
5053}
54+ ```
55+
56+ The ` decode ` method can be invoked multiple times to decode chained FIT file until it return Ok(None) or Err(err).
57+ We can decode chained FIT file using ` while let ` , e.g:
5158
59+ ``` rust
60+ while let Some (fit ) = dec . decode ()? {
61+ println! (" file_header's data_size: {}" , fit . file_header. data_size);
62+ println! (" messages count: {}" , fit . messages. len ());
63+ for field in & fit . messages[0 ]. fields {
64+ // first message: file_id
65+ if field . num == mesgdef :: FileId :: TYPE {
66+ println! (" file type: {}" , typedef :: File (field . value. as_u8 ()));
67+ }
68+ }
69+ }
5270```
5371
5472#### Decode with Closure
5573
56- Decoder's ` decode_fn ` allow us to retrieve message definition or message data event as soon as it is being decoded. This way, users can have fine-grained control on how to interact with the data.
74+ Decoder's ` decode_with ` allow us to retrieve event data (FileHeader, MessageDefinition, Message, CRC) as soon as it is being decoded.
75+ This way, users can have fine-grained control on how to interact with the data.
5776
5877``` rust
5978use rustyfit :: {Decoder , DecoderEvent ,profile :: {mesgdef, typedef}};
60- use std :: {fs :: File , io :: BufReader };
79+ use std :: {error :: Error , fs :: File , io :: BufReader };
6180
62- fn main () {
81+ fn main () -> Result <(), Box < dyn Error >> {
6382 let name = " Activity.fit" ;
64- let f = File :: open (name ). unwrap () ;
83+ let f = File :: open (name )? ;
6584 let br = BufReader :: new (f );
6685 let mut dec = Decoder :: new (br );
6786
68- dec . decode_fn (| event | match event {
87+ dec . decode_with (| event | match event {
88+ DecoderEvent :: FileHeader (_ ) => {},
89+ DecoderEvent :: MessageDefinition (_ ) => {},
6990 DecoderEvent :: Message (mesg ) => {
7091 if mesg . num == typedef :: MesgNum :: SESSION {
7192 // Convert mesg into Session struct
@@ -76,17 +97,34 @@ fn main() {
7697 );
7798 }
7899 }
79- DecoderEvent :: MessageDefinition (_ ) => {}
80- })
81- . unwrap ();
100+ DecoderEvent :: Crc (_ ) => {}
101+ })? ;
102+
103+ Ok (())
82104
83105 // # Output
84106 // session:
85107 // start_time: 995749880
86108 // sport: stand_up_paddleboarding
87109 // num_laps: 1
88110}
111+ ```
112+
113+ The ` decode_with ` method can be invoked multiple times to decode chained FIT file until it return Ok(false) or Err(err).
89114
115+ ``` rust
116+ while dec . decode_with (| event | {
117+ if let DecoderEvent :: Message (mesg ) = event {
118+ if mesg . num == typedef :: MesgNum :: SESSION {
119+ // Convert mesg into Session struct
120+ let ses = mesgdef :: Session :: from (mesg );
121+ println! (
122+ " session:\ n start_time: {}\ n sport: {}\ n num_laps: {}" ,
123+ ses . start_time. 0 , ses . sport, ses . num_laps
124+ );
125+ }
126+ }
127+ })? {}
90128```
91129
92130#### DecoderBuilder
@@ -107,25 +145,14 @@ let mut dec: Decoder = DecoderBuilder::new(br)
107145Here is the example of manually encode FIT protocol using this library to give the idea how it works.
108146
109147``` rust
110- use std :: {
111- fs :: File ,
112- io :: {BufWriter , Write },
113- };
114-
115- use rustyfit :: {
116- Encoder ,
117- profile :: {
118- ProfileType , mesgdef,
119- typedef :: {self },
120- },
121- proto :: {FIT , Field , Message , Value },
122- };
123-
124- fn main () {
148+ use std :: {error :: Error , fs :: File , io :: {BufWriter , Write }};
149+ use rustyfit :: {Encoder , profile :: {ProfileType , mesgdef, typedef :: {self }}, proto :: {FIT , Field , Message , Value }};
150+
151+ fn main () -> Result <(), Box <dyn Error >> {
125152 let fout_name = " output.fit" ;
126- let fout = File :: create (fout_name ). unwrap () ;
127- let bw = BufWriter :: new (fout );
128- let mut enc = Encoder :: new (bw );
153+ let fout = File :: create (fout_name )? ;
154+ let mut bw = BufWriter :: new (fout );
155+ let mut enc = Encoder :: new (& mut bw );
129156
130157 let mut fit = FIT {
131158 messages : vec! [
@@ -159,7 +186,7 @@ fn main() {
159186 Field {
160187 num : mesgdef :: Record :: DISTANCE ,
161188 profile_type : ProfileType :: UINT32 ,
162- value : Value :: Uint16 (100 * 100 ), // 100 m
189+ value : Value :: Uint32 (100 * 100 ), // 100 m
163190 is_expanded : false ,
164191 },
165192 Field {
@@ -181,36 +208,26 @@ fn main() {
181208 .. Default :: default ()
182209 };
183210
184- enc . encode (& mut fit ). unwrap ();
185- bw . flush (). unwrap ();
186- }
211+ enc . encode (& mut fit )? ;
212+ bw . flush ()? ;
187213
214+ Ok (())
215+ }
188216```
189217
190218#### Encode using mesgdef module
191219
192220Alternatively, users can create messages using the mesgdef module for convenience.
193221
194222``` rust
195- use std :: {
196- fs :: File ,
197- io :: {BufWriter , Write },
198- };
199-
200- use rustyfit :: {
201- Encoder ,
202- profile :: {
203- mesgdef,
204- typedef :: {self },
205- },
206- proto :: {FIT , Message },
207- };
208-
209- fn main () {
223+ use std :: {error :: Error , fs :: File , io :: {BufWriter , Write }};
224+ use rustyfit :: {Encoder , profile :: {mesgdef, typedef :: {self }}, proto :: {FIT , Message }};
225+
226+ fn main () -> Result <(), Box <dyn Error >> {
210227 let fout_name = " output.fit" ;
211- let fout = File :: create (fout_name ). unwrap () ;
212- let bw = BufWriter :: new (fout );
213- let mut enc = Encoder :: new (bw );
228+ let fout = File :: create (fout_name )? ;
229+ let mut bw = BufWriter :: new (fout );
230+ let mut enc = Encoder :: new (& mut bw );
214231
215232 let mut fit = FIT {
216233 messages : vec! [
@@ -232,10 +249,11 @@ fn main() {
232249 .. Default :: default ()
233250 };
234251
235- enc . encode (& mut fit ). unwrap ();
236- bw . flush (). unwrap ();
237- }
252+ enc . encode (& mut fit )? ;
253+ bw . flush ()? ;
238254
255+ Ok (())
256+ }
239257```
240258
241259#### EncoderBuilder
0 commit comments