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: cas_service.rs
    path of file: ./repos/pants/src/rust/engine/testutil/mock/src
    
    the code of the file until where you have to start completion: // Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
// Licensed under the Apache License, Version 2.0 (see LICENSE).
use std::collections::HashMap;
use std::convert::TryInto;
use std::pin::Pin;
use std::sync::Arc;

use bytes::{Bytes, BytesMut};
use futures::stream::StreamExt;
use futures::Stream;
use hashing::{Digest, Fingerprint};
use parking_lot::Mutex;
use protos::gen::build::bazel::remote::execution::v2 as remexec;
use protos::gen::build::bazel::semver::SemVer;
use protos::gen::google::bytestream::{
    byte_stream_server::ByteStream, QueryWriteStatusRequest, QueryWriteStatusResponse, ReadRequest,
    ReadResponse, WriteRequest, WriteResponse,
};
use remexec::capabilities_server::Capabilities;
use remexec::content_addressable_storage_server::ContentAddressableStorage;
use remexec::{
    BatchReadBlobsRequest, BatchReadBlobsResponse, BatchUpdateBlobsRequest,
    BatchUpdateBlobsResponse, CacheCapabilities, ExecutionCapabilities, FindMissingBlobsRequest,
    FindMissingBlobsResponse, GetCapabilitiesRequest, GetTreeRequest, GetTreeResponse,
    ServerCapabilities,
};
use tonic::metadata::{AsciiMetadataKey, KeyAndValueRef};
use tonic::{Request, Response, Status};

use crate::cas::{RequestCounter, RequestType};

#[derive(Clone, Debug)]
pub(crate) struct StubCASResponder {
    pub chunk_size_bytes: usize,
    pub instance_name: Option<String>,
    pub blobs: Arc<
    
fn parse_write_resource_name(resource: &str) -> Result<ParsedWriteResourceName, String> {
    if resource.is_empty() {
        return Err("Missing resource name".to_owned());
    }

    // Parse the resource name into parts separated by slashes (/).
    let parts: Vec<_> = resource.split('/').collect();

    // Search for the `uploads` path component.
    let uploads_index = match parts.iter().position(|p| *p == "uploads") {
        Some(index) => index,
        None => return Err("Malformed resource name: missing `uploads` component".to_owned()),
    };
    let instance_parts = &parts[0..uploads_index];

    if (parts.len() - uploads_index) < 5 {
        return Err(
            "Malformed resource name: not enough path components after `uploads`".to_owned(),
        );
    }

    if parts[uploads_index + 2] != "blobs" {
        return Err("Malformed resource name: expected `blobs` component".to_owned());
    }

    let size = parts[uploads_index + 4]
        .parse::<usize>()
        .map_err(|_| "Malformed resource name: cannot parse size".to_owned())?;

    let instance_name = if instance_parts.is_empty() {
        ""
    } else {
        let last_instance_name_index =
            instance_parts.iter().map(|x| (*x).len()).sum::<usize>() + instance_parts.len() - 1;
        &resource[0..last_instance_name_index]
    };

    Ok(ParsedWriteResourceName {
        instance_name,
        _uuid: parts[uploads_index + 1],
        hash: parts[uploads_index + 3],
        size,
    })
}