import Config from '../../config' ; import { StaticDataView } from '../../data-view' ; import NetworkFilter from '../../filters/network' ; import Request from '../../request' ; import { noopOptimizeNetwork , optimizeNetwork } from '../optimizer' ; import ReverseIndex from '../reverse-index' ; import FiltersContainer from './filters' ; /**
 * Accelerating data structure for network filters matching.
 */ export default class NetworkFilterBucket { public static deserialize ( buffer , config ) { const bucket = new NetworkFilterBucket ( { config } ) ; bucket . index = ReverseIndex . deserialize ( buffer , NetworkFilter . deserialize , config . enableOptimizations ? optimizeNetwork : noopOptimizeNetwork , config ) ; bucket . badFilters = FiltersContainer . deserialize ( buffer , NetworkFilter . deserialize , config ) ; return bucket ; } public index : ReverseIndex < NetworkFilter > ; public badFilters : FiltersContainer < NetworkFilter > ; private badFiltersIds : Set < number > | null ; constructor ( { filters = [ ] , config } ) { this . index = new ReverseIndex ( { config , deserialize : NetworkFilter . deserialize , filters : [ ] , optimize : config . enableOptimizations ? optimizeNetwork : noopOptimizeNetwork , } ) ; this . badFiltersIds = null ; this . badFilters = new FiltersContainer ( { config , deserialize : NetworkFilter . deserialize , filters : [ ] , } ) ; if ( filters . length !== 0 ) { this . update ( filters , undefined ) ; } } public getFilters ( ) { const filters = [ ] ; return filters . concat ( this . badFilters . getFilters ( ) , this . index . getFilters ( ) ) ; } public update ( newFilters , removedFilters ) { const badFilters = [ ] ; const remaining = [ ] ; for ( const filter of newFilters ) { if ( filter . isBadFilter ( ) ) { badFilters . push ( filter ) ; } else { remaining . push ( filter ) ; } } this . badFilters . update ( badFilters , removedFilters ) ; this . index . update ( remaining , removedFilters ) ; this . badFiltersIds = null ; } public getSerializedSize ( ) { return this . badFilters . getSerializedSize ( ) + this . index . getSerializedSize ( ) ; } public serialize ( buffer ) { this . index . serialize ( buffer ) ; this . badFilters . serialize ( buffer ) ; } public matchAll ( request ) { const filters = [ ] ; this . index . iterMatchingFilters ( request . getTokens ( ) , ( filter ) => { if ( filter . match ( request ) && this . isFilterDisabled ( filter ) === false ) { filters . push ( filter ) ; } return true ; } ) ; return filters ; } public match ( request ) { let match ; this . index . iterMatchingFilters ( request . getTokens ( ) , ( filter ) => { if ( filter . match ( request ) && this . isFilterDisabled ( filter ) === false ) { match = filter ; return false ; } return true ; } ) ; return match ; } /**
     * Given a matching filter, check if it is disabled by a $badfilter
     */ private isFilterDisabled ( filter ) { if ( this . badFiltersIds === null ) { const badFilters = this . badFilters . getFilters ( ) ; if ( badFilters . length === 0 ) { return false ; } const badFiltersIds = new Set ( ) ; for ( const badFilter of badFilters ) { badFiltersIds . add ( badFilter . getIdWithoutBadFilter ( ) ) ; } this . badFiltersIds = badFiltersIds ; } return this . badFiltersIds . has ( filter . getId ( ) ) ; } }