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: type_filter.rs
    path of file: ./repos/rusoto/service_crategen/src/commands/generate/codegen
    
    the code of the file until where you have to start completion: use std::collections::BTreeSet;

use super::{contains_eventstreams, mutate_type_name};
use crate::botocore::{Shape, ShapeType};
use crate::Service;

pub fn filter_types(service: &Service<'_>) -> (BTreeSet<String>, BTreeSet<String>) {
    let mut deserialized_types: BTreeSet<String> = BTreeSet::new();
    let mut serialized_types: BTreeSet<String> = BTreeSet::new();
    for operation in service.operations().values() {
        if let Some(ref output) = operation.output {
            let output_shape = service
                .get_shape(&output.shape)
                .expect("Shape type missing from service definition");

            if !can_skip_deserializer_recursively(service, output_shape) {
                recurse_find_serializabl
    
fn can_skip_deserializer_recursively(service: &Service<'_>, output_shape: &Shape) -> bool {
    if let Some(ref payload_field) = output_shape.payload {
        let payload_member = output_shape
            .members
            .as_ref()
            .unwrap()
            .get(payload_field)
            .unwrap();
        let payload_shape = service.get_shape(&payload_member.shape).unwrap();

        // we can skip deserializer generation if the payload member in the output shape
        // is explicitly flagged as streaming, or if the payload shape itself is
        // a Blob or a String (in which case it will just be the raw response body)
        payload_member.streaming()
            || payload_shape.shape_type == ShapeType::Blob
            || payload_shape.shape_type == ShapeType::String
    } else {
        false
    }
}