Skip to content

Commit f29b9f7

Browse files
committed
Simplify the shell example.
Now we can open multiple files at once, we don't need to be so careful in our tree code.
1 parent 111cc36 commit f29b9f7

File tree

1 file changed

+36
-49
lines changed

1 file changed

+36
-49
lines changed

examples/shell.rs

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@
6969
//! | `B:/BACKUP.000/NAMES.CSV` | `B:` | Yes | `[BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
7070
//! | `B:../BACKUP.000/NAMES.CSV` | `B:` | No | `[.., BACKUP.000]` | `NAMES.CSV` | `B:/BACKUP.000/NAMES.CSV` |
7171
72-
use std::io::prelude::*;
72+
use std::{cell::RefCell, io::prelude::*};
7373

74-
use embedded_sdmmc::{
75-
Error as EsError, RawDirectory, RawVolume, ShortFileName, VolumeIdx, VolumeManager,
76-
};
74+
use embedded_sdmmc::{Error as EsError, RawDirectory, RawVolume, ShortFileName, VolumeIdx};
75+
76+
type VolumeManager = embedded_sdmmc::VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>;
77+
type Directory<'a> = embedded_sdmmc::Directory<'a, LinuxBlockDevice, Clock, 8, 8, 4>;
7778

7879
use crate::linux::{Clock, LinuxBlockDevice};
7980

@@ -182,21 +183,21 @@ struct VolumeState {
182183
}
183184

184185
struct Context {
185-
volume_mgr: VolumeManager<LinuxBlockDevice, Clock, 8, 8, 4>,
186-
volumes: [Option<VolumeState>; 4],
186+
volume_mgr: VolumeManager,
187+
volumes: RefCell<[Option<VolumeState>; 4]>,
187188
current_volume: usize,
188189
}
189190

