Skip to content

Commit 06d603c

Browse files
committed
Flatten trigger specs
1 parent b433ca6 commit 06d603c

File tree

6 files changed

+58
-174
lines changed

6 files changed

+58
-174
lines changed

ts/src/flexible-event/main.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,10 @@ if (options.json_file !== undefined) {
113113
new Config(
114114
source.maxEventLevelReports,
115115
source.attributionScopes,
116-
source.triggerSpecs.flatMap((spec) =>
117-
new Array<PerTriggerDataConfig>(spec.triggerData.size).fill(
118-
new PerTriggerDataConfig(
119-
spec.eventReportWindows.endTimes.length,
120-
spec.summaryBuckets.length
121-
)
116+
new Array<PerTriggerDataConfig>(source.triggerData.size).fill(
117+
new PerTriggerDataConfig(
118+
source.eventReportWindows.endTimes.length,
119+
source.maxEventLevelReports
122120
)
123121
)
124122
)

ts/src/header-validator/source.test.ts

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { SourceType } from '../source-type'
22
import * as vsv from '../vendor-specific-values'
33
import { Maybe } from './maybe'
4-
import { Source, SummaryOperator, TriggerDataMatching } from './source'
4+
import { Source, TriggerDataMatching } from './source'
55
import * as testutil from './util.test'
66
import * as jsontest from './validate-json.test'
77
import * as source from './validate-source'
@@ -69,17 +69,11 @@ const testCases: TestCase[] = [
6969
priority: 2n,
7070
sourceEventId: 3n,
7171
maxEventLevelReports: 2,
72-
triggerSpecs: [
73-
{
74-
eventReportWindows: {
75-
startTime: 0,
76-
endTimes: [3601],
77-
},
78-
summaryBuckets: [1, 2],
79-
summaryOperator: SummaryOperator.count,
80-
triggerData: new Set([0, 1, 2, 3, 4, 5, 6, 7]),
81-
},
82-
],
72+
eventReportWindows: {
73+
startTime: 0,
74+
endTimes: [3601],
75+
},
76+
triggerData: new Set([0, 1, 2, 3, 4, 5, 6, 7]),
8377
triggerDataMatching: TriggerDataMatching.modulus,
8478
aggregatableDebugReporting: {
8579
budget: 1234,

ts/src/header-validator/source.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,6 @@ export type FilterData = Map<string, Set<string>>
1010
export type AggregationKeys = Map<string, bigint>
1111
export type NamedBudgets = Map<string, number>
1212

13-
export enum SummaryOperator {
14-
count = 'count',
15-
value_sum = 'value_sum',
16-
}
17-
18-
export type TriggerSpec = {
19-
eventReportWindows: EventReportWindows
20-
summaryBuckets: number[]
21-
summaryOperator: SummaryOperator
22-
triggerData: Set<number>
23-
}
24-
2513
export type SourceAggregatableDebugReportingConfig =
2614
reg.AggregatableDebugReportingConfig & {
2715
budget: number
@@ -49,7 +37,8 @@ export type Source = reg.CommonDebug &
4937
maxEventLevelReports: number
5038
sourceEventId: bigint
5139

52-
triggerSpecs: TriggerSpec[]
40+
eventReportWindows: EventReportWindows
41+
triggerData: Set<number>
5342
triggerDataMatching: TriggerDataMatching
5443

5544
eventLevelEpsilon: number

ts/src/header-validator/to-json.ts

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -135,23 +135,15 @@ function serializeAttributionScopes(
135135
}
136136
}
137137

138-
type NotFullFlexSource = Partial<EventReportWindows> & {
138+
type NotFullFlexSource = EventReportWindows & {
139139
trigger_data: number[]
140140
}
141141

142142
function serializeFlexSource(s: source.Source): NotFullFlexSource {
143-
if (s.triggerSpecs.length === 0) {
144-
return { trigger_data: [] }
145-
}
146-
147-
if (s.triggerSpecs.length === 1) {
148-
return {
149-
...serializeEventReportWindows(s.triggerSpecs[0]!.eventReportWindows),
150-
...serializeTriggerData(s.triggerSpecs[0]!.triggerData),
151-
}
143+
return {
144+
...serializeEventReportWindows(s.eventReportWindows),
145+
...serializeTriggerData(s.triggerData),
152146
}
153-
154-
throw new TypeError()
155147
}
156148

157149
type Source = CommonDebug &
@@ -172,12 +164,7 @@ type Source = CommonDebug &
172164
attribution_scopes?: AttributionScopes
173165
}
174166

175-
export interface Options {}
176-
177-
export function serializeSource(
178-
s: source.Source,
179-
_: Readonly<Options>
180-
): string {
167+
export function serializeSource(s: source.Source): string {
181168
const source: Source = {
182169
...serializeCommonDebug(s),
183170
...serializePriority(s),
@@ -352,10 +339,7 @@ type Trigger = CommonDebug &
352339
attribution_scopes?: string[]
353340
}
354341

355-
export function serializeTrigger(
356-
t: trigger.Trigger,
357-
_: Readonly<Options>
358-
): string {
342+
export function serializeTrigger(t: trigger.Trigger): string {
359343
const trigger: Trigger = {
360344
...serializeCommonDebug(t),
361345
...serializeFilterPair(t),

ts/src/header-validator/validate-source.ts

Lines changed: 39 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ import {
1010
FilterData,
1111
Source,
1212
SourceAggregatableDebugReportingConfig,
13-
SummaryOperator,
1413
TriggerDataMatching,
15-
TriggerSpec,
1614
} from './source'
1715
import {
1816
ItemErrorAction,
@@ -336,12 +334,12 @@ function eventLevelEpsilon(j: Json, ctx: Context): Maybe<number> {
336334
function channelCapacity(s: Source, ctx: Context): void {
337335
const numStatesWords = 'number of possible output states'
338336

339-
const perTriggerDataConfigs = s.triggerSpecs.flatMap((spec) =>
340-
Array<privacy.PerTriggerDataConfig>(spec.triggerData.size).fill(
341-
new privacy.PerTriggerDataConfig(
342-
spec.eventReportWindows.endTimes.length,
343-
spec.summaryBuckets.length
344-
)
337+
const perTriggerDataConfigs = Array<privacy.PerTriggerDataConfig>(
338+
s.triggerData.size
339+
).fill(
340+
new privacy.PerTriggerDataConfig(
341+
s.eventReportWindows.endTimes.length,
342+
s.maxEventLevelReports
345343
)
346344
)
347345

@@ -438,84 +436,14 @@ function fullFlexTriggerDatum(j: Json, ctx: Context): Maybe<number> {
438436
.filter(isInRange, ctx, 0, UINT32_MAX)
439437
}
440438

441-
function triggerDataSet(
442-
j: Json,
443-
ctx: Context,
444-
allowEmpty: boolean = false
445-
): Maybe<Set<number>> {
439+
function triggerData(j: Json, ctx: Context): Maybe<Set<number>> {
446440
return set(j, ctx, fullFlexTriggerDatum, {
447-
minLength: allowEmpty ? 0 : 1,
441+
minLength: 0,
448442
maxLength: constants.maxTriggerDataPerSource,
449443
requireDistinct: true,
450444
})
451445
}
452446

453-
type TriggerSpecDeps = {
454-
expiry: Maybe<number>
455-
eventReportWindows: Maybe<EventReportWindows>
456-
maxEventLevelReports: Maybe<number>
457-
}
458-
459-
function makeDefaultSummaryBuckets(maxEventLevelReports: number): number[] {
460-
return Array.from({ length: maxEventLevelReports }, (_, i) => i + 1)
461-
}
462-
463-
function triggerSpecsFromTriggerData(
464-
j: Json,
465-
ctx: Context,
466-
deps: TriggerSpecDeps
467-
): Maybe<TriggerSpec[]> {
468-
return triggerDataSet(j, ctx, /*allowEmpty=*/ true).map((triggerData) => {
469-
if (
470-
triggerData.size === 0 ||
471-
deps.eventReportWindows.value === undefined ||
472-
deps.maxEventLevelReports.value === undefined
473-
) {
474-
return []
475-
}
476-
477-
return [
478-
{
479-
eventReportWindows: deps.eventReportWindows.value,
480-
summaryBuckets: makeDefaultSummaryBuckets(
481-
deps.maxEventLevelReports.value
482-
),
483-
summaryOperator: SummaryOperator.count,
484-
triggerData: triggerData,
485-
},
486-
]
487-
})
488-
}
489-
490-
function defaultTriggerSpecs(
491-
ctx: Context,
492-
eventReportWindows: Maybe<EventReportWindows>,
493-
maxEventLevelReports: Maybe<number>
494-
): Maybe<TriggerSpec[]> {
495-
return eventReportWindows.flatMap((eventReportWindows) =>
496-
maxEventLevelReports.map((maxEventLevelReports) => [
497-
{
498-
eventReportWindows,
499-
summaryBuckets: Array.from(
500-
{ length: maxEventLevelReports },
501-
(_, i) => i + 1
502-
),
503-
summaryOperator: SummaryOperator.count,
504-
triggerData: new Set(
505-
Array.from(
506-
{
507-
length: Number(
508-
constants.defaultTriggerDataCardinality[ctx.opts.sourceType]
509-
),
510-
},
511-
(_, i) => i
512-
)
513-
),
514-
},
515-
])
516-
)
517-
}
518-
519447
function compareNumbers(a: number, b: number): number {
520448
return a - b
521449
}
@@ -526,9 +454,7 @@ function isTriggerDataMatchingValidForSpecs(s: Source, ctx: Context): boolean {
526454
return true
527455
}
528456

529-
const triggerData: number[] = s.triggerSpecs
530-
.flatMap((spec) => Array.from(spec.triggerData))
531-
.sort(compareNumbers)
457+
const triggerData: number[] = Array.from(s.triggerData).sort(compareNumbers)
532458

533459
if (triggerData.some((triggerDatum, i) => triggerDatum !== i)) {
534460
ctx.error(
@@ -546,7 +472,7 @@ function warnInconsistentMaxEventLevelReportsAndTriggerSpecs(
546472
ctx: Context
547473
): void {
548474
const allowsReports = s.maxEventLevelReports > 0
549-
const hasSpecs = s.triggerSpecs.length > 0
475+
const hasSpecs = s.triggerData.size > 0
550476

551477
if (allowsReports && !hasSpecs) {
552478
ctx.warning(
@@ -567,39 +493,6 @@ function source(j: Json, ctx: Context): Maybe<Source> {
567493
withDefault(expiry, constants.validSourceExpiryRange[1])
568494
)(j, ctx)
569495

570-
const eventReportWindowsVal = exclusive(
571-
{
572-
event_report_window: (j) => eventReportWindow(j, ctx, expiryVal),
573-
event_report_windows: (j) => eventReportWindows(j, ctx, expiryVal),
574-
},
575-
expiryVal.map(defaultEventReportWindows, ctx)
576-
)(j, ctx)
577-
578-
const maxEventLevelReportsVal = field(
579-
'max_event_level_reports',
580-
maxEventLevelReports
581-
)(j, ctx)
582-
583-
const defaultTriggerSpecsVal = defaultTriggerSpecs(
584-
ctx,
585-
eventReportWindowsVal,
586-
maxEventLevelReportsVal
587-
)
588-
589-
const triggerSpecsDeps = {
590-
expiry: expiryVal,
591-
eventReportWindows: eventReportWindowsVal,
592-
maxEventLevelReports: maxEventLevelReportsVal,
593-
}
594-
595-
const triggerSpecsVal = exclusive(
596-
{
597-
trigger_data: (j) =>
598-
triggerSpecsFromTriggerData(j, ctx, triggerSpecsDeps),
599-
},
600-
defaultTriggerSpecsVal
601-
)(j, ctx)
602-
603496
return struct(j, ctx, {
604497
aggregatableReportWindow: field('aggregatable_report_window', (j) =>
605498
j === undefined ? expiryVal : singleReportWindow(j, ctx, expiryVal)
@@ -618,9 +511,35 @@ function source(j: Json, ctx: Context): Maybe<Source> {
618511
),
619512
expiry: () => expiryVal,
620513
filterData: field('filter_data', withDefault(filterData, new Map())),
621-
maxEventLevelReports: () => maxEventLevelReportsVal,
514+
maxEventLevelReports: field(
515+
'max_event_level_reports',
516+
maxEventLevelReports
517+
),
622518
sourceEventId: field('source_event_id', withDefault(uint64, 0n)),
623-
triggerSpecs: () => triggerSpecsVal,
519+
eventReportWindows: exclusive(
520+
{
521+
event_report_window: (j) => eventReportWindow(j, ctx, expiryVal),
522+
event_report_windows: (j) => eventReportWindows(j, ctx, expiryVal),
523+
},
524+
expiryVal.map(defaultEventReportWindows, ctx)
525+
),
526+
527+
triggerData: field(
528+
'trigger_data',
529+
withDefault(
530+
triggerData,
531+
new Set(
532+
Array.from(
533+
{
534+
length: Number(
535+
constants.defaultTriggerDataCardinality[ctx.opts.sourceType]
536+
),
537+
},
538+
(_, i) => i
539+
)
540+
)
541+
)
542+
),
624543
aggregatableDebugReporting: field(
625544
'aggregatable_debug_reporting',
626545
withDefault(
@@ -731,6 +650,6 @@ export function validateSource(
731650
export function validator(opts: Readonly<SourceOptions>): Validator<Source> {
732651
return {
733652
validate: (input) => validateSource(input, opts),
734-
serialize: (value) => serializeSource(value, opts),
653+
serialize: serializeSource,
735654
}
736655
}

ts/src/header-validator/validate-trigger.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,6 @@ export function validator(
426426
): Validator<Trigger> {
427427
return {
428428
validate: (input) => validateTrigger(input, opts),
429-
serialize: (value) => serializeTrigger(value, opts),
429+
serialize: serializeTrigger,
430430
}
431431
}

0 commit comments

Comments
 (0)