You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: lib.rs
    path of file: ./repos/materialize/src/npm/src
    
    the code of the file until where you have to start completion: // Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

//! A lightweight JavaScript package manager, like npm.
//!
//! There are several goals here:
//!
//!   * Embed the JavaScript assets into the production binary so that the
//!     binary does not depend on any external resources, like JavaScript CDNs.
//!     Access to these CDNs may be blocked by corporate firewalls, and old
//!     versions of environmentd may outlive the CDNs they refer to.
//!
//!   * Avoid checking in the code for JavaScript assets. Checking in blobs of
//!     JavaScript code bloats the repository and leads to merge conflicts. Plus
//!     it is hard to verify the origin of blobs in code review.
//!
//!   * Avoid depending on a full Node.js/npm/webpack stack. Materialize is
//!     primarily a Rust project, and thus most Materialize developers do not
//!     have a Node.js installation available nor do they have the expertise to
//!     debug the inevitable errors that arise.
//!
//! Our needs are simple enough that it is straightforward to download the
//! JavaScript and CSS files we need directly from the NPM registry, without
//! involving the actual npm tool.
//!
//! In our worldview, an `NpmPackage` consists of a name, version, an optional
//! CSS file, a non-minified "development" JavaScript file, and a minified
//! "production" JavaScript file. The CSS file, if present, is extracted into
//! `C
    
pub fn ensure() -> Result<(), anyhow::Error> {
    println!("ensuring all npm packages are up-to-date...");

    let client = reqwest::blocking::Client::new();
    for pkg in NPM_PACKAGES {
        if pkg.compute_digest().ok().as_deref() == Some(&pkg.digest) {
            println!("{} is up-to-date", pkg.name);
            continue;
        } else {
            println!("{} needs updating...", pkg.name);
        }

        let url = format!(
            "https://registry.npmjs.org/{}/-/{}-{}.tgz",
            pkg.name,
            pkg.name.split('/').last().unwrap(),
            pkg.version,
        );
        let res = client
            .get(url)
            .send()
            .and_then(|res| res.error_for_status())
            .with_context(|| format!("downloading {}", pkg.name))?;
        let mut archive = tar::Archive::new(GzDecoder::new(res));
        for entry in archive.entries()? {
            let mut entry = entry?;
            let path = entry.path()?.strip_prefix("package")?.to_owned();
            if let Some(css_file) = &pkg.css_file {
                if path == Path::new(css_file) {
                    unpack_entry(&mut entry, &pkg.css_path())?;
                }
            }
            if path == Path::new(pkg.js_prod_file) {
                unpack_entry(&mut entry, &pkg.js_prod_path())?;
            }
            if path == Path::new(pkg.js_dev_file) {
                unpack_entry(&mut entry, &pkg.js_dev_path())?;
            }
            if let Some((extra_src, _extra_dst)) = &pkg.extra_file {
                if path == Path::new(extra_src) {
                    unpack_entry(&mut entry, &pkg.extra_path())?;
                }
            }
        }

        let digest = pkg
            .compute_digest()
            .with_context(|| format!("computing digest for {}", pkg.name))?;
        if digest != pkg.digest {
            bail!(
                "npm package {} did not match expected digest
expected: {}
  actual: {}",
                pkg.name,
                hex::encode(pkg.digest),
                hex::encode(digest),
            );
        }
    }

    // Clean up any stray files. This is more important than it might seem,
    // since files in `CSS_VENDOR` and `JS_PROD_VENDOR` are blindly bundled into
    // the binary at build time by the `include_dir` macro.
    let mut known_paths = BTreeSet::new();
    for pkg in NPM_PACKAGES {
        if pkg.css_file.is_some() {
            known_paths.insert(pkg.css_path());
        }
        known_paths.insert(pkg.js_prod_path());
        known_paths.insert(pkg.js_dev_path());
        if pkg.extra_file.is_some() {
            known_paths.insert(pkg.extra_path());
        }
    }
    for dir in &[CSS_VENDOR, JS_PROD_VENDOR, JS_DEV_VENDOR] {
        for entry in WalkDir::new(dir) {
            let entry = entry?;
            if entry.file_type().is_file() && !known_paths.contains(entry.path()) {
                println!("removing stray vendor file {}", entry.path().display());
                fs::remove_file(entry.path())?;
            }
        }
    }

    Ok(())
}