190191
impl Context {
191192
fn current_path(&self) -> Vec<String> {
192-
let Some(s) = &self.volumes[self.current_volume] else {
193+
let Some(s) = &self.volumes.borrow()[self.current_volume] else {
193194
return vec![];
194195
};
195196
s.path.clone()
196197
}
197198

198199
/// Print some help text
199-
fn help(&mut self) -> Result<(), Error> {
200+
fn help(&self) -> Result<(), Error> {
200201
println!("Commands:");
201202
println!("\thelp -> this help text");
202203
println!("\t<volume>: -> change volume/partition");
@@ -219,16 +220,15 @@ impl Context {
219220
}
220221

221222
/// Print volume manager status
222-
fn stat(&mut self) -> Result<(), Error> {
223+
fn stat(&self) -> Result<(), Error> {
223224
println!("Status:\n{:#?}", self.volume_mgr);
224225
Ok(())
225226
}
226227

227228
/// Print a directory listing
228-
fn dir(&mut self, path: &Path) -> Result<(), Error> {
229+
fn dir(&self, path: &Path) -> Result<(), Error> {
229230
println!("Directory listing of {:?}", path);
230231
let dir = self.resolve_existing_directory(path)?;
231-
let dir = dir.to_directory(&mut self.volume_mgr);
232232
dir.iterate_dir(|entry| {
233233
if !entry.attributes.is_volume() && !entry.attributes.is_lfn() {
234234
println!(
@@ -246,7 +246,7 @@ impl Context {
246246
}
247247

248248
/// Print a recursive directory listing for the given path
249-
fn tree(&mut self, path: &Path) -> Result<(), Error> {
249+
fn tree(&self, path: &Path) -> Result<(), Error> {
250250
println!("Directory listing of {:?}", path);
251251
let dir = self.resolve_existing_directory(path)?;
252252
// tree_dir will close this directory, always
@@ -256,8 +256,7 @@ impl Context {
256256
/// Print a recursive directory listing for the given open directory.
257257
///
258258
/// Will close the given directory.
259-
fn tree_dir(&mut self, dir: RawDirectory) -> Result<(), Error> {
260-
let dir = dir.to_directory(&mut self.volume_mgr);
259+
fn tree_dir<'a>(&'a self, dir: Directory<'a>) -> Result<(), Error> {
261260
let mut children = Vec::new();
262261
dir.iterate_dir(|entry| {
263262
println!(
@@ -271,25 +270,20 @@ impl Context {
271270
children.push(entry.name.clone());
272271
}
273272
})?;
274-
// Be sure to close this, no matter what happens
275-
let dir = dir.to_raw_directory();
276273
for child in children {
277274
println!("Entering {}", child);
278-
let child_dir = match self.volume_mgr.open_dir(dir, &child) {
275+
let child_dir = match dir.open_dir(&child) {
279276
Ok(child_dir) => child_dir,
280277
Err(e) => {
281-
self.volume_mgr.close_dir(dir).expect("close open dir");
282278
return Err(e);
283279
}
284280
};
285281
let result = self.tree_dir(child_dir);
286282
println!("Returning from {}", child);
287283
if let Err(e) = result {
288-
self.volume_mgr.close_dir(dir).expect("close open dir");
289284
return Err(e);
290285
}
291286
}
292-
self.volume_mgr.close_dir(dir).expect("close open dir");
293287
Ok(())
294288
}
295289

@@ -300,17 +294,17 @@ impl Context {
300294
/// sub-folder, starting from the current directory on the current volume
301295
/// * An absolute path like `B:/FOO` changes the CWD on Volume 1 to path
302296
/// `/FOO`
303-
fn cd(&mut self, full_path: &Path) -> Result<(), Error> {
297+
fn cd(&self, full_path: &Path) -> Result<(), Error> {
304298
let volume_idx = self.resolve_volume(full_path)?;
305-
let d = self.resolve_existing_directory(full_path)?;
306-
let Some(s) = &mut self.volumes[volume_idx] else {
307-
self.volume_mgr.close_dir(d).expect("close open dir");
299+
let (mut d, fragment) = self.resolve_filename(full_path)?;
300+
d.change_dir(fragment)?;
301+
let Some(s) = &mut self.volumes.borrow_mut()[volume_idx] else {
308302
return Err(Error::NoSuchVolume);
309303
};
310304
self.volume_mgr
311305
.close_dir(s.directory)
312306
.expect("close open dir");
313-
s.directory = d;
307+
s.directory = d.to_raw_directory();
314308
if full_path.is_absolute() {
315309
s.path.clear();
316310
}
@@ -327,9 +321,8 @@ impl Context {
327321
}
328322

329323
/// print a text file
330-
fn cat(&mut self, filename: &Path) -> Result<(), Error> {
324+
fn cat(&self, filename: &Path) -> Result<(), Error> {
331325
let (dir, filename) = self.resolve_filename(filename)?;
332-
let dir = dir.to_directory(&mut self.volume_mgr);
333326
let f = dir.open_file_in_dir(filename, embedded_sdmmc::Mode::ReadOnly)?;
334327
let mut data = Vec::new();
335328
while !f.is_eof() {
@@ -348,9 +341,8 @@ impl Context {
348341
}
349342

350343
/// print a binary file
351-
fn hexdump(&mut self, filename: &Path) -> Result<(), Error> {
344+
fn hexdump(&self, filename: &Path) -> Result<(), Error> {
352345
let (dir, filename) = self.resolve_filename(filename)?;
353-
let dir = dir.to_directory(&mut self.volume_mgr);
354346
let f = dir.open_file_in_dir(filename, embedded_sdmmc::Mode::ReadOnly)?;
355347
let mut data = Vec::new();
356348
while !f.is_eof() {
@@ -385,9 +377,8 @@ impl Context {
385377
}
386378

387379
/// create a directory
388-
fn mkdir(&mut self, dir_name: &Path) -> Result<(), Error> {
380+
fn mkdir(&self, dir_name: &Path) -> Result<(), Error> {
389381
let (dir, filename) = self.resolve_filename(dir_name)?;
390-
let dir = dir.to_directory(&mut self.volume_mgr);
391382
dir.make_dir_in_dir(filename)
392383
}
393384

@@ -435,11 +426,10 @@ impl Context {
435426
/// * Relative names, like `../SOMEDIR` or `./SOMEDIR`, traverse
436427
/// starting at the current volume and directory.
437428
/// * Absolute, like `B:/SOMEDIR/OTHERDIR` start at the given volume.
438-
fn resolve_existing_directory(&mut self, full_path: &Path) -> Result<RawDirectory, Error> {
439-
let (dir, fragment) = self.resolve_filename(full_path)?;
440-
let mut work_dir = dir.to_directory(&mut self.volume_mgr);
441-
work_dir.change_dir(fragment)?;
442-
Ok(work_dir.to_raw_directory())
429+
fn resolve_existing_directory<'a>(&'a self, full_path: &Path) -> Result<Directory<'a>, Error> {
430+
let (mut dir, fragment) = self.resolve_filename(full_path)?;
431+
dir.change_dir(fragment)?;
432+
Ok(dir)
443433
}
444434

445435
/// Either get the volume from the path, or pick the current volume.
@@ -464,33 +454,30 @@ impl Context {
464454
/// * Relative names, like `../SOMEDIR/SOMEFILE` or `./SOMEDIR/SOMEFILE`, traverse
465455
/// starting at the current volume and directory.
466456
/// * Absolute, like `B:/SOMEDIR/SOMEFILE` start at the given volume.
467-
fn resolve_filename<'path>(
468-
&mut self,
457+
fn resolve_filename<'a, 'path>(
458+
&'a self,
469459
full_path: &'path Path,
470-
) -> Result<(RawDirectory, &'path str), Error> {
460+
) -> Result<(Directory<'a>, &'path str), Error> {
471461
let volume_idx = self.resolve_volume(full_path)?;
472-
let Some(s) = &mut self.volumes[volume_idx] else {
462+
let Some(s) = &self.volumes.borrow()[volume_idx] else {
473463
return Err(Error::NoSuchVolume);
474464
};
475465
let mut work_dir = if full_path.is_absolute() {
476466
// relative to root
477467
self.volume_mgr
478468
.open_root_dir(s.volume)?
479-
.to_directory(&mut self.volume_mgr)
469+
.to_directory(&self.volume_mgr)
480470
} else {
481471
// relative to CWD
482472
self.volume_mgr
483473
.open_dir(s.directory, ".")?
484-
.to_directory(&mut self.volume_mgr)
474+
.to_directory(&self.volume_mgr)
485475
};
486476

487477
for fragment in full_path.iterate_dirs() {
488478
work_dir.change_dir(fragment)?;
489479
}
490-
Ok((
491-
work_dir.to_raw_directory(),
492-
full_path.basename().unwrap_or("."),
493-
))
480+
Ok((work_dir, full_path.basename().unwrap_or(".")))
494481
}
495482

496483
/// Convert a volume index to a letter
@@ -507,7 +494,7 @@ impl Context {
507494

508495
impl Drop for Context {
509496
fn drop(&mut self) {
510-
for v in self.volumes.iter_mut() {
497+
for v in self.volumes.borrow_mut().iter_mut() {
511498
if let Some(v) = v {
512499
println!("Closing directory {:?}", v.directory);
513500
self.volume_mgr
@@ -534,7 +521,7 @@ fn main() -> Result<(), Error> {
534521

535522
let mut ctx = Context {
536523
volume_mgr: VolumeManager::new_with_limits(lbd, Clock, 100),
537-
volumes: [None, None, None, None],
524+
volumes: RefCell::new([None, None, None, None]),
538525
current_volume: 0,
539526
};
540527

@@ -549,7 +536,7 @@ fn main() -> Result<(), Error> {
549536
);
550537
match ctx.volume_mgr.open_root_dir(volume) {
551538
Ok(root_dir) => {
552-
ctx.volumes[volume_no] = Some(VolumeState {
539+
ctx.volumes.borrow_mut()[volume_no] = Some(VolumeState {
553540
directory: root_dir,
554541
volume,
555542
path: vec![],

0 commit comments

Comments
 (0)