diff --git a/parser/src/config.rs b/parser/src/config.rs
new file mode 100644
index 0000000..4204acf
--- /dev/null
+++ b/parser/src/config.rs
@@ -0,0 +1,500 @@
+// Copyright 2020 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use indexmap::map::IndexMap as HashMap;
+use indexmap::set::IndexSet as HashSet;
+use std::borrow::Cow;
+use std::collections::hash_map::DefaultHasher;
+use std::hash::{Hash, Hasher};
+
+use itertools::Itertools;
+use proc_macro2::Span;
+use quote::ToTokens;
+
+#[cfg(feature = "reproduction_case")]
+use quote::format_ident;
+use syn::{
+    parse::{Parse, ParseStream},
+    Signature, Token, TypePath,
+};
+use syn::{Ident, Result as ParseResult};
+use thiserror::Error;
+
+use crate::{directives::get_directives, RustPath};
+
+use quote::quote;
+
+#[derive(PartialEq, Clone, Debug, Hash)]
+pub enum UnsafePolicy {
+    AllFunctionsSafe,
+    AllFunctionsUnsafe,
+}
+
+impl Default for UnsafePolicy {
+    fn default() -> Self {
+        Self::AllFunctionsUnsafe
+    }
+}
+
+impl Parse for UnsafePolicy {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        if input.parse::<Option<Token![unsafe]>>()?.is_some() {
+            return Ok(UnsafePolicy::AllFunctionsSafe);
+        }
+        let r = match input.parse::<Option<syn::Ident>>()? {
+            Some(id) => {
+                if id == "unsafe_ffi" {
+                    Ok(UnsafePolicy::AllFunctionsSafe)
+                } else {
+                    Err(syn::Error::new(id.span(), "expected unsafe_ffi"))
+                }
+            }
+            None => Ok(UnsafePolicy::AllFunctionsUnsafe),
+        };
+        if !input.is_empty() {
+            return Err(syn::Error::new(
+                Span::call_site(),
+                "unexpected tokens within safety directive",
+            ));
+        }
+        r
+    }
+}
+
+impl ToTokens for UnsafePolicy {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        if *self == UnsafePolicy::AllFunctionsSafe {
+            tokens.extend(quote! { unsafe })
+        }
+    }
+}
+
+/// An entry in the allowlist.
+#[derive(Hash, Debug)]
+pub enum AllowlistEntry {
+    Item(String),
+    Namespace(String),
+}
+
+impl AllowlistEntry {
+    fn to_bindgen_item(&self) -> String {
+        match self {
+            AllowlistEntry::Item(i) => i.clone(),
+            AllowlistEntry::Namespace(ns) => format!("{}::.*", ns),
+        }
+    }
+}
+
+/// Allowlist configuration.
+#[derive(Hash, Debug)]
+pub enum Allowlist {
+    Unspecified(Vec<AllowlistEntry>),
+    All,
+    Specific(Vec<AllowlistEntry>),
+}
+
+/// Errors that may be encountered while adding allowlist entries.
+#[derive(Error, Debug)]
+pub enum AllowlistErr {
+    #[error("Conflict between generate/generate_ns! and generate_all! - use one not both")]
+    ConflictingGenerateAndGenerateAll,
+}
+
+impl Allowlist {
+    pub fn push(&mut self, item: AllowlistEntry) -> Result<(), AllowlistErr> {
+        match self {
+            Allowlist::Unspecified(ref mut uncommitted_list) => {
+                let new_list = uncommitted_list
+                    .drain(..)
+                    .chain(std::iter::once(item))
+                    .collect();
+                *self = Allowlist::Specific(new_list);
+            }
+            Allowlist::All => {
+                return Err(AllowlistErr::ConflictingGenerateAndGenerateAll);
+            }
+            Allowlist::Specific(list) => list.push(item),
+        };
+        Ok(())
+    }
+
+    pub(crate) fn set_all(&mut self) -> Result<(), AllowlistErr> {
+        if matches!(self, Allowlist::Specific(..)) {
+            return Err(AllowlistErr::ConflictingGenerateAndGenerateAll);
+        }
+        *self = Allowlist::All;
+        Ok(())
+    }
+}
+
+#[allow(clippy::derivable_impls)] // nightly-only
+impl Default for Allowlist {
+    fn default() -> Self {
+        Allowlist::Unspecified(Vec::new())
+    }
+}
+
+#[derive(Debug, Hash)]
+pub struct Subclass {
+    pub superclass: String,
+    pub subclass: Ident,
+}
+
+#[derive(Clone, Hash)]
+pub struct RustFun {
+    pub path: RustPath,
+    pub sig: Signature,
+    pub receiver: Option<Ident>,
+}
+
+impl std::fmt::Debug for RustFun {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("RustFun")
+            .field("path", &self.path)
+            .field("sig", &self.sig.to_token_stream().to_string())
+            .finish()
+    }
+}
+
+#[derive(Debug, Clone, Hash)]
+pub struct ExternCppType {
+    pub rust_path: TypePath,
+    pub opaque: bool,
+}
+
+/// Newtype wrapper so we can implement Hash.
+#[derive(Debug, Default)]
+pub struct ExternCppTypeMap(pub HashMap<String, ExternCppType>);
+
+impl std::hash::Hash for ExternCppTypeMap {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        for (k, v) in &self.0 {
+            k.hash(state);
+            v.hash(state);
+        }
+    }
+}
+
+/// Newtype wrapper so we can implement Hash.
+#[derive(Debug, Default)]
+pub struct ConcretesMap(pub HashMap<String, Ident>);
+
+impl std::hash::Hash for ConcretesMap {
+    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+        for (k, v) in &self.0 {
+            k.hash(state);
+            v.hash(state);
+        }
+    }
+}
+
+#[derive(Debug, Default, Hash)]
+pub struct IncludeCppConfig {
+    pub inclusions: Vec<String>,
+    pub unsafe_policy: UnsafePolicy,
+    pub parse_only: bool,
+    pub exclude_impls: bool,
+    pub(crate) pod_requests: Vec<String>,
+    pub allowlist: Allowlist,
+    pub(crate) blocklist: Vec<String>,
+    pub(crate) constructor_blocklist: Vec<String>,
+    pub instantiable: Vec<String>,
+    pub(crate) exclude_utilities: bool,
+    pub(crate) mod_name: Option<Ident>,
+    pub rust_types: Vec<RustPath>,
+    pub subclasses: Vec<Subclass>,
+    pub extern_rust_funs: Vec<RustFun>,
+    pub concretes: ConcretesMap,
+    pub externs: ExternCppTypeMap,
+}
+
+impl Parse for IncludeCppConfig {
+    fn parse(input: ParseStream) -> ParseResult<Self> {
+        let mut config = IncludeCppConfig::default();
+
+        while !input.is_empty() {
+            let has_hexathorpe = input.parse::<Option<syn::token::Pound>>()?.is_some();
+            let ident: syn::Ident = input.parse()?;
+            let args;
+            let (possible_directives, to_parse, parse_completely) = if has_hexathorpe {
+                (&get_directives().need_hexathorpe, input, false)
+            } else {
+                input.parse::<Option<syn::token::Bang>>()?;
+                syn::parenthesized!(args in input);
+                (&get_directives().need_exclamation, &args, true)
+            };
+            let all_possible = possible_directives.keys().join(", ");
+            let ident_str = ident.to_string();
+            match possible_directives.get(&ident_str) {
+                None => {
+                    return Err(syn::Error::new(
+                        ident.span(),
+                        format!("expected {}", all_possible),
+                    ));
+                }
+                Some(directive) => directive.parse(to_parse, &mut config, &ident.span())?,
+            }
+            if parse_completely && !to_parse.is_empty() {
+                return Err(syn::Error::new(
+                    ident.span(),
+                    format!("found unexpected input within the directive {}", ident_str),
+                ));
+            }
+            if input.is_empty() {
+                break;
+            }
+        }
+        Ok(config)
+    }
+}
+
+impl IncludeCppConfig {
+    pub fn get_pod_requests(&self) -> &[String] {
+        &self.pod_requests
+    }
+
+    pub fn get_mod_name(&self) -> Ident {
+        self.mod_name
+            .as_ref()
+            .cloned()
+            .unwrap_or_else(|| Ident::new("ffi", Span::call_site()))
+    }
+
+    /// Whether to avoid generating the standard helpful utility
+    /// functions which we normally include in every mod.
+    pub fn exclude_utilities(&self) -> bool {
+        self.exclude_utilities
+    }
+
+    /// Items which the user has explicitly asked us to generate;
+    /// we should raise an error if we weren't able to do so.
+    pub fn must_generate_list(&self) -> Box<dyn Iterator<Item = String> + '_> {
+        if let Allowlist::Specific(items) = &self.allowlist {
+            Box::new(
+                items
+                    .iter()
+                    .filter_map(|i| match i {
+                        AllowlistEntry::Item(i) => Some(i),
+                        AllowlistEntry::Namespace(_) => None,
+                    })
+                    .chain(self.pod_requests.iter())
+                    .cloned(),
+            )
+        } else {
+            Box::new(self.pod_requests.iter().cloned())
+        }
+    }
+
+    /// The allowlist of items to be passed into bindgen, if any.
+    pub fn bindgen_allowlist(&self) -> Option<Box<dyn Iterator<Item = String> + '_>> {
+        match &self.allowlist {
+            Allowlist::All => None,
+            Allowlist::Specific(items) => Some(Box::new(
+                items
+                    .iter()
+                    .map(AllowlistEntry::to_bindgen_item)
+                    .chain(self.pod_requests.iter().cloned())
+                    .chain(self.active_utilities())
+                    .chain(self.subclasses.iter().flat_map(|sc| {
+                        [
+                            format!("{}Cpp", sc.subclass),
+                            sc.subclass.to_string(), // TODO may not be necessary
+                            sc.superclass.clone(),
+                        ]
+                    })),
+            )),
+            Allowlist::Unspecified(_) => unreachable!(),
+        }
+    }
+
+    fn active_utilities(&self) -> Vec<String> {
+        if self.exclude_utilities {
+            Vec::new()
+        } else {
+            vec![self.get_makestring_name()]
+        }
+    }
+
+    fn is_subclass_or_superclass(&self, cpp_name: &str) -> bool {
+        self.subclasses
+            .iter()
+            .flat_map(|sc| {
+                [
+                    Cow::Owned(sc.subclass.to_string()),
+                    Cow::Borrowed(&sc.superclass),
+                ]
+            })
+            .any(|item| cpp_name == item.as_str())
+    }
+
+    /// Whether this type is on the allowlist specified by the user.
+    ///
+    /// A note on the allowlist handling in general. It's used in two places:
+    /// 1) As directives to bindgen
+    /// 2) After bindgen has generated code, to filter the APIs which
+    ///    we pass to cxx.
+    /// This second pass may seem redundant. But sometimes bindgen generates
+    /// unnecessary stuff.
+    pub fn is_on_allowlist(&self, cpp_name: &str) -> bool {
+        self.active_utilities().iter().any(|item| *item == cpp_name)
+            || self.is_subclass_or_superclass(cpp_name)
+            || self.is_subclass_holder(cpp_name)
+            || self.is_subclass_cpp(cpp_name)
+            || self.is_rust_fun(cpp_name)
+            || self.is_concrete_type(cpp_name)
+            || match &self.allowlist {
+                Allowlist::Unspecified(_) => panic!("Eek no allowlist yet"),
+                Allowlist::All => true,
+                Allowlist::Specific(items) => items.iter().any(|entry| match entry {
+                    AllowlistEntry::Item(i) => i == cpp_name,
+                    AllowlistEntry::Namespace(ns) => cpp_name.starts_with(ns),
+                }),
+            }
+    }
+
+    pub fn is_on_blocklist(&self, cpp_name: &str) -> bool {
+        self.blocklist.contains(&cpp_name.to_string())
+    }
+
+    pub fn is_on_constructor_blocklist(&self, cpp_name: &str) -> bool {
+        self.constructor_blocklist.contains(&cpp_name.to_string())
+    }
+
+    pub fn get_blocklist(&self) -> impl Iterator<Item = &String> {
+        self.blocklist.iter()
+    }
+
+    fn is_concrete_type(&self, cpp_name: &str) -> bool {
+        self.concretes.0.values().any(|val| *val == cpp_name)
+    }
+
+    /// Get a hash of the contents of this `include_cpp!` block.
+    pub fn get_hash(&self) -> u64 {
+        let mut s = DefaultHasher::new();
+        self.hash(&mut s);
+        s.finish()
+    }
+
+    /// In case there are multiple sets of ffi mods in a single binary,
+    /// endeavor to return a name which can be used to make symbols
+    /// unique.
+    pub fn uniquify_name_per_mod(&self, name: &str) -> String {
+        format!("{}_{:#x}", name, self.get_hash())
+    }
+
+    pub fn get_makestring_name(&self) -> String {
+        self.uniquify_name_per_mod("autocxx_make_string")
+    }
+
+    pub fn is_rust_type(&self, id: &Ident) -> bool {
+        self.rust_types
+            .iter()
+            .any(|rt| rt.get_final_ident() == &id.to_string())
+            || self.is_subclass_holder(&id.to_string())
+    }
+
+    fn is_rust_fun(&self, possible_fun: &str) -> bool {
+        self.extern_rust_funs
+            .iter()
+            .map(|fun| &fun.sig.ident)
+            .any(|id| id == possible_fun)
+    }
+
+    pub fn superclasses(&self) -> impl Iterator<Item = &String> {
+        let mut uniquified = HashSet::new();
+        uniquified.extend(self.subclasses.iter().map(|sc| &sc.superclass));
+        uniquified.into_iter()
+    }
+
+    pub fn is_subclass_holder(&self, id: &str) -> bool {
+        self.subclasses
+            .iter()
+            .any(|sc| format!("{}Holder", sc.subclass) == id)
+    }
+
+    fn is_subclass_cpp(&self, id: &str) -> bool {
+        self.subclasses
+            .iter()
+            .any(|sc| format!("{}Cpp", sc.subclass) == id)
+    }
+
+    /// Return the filename to which generated .rs should be written.
+    pub fn get_rs_filename(&self) -> String {
+        format!(
+            "autocxx-{}-gen.rs",
+            self.mod_name
+                .as_ref()
+                .map(|id| id.to_string())
+                .unwrap_or_else(|| "ffi-default".into())
+        )
+    }
+
+    pub fn confirm_complete(&mut self) {
+        if matches!(self.allowlist, Allowlist::Unspecified(_)) {
+            self.allowlist = Allowlist::Specific(Vec::new());
+        }
+    }
+
+    /// Used in reduction to substitute all included headers with a single
+    /// preprocessed replacement.
+    pub fn replace_included_headers(&mut self, replacement: &str) {
+        self.inclusions.clear();
+        self.inclusions.push(replacement.to_string());
+    }
+}
+
+#[cfg(feature = "reproduction_case")]
+impl ToTokens for IncludeCppConfig {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        let directives = get_directives();
+        let hexathorpe = syn::token::Pound(Span::call_site());
+        for (id, directive) in &directives.need_hexathorpe {
+            let id = format_ident!("{}", id);
+            for output in directive.output(self) {
+                tokens.extend(quote! {
+                    #hexathorpe #id #output
+                })
+            }
+        }
+        for (id, directive) in &directives.need_exclamation {
+            let id = format_ident!("{}", id);
+            for output in directive.output(self) {
+                tokens.extend(quote! {
+                    #id ! (#output)
+                })
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod parse_tests {
+    use crate::config::UnsafePolicy;
+    use syn::parse_quote;
+    #[test]
+    fn test_safety_unsafe() {
+        let us: UnsafePolicy = parse_quote! {
+            unsafe
+        };
+        assert_eq!(us, UnsafePolicy::AllFunctionsSafe)
+    }
+
+    #[test]
+    fn test_safety_unsafe_ffi() {
+        let us: UnsafePolicy = parse_quote! {
+            unsafe_ffi
+        };
+        assert_eq!(us, UnsafePolicy::AllFunctionsSafe)
+    }
+
+    #[test]
+    fn test_safety_safe() {
+        let us: UnsafePolicy = parse_quote! {};
+        assert_eq!(us, UnsafePolicy::AllFunctionsUnsafe)
+    }
+}
