`s.
.nav {
display: flex;
flex-wrap: wrap;
padding-left: 0;
margin-bottom: 0;
list-style: none;
}
.nav-link {
display: block;
padding: $nav-link-padding-y $nav-link-padding-x;
@include hover-focus {
text-decoration: none;
}
// Disabled state lightens text
&.disabled {
color: $nav-link-disabled-color;
pointer-events: none;
cursor: default;
}
}
//
// Tabs
//
.nav-tabs {
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
.nav-item {
margin-bottom: -$nav-tabs-border-width;
}
.nav-link {
border: $nav-tabs-border-width solid transparent;
@include border-top-radius($nav-tabs-border-radius);
@include hover-focus {
border-color: $nav-tabs-link-hover-border-color;
}
&.disabled {
color: $nav-link-disabled-color;
background-color: transparent;
border-color: transparent;
}
}
.nav-link.active,
.nav-item.show .nav-link {
color: $nav-tabs-link-active-color;
background-color: $nav-tabs-link-active-bg;
border-color: $nav-tabs-link-active-border-color;
}
.dropdown-menu {
// Make dropdown border overlap tab border
margin-top: -$nav-tabs-border-width;
// Remove the top rounded corners here since there is a hard edge above the menu
@include border-top-radius(0);
}
}
//
// Pills
//
.nav-pills {
.nav-link {
@include border-radius($nav-pills-border-radius);
}
.nav-link.active,
.show > .nav-link {
color: $nav-pills-link-active-color;
background-color: $nav-pills-link-active-bg;
}
}
//
// Justified variants
//
.nav-fill {
.nav-item {
flex: 1 1 auto;
text-align: center;
}
}
.nav-justified {
.nav-item {
flex-basis: 0;
flex-grow: 1;
text-align: center;
}
}
// Tabbable tabs
//
// Hide tabbable panes to start, show them when `.active`
.tab-content {
> .tab-pane {
display: none;
}
> .active {
display: block;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_navbar.scss
================================================
// Contents
//
// Navbar
// Navbar brand
// Navbar nav
// Navbar text
// Navbar divider
// Responsive navbar
// Navbar position
// Navbar themes
// Navbar
//
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.
.navbar {
position: relative;
display: flex;
flex-wrap: wrap; // allow us to do the line break for collapsing content
align-items: center;
justify-content: space-between; // space out brand from logo
padding: $navbar-padding-y $navbar-padding-x;
// Because flex properties aren't inherited, we need to redeclare these first
// few properties so that content nested within behave properly.
> .container,
> .container-fluid {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
}
}
// Navbar brand
//
// Used for brand, project, or site names.
.navbar-brand {
display: inline-block;
padding-top: $navbar-brand-padding-y;
padding-bottom: $navbar-brand-padding-y;
margin-right: $navbar-padding-x;
@include font-size($navbar-brand-font-size);
line-height: inherit;
white-space: nowrap;
@include hover-focus {
text-decoration: none;
}
}
// Navbar nav
//
// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
.navbar-nav {
display: flex;
flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
padding-left: 0;
margin-bottom: 0;
list-style: none;
.nav-link {
padding-right: 0;
padding-left: 0;
}
.dropdown-menu {
position: static;
float: none;
}
}
// Navbar text
//
//
.navbar-text {
display: inline-block;
padding-top: $nav-link-padding-y;
padding-bottom: $nav-link-padding-y;
}
// Responsive navbar
//
// Custom styles for responsive collapsing and toggling of navbar contents.
// Powered by the collapse Bootstrap JavaScript plugin.
// When collapsed, prevent the toggleable navbar contents from appearing in
// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
// on the `.navbar` parent.
.navbar-collapse {
flex-basis: 100%;
flex-grow: 1;
// For always expanded or extra full navbars, ensure content aligns itself
// properly vertically. Can be easily overridden with flex utilities.
align-items: center;
}
// Button for toggling the navbar when in its collapsed state
.navbar-toggler {
padding: $navbar-toggler-padding-y $navbar-toggler-padding-x;
@include font-size($navbar-toggler-font-size);
line-height: 1;
background-color: transparent; // remove default button style
border: $border-width solid transparent; // remove default button style
@include border-radius($navbar-toggler-border-radius);
@include hover-focus {
text-decoration: none;
}
}
// Keep as a separate element so folks can easily override it with another icon
// or image file as needed.
.navbar-toggler-icon {
display: inline-block;
width: 1.5em;
height: 1.5em;
vertical-align: middle;
content: "";
background: no-repeat center center;
background-size: 100% 100%;
}
// Generate series of `.navbar-expand-*` responsive classes for configuring
// where your navbar collapses.
.navbar-expand {
@each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
{$infix} {
@include media-breakpoint-down($breakpoint) {
> .container,
> .container-fluid {
padding-right: 0;
padding-left: 0;
}
}
@include media-breakpoint-up($next) {
flex-flow: row nowrap;
justify-content: flex-start;
.navbar-nav {
flex-direction: row;
.dropdown-menu {
position: absolute;
}
.nav-link {
padding-right: $navbar-nav-link-padding-x;
padding-left: $navbar-nav-link-padding-x;
}
}
// For nesting containers, have to redeclare for alignment purposes
> .container,
> .container-fluid {
flex-wrap: nowrap;
}
.navbar-collapse {
display: flex !important; // stylelint-disable-line declaration-no-important
// Changes flex-bases to auto because of an IE10 bug
flex-basis: auto;
}
.navbar-toggler {
display: none;
}
}
}
}
}
// Navbar themes
//
// Styles for switching between navbars with light or dark background.
// Dark links against a light background
.navbar-light {
.navbar-brand {
color: $navbar-light-brand-color;
@include hover-focus {
color: $navbar-light-brand-hover-color;
}
}
.navbar-nav {
.nav-link {
color: $navbar-light-color;
@include hover-focus {
color: $navbar-light-hover-color;
}
&.disabled {
color: $navbar-light-disabled-color;
}
}
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active {
color: $navbar-light-active-color;
}
}
.navbar-toggler {
color: $navbar-light-color;
border-color: $navbar-light-toggler-border-color;
}
.navbar-toggler-icon {
background-image: $navbar-light-toggler-icon-bg;
}
.navbar-text {
color: $navbar-light-color;
a {
color: $navbar-light-active-color;
@include hover-focus {
color: $navbar-light-active-color;
}
}
}
}
// White links against a dark background
.navbar-dark {
.navbar-brand {
color: $navbar-dark-brand-color;
@include hover-focus {
color: $navbar-dark-brand-hover-color;
}
}
.navbar-nav {
.nav-link {
color: $navbar-dark-color;
@include hover-focus {
color: $navbar-dark-hover-color;
}
&.disabled {
color: $navbar-dark-disabled-color;
}
}
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active {
color: $navbar-dark-active-color;
}
}
.navbar-toggler {
color: $navbar-dark-color;
border-color: $navbar-dark-toggler-border-color;
}
.navbar-toggler-icon {
background-image: $navbar-dark-toggler-icon-bg;
}
.navbar-text {
color: $navbar-dark-color;
a {
color: $navbar-dark-active-color;
@include hover-focus {
color: $navbar-dark-active-color;
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_pagination.scss
================================================
.pagination {
display: flex;
@include list-unstyled();
@include border-radius();
}
.page-link {
position: relative;
display: block;
padding: $pagination-padding-y $pagination-padding-x;
margin-left: -$pagination-border-width;
line-height: $pagination-line-height;
color: $pagination-color;
background-color: $pagination-bg;
border: $pagination-border-width solid $pagination-border-color;
&:hover {
z-index: 2;
color: $pagination-hover-color;
text-decoration: none;
background-color: $pagination-hover-bg;
border-color: $pagination-hover-border-color;
}
&:focus {
z-index: 2;
outline: $pagination-focus-outline;
box-shadow: $pagination-focus-box-shadow;
}
}
.page-item {
&:first-child {
.page-link {
margin-left: 0;
@include border-left-radius($border-radius);
}
}
&:last-child {
.page-link {
@include border-right-radius($border-radius);
}
}
&.active .page-link {
z-index: 1;
color: $pagination-active-color;
background-color: $pagination-active-bg;
border-color: $pagination-active-border-color;
}
&.disabled .page-link {
color: $pagination-disabled-color;
pointer-events: none;
// Opinionated: remove the "hand" cursor set previously for .page-link
cursor: auto;
background-color: $pagination-disabled-bg;
border-color: $pagination-disabled-border-color;
}
}
//
// Sizing
//
.pagination-lg {
@include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg);
}
.pagination-sm {
@include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_popover.scss
================================================
.popover {
position: absolute;
top: 0;
left: 0;
z-index: $zindex-popover;
display: block;
max-width: $popover-max-width;
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
@include reset-text();
@include font-size($popover-font-size);
// Allow breaking very long words so they don't overflow the popover's bounds
word-wrap: break-word;
background-color: $popover-bg;
background-clip: padding-box;
border: $popover-border-width solid $popover-border-color;
@include border-radius($popover-border-radius);
@include box-shadow($popover-box-shadow);
.arrow {
position: absolute;
display: block;
width: $popover-arrow-width;
height: $popover-arrow-height;
margin: 0 $border-radius-lg;
&::before,
&::after {
position: absolute;
display: block;
content: "";
border-color: transparent;
border-style: solid;
}
}
}
.bs-popover-top {
margin-bottom: $popover-arrow-height;
> .arrow {
bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
&::before {
bottom: 0;
border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;
border-top-color: $popover-arrow-outer-color;
}
&::after {
bottom: $popover-border-width;
border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;
border-top-color: $popover-arrow-color;
}
}
}
.bs-popover-right {
margin-left: $popover-arrow-height;
> .arrow {
left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
width: $popover-arrow-height;
height: $popover-arrow-width;
margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
&::before {
left: 0;
border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;
border-right-color: $popover-arrow-outer-color;
}
&::after {
left: $popover-border-width;
border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;
border-right-color: $popover-arrow-color;
}
}
}
.bs-popover-bottom {
margin-top: $popover-arrow-height;
> .arrow {
top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
&::before {
top: 0;
border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);
border-bottom-color: $popover-arrow-outer-color;
}
&::after {
top: $popover-border-width;
border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);
border-bottom-color: $popover-arrow-color;
}
}
// This will remove the popover-header's border just below the arrow
.popover-header::before {
position: absolute;
top: 0;
left: 50%;
display: block;
width: $popover-arrow-width;
margin-left: -$popover-arrow-width / 2;
content: "";
border-bottom: $popover-border-width solid $popover-header-bg;
}
}
.bs-popover-left {
margin-right: $popover-arrow-height;
> .arrow {
right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
width: $popover-arrow-height;
height: $popover-arrow-width;
margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
&::before {
right: 0;
border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;
border-left-color: $popover-arrow-outer-color;
}
&::after {
right: $popover-border-width;
border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;
border-left-color: $popover-arrow-color;
}
}
}
.bs-popover-auto {
&[x-placement^="top"] {
@extend .bs-popover-top;
}
&[x-placement^="right"] {
@extend .bs-popover-right;
}
&[x-placement^="bottom"] {
@extend .bs-popover-bottom;
}
&[x-placement^="left"] {
@extend .bs-popover-left;
}
}
// Offset the popover to account for the popover arrow
.popover-header {
padding: $popover-header-padding-y $popover-header-padding-x;
margin-bottom: 0; // Reset the default from Reboot
@include font-size($font-size-base);
color: $popover-header-color;
background-color: $popover-header-bg;
border-bottom: $popover-border-width solid darken($popover-header-bg, 5%);
$offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width});
@include border-top-radius($offset-border-width);
&:empty {
display: none;
}
}
.popover-body {
padding: $popover-body-padding-y $popover-body-padding-x;
color: $popover-body-color;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_print.scss
================================================
// stylelint-disable declaration-no-important, selector-no-qualifying-type
// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
// ==========================================================================
// Print styles.
// Inlined to avoid the additional HTTP request:
// https://www.phpied.com/delay-loading-your-print-css/
// ==========================================================================
@if $enable-print-styles {
@media print {
*,
*::before,
*::after {
// Bootstrap specific; comment out `color` and `background`
//color: $black !important; // Black prints faster
text-shadow: none !important;
//background: transparent !important;
box-shadow: none !important;
}
a {
&:not(.btn) {
text-decoration: underline;
}
}
// Bootstrap specific; comment the following selector out
//a[href]::after {
// content: " (" attr(href) ")";
//}
abbr[title]::after {
content: " (" attr(title) ")";
}
// Bootstrap specific; comment the following selector out
//
// Don't show links that are fragment identifiers,
// or use the `javascript:` pseudo protocol
//
//a[href^="#"]::after,
//a[href^="javascript:"]::after {
// content: "";
//}
pre {
white-space: pre-wrap !important;
}
pre,
blockquote {
border: $border-width solid $gray-500; // Bootstrap custom code; using `$border-width` instead of 1px
page-break-inside: avoid;
}
//
// Printing Tables:
// http://css-discuss.incutio.com/wiki/Printing_Tables
//
thead {
display: table-header-group;
}
tr,
img {
page-break-inside: avoid;
}
p,
h2,
h3 {
orphans: 3;
widows: 3;
}
h2,
h3 {
page-break-after: avoid;
}
// Bootstrap specific changes start
// Specify a size and min-width to make printing closer across browsers.
// We don't set margin here because it breaks `size` in Chrome. We also
// don't use `!important` on `size` as it breaks in Chrome.
@page {
size: $print-page-size;
}
body {
min-width: $print-body-min-width !important;
}
.container {
min-width: $print-body-min-width !important;
}
// Bootstrap components
.navbar {
display: none;
}
.badge {
border: $border-width solid $black;
}
.table {
border-collapse: collapse !important;
td,
th {
background-color: $white !important;
}
}
.table-bordered {
th,
td {
border: 1px solid $gray-300 !important;
}
}
.table-dark {
color: inherit;
th,
td,
thead th,
tbody + tbody {
border-color: $table-border-color;
}
}
.table .thead-dark th {
color: inherit;
border-color: $table-border-color;
}
// Bootstrap specific changes end
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_progress.scss
================================================
// Disable animation if transitions are disabled
@if $enable-transitions {
@keyframes progress-bar-stripes {
from { background-position: $progress-height 0; }
to { background-position: 0 0; }
}
}
.progress {
display: flex;
height: $progress-height;
overflow: hidden; // force rounded corners by cropping it
@include font-size($progress-font-size);
background-color: $progress-bg;
@include border-radius($progress-border-radius);
@include box-shadow($progress-box-shadow);
}
.progress-bar {
display: flex;
flex-direction: column;
justify-content: center;
color: $progress-bar-color;
text-align: center;
white-space: nowrap;
background-color: $progress-bar-bg;
@include transition($progress-bar-transition);
}
.progress-bar-striped {
@include gradient-striped();
background-size: $progress-height $progress-height;
}
@if $enable-transitions {
.progress-bar-animated {
animation: progress-bar-stripes $progress-bar-animation-timing;
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_reboot.scss
================================================
// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
// Reboot
//
// Normalization of HTML elements, manually forked from Normalize.css to remove
// styles targeting irrelevant browsers while applying new styles.
//
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
// Document
//
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
// 2. Change the default font family in all browsers.
// 3. Correct the line height in all browsers.
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
// 5. Change the default tap highlight to be completely transparent in iOS.
*,
*::before,
*::after {
box-sizing: border-box; // 1
}
html {
font-family: sans-serif; // 2
line-height: 1.15; // 3
-webkit-text-size-adjust: 100%; // 4
-webkit-tap-highlight-color: rgba($black, 0); // 5
}
// Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers)
// TODO: remove in v5
// stylelint-disable-next-line selector-list-comma-newline-after
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block;
}
// Body
//
// 1. Remove the margin in all browsers.
// 2. As a best practice, apply a default `background-color`.
// 3. Set an explicit initial text-align value so that we can later use
// the `inherit` value on things like `` elements.
body {
margin: 0; // 1
font-family: $font-family-base;
@include font-size($font-size-base);
font-weight: $font-weight-base;
line-height: $line-height-base;
color: $body-color;
text-align: left; // 3
background-color: $body-bg; // 2
}
// Suppress the focus outline on elements that cannot be accessed via keyboard.
// This prevents an unwanted focus outline from appearing around elements that
// might still respond to pointer events.
//
// Credit: https://github.com/suitcss/base
[tabindex="-1"]:focus {
outline: 0 !important;
}
// Content grouping
//
// 1. Add the correct box sizing in Firefox.
// 2. Show the overflow in Edge and IE.
hr {
box-sizing: content-box; // 1
height: 0; // 1
overflow: visible; // 2
}
//
// Typography
//
// Remove top margins from headings
//
// By default, ``-`` all receive top and bottom margins. We nuke the top
// margin for easier control within type scales as it avoids margin collapsing.
// stylelint-disable-next-line selector-list-comma-newline-after
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
margin-bottom: $headings-margin-bottom;
}
// Reset margins on paragraphs
//
// Similarly, the top margin on ` `s get reset. However, we also reset the
// bottom margin to use `rem` units instead of `em`.
p {
margin-top: 0;
margin-bottom: $paragraph-margin-bottom;
}
// Abbreviations
//
// 1. Duplicate behavior to the data-* attribute for our tooltip plugin
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
// 3. Add explicit cursor to indicate changed behavior.
// 4. Remove the bottom border in Firefox 39-.
// 5. Prevent the text-decoration to be skipped.
abbr[title],
abbr[data-original-title] { // 1
text-decoration: underline; // 2
text-decoration: underline dotted; // 2
cursor: help; // 3
border-bottom: 0; // 4
text-decoration-skip-ink: none; // 5
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: $dt-font-weight;
}
dd {
margin-bottom: .5rem;
margin-left: 0; // Undo browser default
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: $font-weight-bolder; // Add the correct font weight in Chrome, Edge, and Safari
}
small {
@include font-size(80%); // Add the correct font size in all browsers
}
//
// Prevent `sub` and `sup` elements from affecting the line height in
// all browsers.
//
sub,
sup {
position: relative;
@include font-size(75%);
line-height: 0;
vertical-align: baseline;
}
sub { bottom: -.25em; }
sup { top: -.5em; }
//
// Links
//
a {
color: $link-color;
text-decoration: $link-decoration;
background-color: transparent; // Remove the gray background on active links in IE 10.
@include hover {
color: $link-hover-color;
text-decoration: $link-hover-decoration;
}
}
// And undo these styles for placeholder links/named anchors (without href)
// which have not been made explicitly keyboard-focusable (without tabindex).
// It would be more straightforward to just use a[href] in previous block, but that
// causes specificity issues in many other styles that are too complex to fix.
// See https://github.com/twbs/bootstrap/issues/19402
a:not([href]):not([tabindex]) {
color: inherit;
text-decoration: none;
@include hover-focus {
color: inherit;
text-decoration: none;
}
&:focus {
outline: 0;
}
}
//
// Code
//
pre,
code,
kbd,
samp {
font-family: $font-family-monospace;
@include font-size(1em); // Correct the odd `em` font sizing in all browsers.
}
pre {
// Remove browser default top margin
margin-top: 0;
// Reset browser default of `1em` to use `rem`s
margin-bottom: 1rem;
// Don't allow content to break outside
overflow: auto;
}
//
// Figures
//
figure {
// Apply a consistent margin strategy (matches our type styles).
margin: 0 0 1rem;
}
//
// Images and content
//
img {
vertical-align: middle;
border-style: none; // Remove the border on images inside links in IE 10-.
}
svg {
// Workaround for the SVG overflow bug in IE10/11 is still required.
// See https://github.com/twbs/bootstrap/issues/26878
overflow: hidden;
vertical-align: middle;
}
//
// Tables
//
table {
border-collapse: collapse; // Prevent double borders
}
caption {
padding-top: $table-cell-padding;
padding-bottom: $table-cell-padding;
color: $table-caption-color;
text-align: left;
caption-side: bottom;
}
th {
// Matches default `
` alignment by inheriting from the ``, or the
// closest parent with a set `text-align`.
text-align: inherit;
}
//
// Forms
//
label {
// Allow labels to use `margin` for spacing.
display: inline-block;
margin-bottom: $label-margin-bottom;
}
// Remove the default `border-radius` that macOS Chrome adds.
//
// Details at https://github.com/twbs/bootstrap/issues/24093
button {
// stylelint-disable-next-line property-blacklist
border-radius: 0;
}
// Work around a Firefox/IE bug where the transparent `button` background
// results in a loss of the default `button` focus styles.
//
// Credit: https://github.com/suitcss/base/
button:focus {
outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color;
}
input,
button,
select,
optgroup,
textarea {
margin: 0; // Remove the margin in Firefox and Safari
font-family: inherit;
@include font-size(inherit);
line-height: inherit;
}
button,
input {
overflow: visible; // Show the overflow in Edge
}
button,
select {
text-transform: none; // Remove the inheritance of text transform in Firefox
}
// Remove the inheritance of word-wrap in Safari.
//
// Details at https://github.com/twbs/bootstrap/issues/24990
select {
word-wrap: normal;
}
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
// controls in Android 4.
// 2. Correct the inability to style clickable types in iOS and Safari.
button,
[type="button"], // 1
[type="reset"],
[type="submit"] {
-webkit-appearance: button; // 2
}
// Opinionated: add "hand" cursor to non-disabled button elements.
@if $enable-pointer-cursor-for-buttons {
button,
[type="button"],
[type="reset"],
[type="submit"] {
&:not(:disabled) {
cursor: pointer;
}
}
}
// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
padding: 0;
border-style: none;
}
input[type="radio"],
input[type="checkbox"] {
box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
padding: 0; // 2. Remove the padding in IE 10-
}
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"] {
// Remove the default appearance of temporal inputs to avoid a Mobile Safari
// bug where setting a custom line-height prevents text from being vertically
// centered within the input.
// See https://bugs.webkit.org/show_bug.cgi?id=139848
// and https://github.com/twbs/bootstrap/issues/11266
-webkit-appearance: listbox;
}
textarea {
overflow: auto; // Remove the default vertical scrollbar in IE.
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
resize: vertical;
}
fieldset {
// Browsers set a default `min-width: min-content;` on fieldsets,
// unlike e.g. ``s, which have `min-width: 0;` by default.
// So we reset that to ensure fieldsets behave more like a standard block element.
// See https://github.com/twbs/bootstrap/issues/12359
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
min-width: 0;
// Reset the default outline behavior of fieldsets so they don't affect page layout.
padding: 0;
margin: 0;
border: 0;
}
// 1. Correct the text wrapping in Edge and IE.
// 2. Correct the color inheritance from `fieldset` elements in IE.
legend {
display: block;
width: 100%;
max-width: 100%; // 1
padding: 0;
margin-bottom: .5rem;
@include font-size(1.5rem);
line-height: inherit;
color: inherit; // 2
white-space: normal; // 1
}
progress {
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
}
// Correct the cursor style of increment and decrement buttons in Chrome.
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
// This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586.
outline-offset: -2px; // 2. Correct the outline style in Safari.
-webkit-appearance: none;
}
//
// Remove the inner padding in Chrome and Safari on macOS.
//
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
//
// 1. Correct the inability to style clickable types in iOS and Safari.
// 2. Change font properties to `inherit` in Safari.
//
::-webkit-file-upload-button {
font: inherit; // 2
-webkit-appearance: button; // 1
}
//
// Correct element displays
//
output {
display: inline-block;
}
summary {
display: list-item; // Add the correct display in all browsers
cursor: pointer;
}
template {
display: none; // Add the correct display in IE
}
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
// Needed for proper display in IE 10-.
[hidden] {
display: none !important;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_root.scss
================================================
:root {
// Custom variable values only support SassScript inside `#{}`.
@each $color, $value in $colors {
--#{$color}: #{$value};
}
@each $color, $value in $theme-colors {
--#{$color}: #{$value};
}
@each $bp, $value in $grid-breakpoints {
--breakpoint-#{$bp}: #{$value};
}
// Use `inspect` for lists so that quoted items keep the quotes.
// See https://github.com/sass/sass/issues/2383#issuecomment-336349172
--font-family-sans-serif: #{inspect($font-family-sans-serif)};
--font-family-monospace: #{inspect($font-family-monospace)};
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_spinners.scss
================================================
//
// Rotating border
//
@keyframes spinner-border {
to { transform: rotate(360deg); }
}
.spinner-border {
display: inline-block;
width: $spinner-width;
height: $spinner-height;
vertical-align: text-bottom;
border: $spinner-border-width solid currentColor;
border-right-color: transparent;
// stylelint-disable-next-line property-blacklist
border-radius: 50%;
animation: spinner-border .75s linear infinite;
}
.spinner-border-sm {
width: $spinner-width-sm;
height: $spinner-height-sm;
border-width: $spinner-border-width-sm;
}
//
// Growing circle
//
@keyframes spinner-grow {
0% {
transform: scale(0);
}
50% {
opacity: 1;
}
}
.spinner-grow {
display: inline-block;
width: $spinner-width;
height: $spinner-height;
vertical-align: text-bottom;
background-color: currentColor;
// stylelint-disable-next-line property-blacklist
border-radius: 50%;
opacity: 0;
animation: spinner-grow .75s linear infinite;
}
.spinner-grow-sm {
width: $spinner-width-sm;
height: $spinner-height-sm;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_tables.scss
================================================
//
// Basic Bootstrap table
//
.table {
width: 100%;
margin-bottom: $spacer;
color: $table-color;
background-color: $table-bg; // Reset for nesting within parents with `background-color`.
th,
td {
padding: $table-cell-padding;
vertical-align: top;
border-top: $table-border-width solid $table-border-color;
}
thead th {
vertical-align: bottom;
border-bottom: (2 * $table-border-width) solid $table-border-color;
}
tbody + tbody {
border-top: (2 * $table-border-width) solid $table-border-color;
}
}
//
// Condensed table w/ half padding
//
.table-sm {
th,
td {
padding: $table-cell-padding-sm;
}
}
// Border versions
//
// Add or remove borders all around the table and between all the columns.
.table-bordered {
border: $table-border-width solid $table-border-color;
th,
td {
border: $table-border-width solid $table-border-color;
}
thead {
th,
td {
border-bottom-width: 2 * $table-border-width;
}
}
}
.table-borderless {
th,
td,
thead th,
tbody + tbody {
border: 0;
}
}
// Zebra-striping
//
// Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-accent-bg;
}
}
// Hover effect
//
// Placed here since it has to come after the potential zebra striping
.table-hover {
tbody tr {
@include hover {
color: $table-hover-color;
background-color: $table-hover-bg;
}
}
}
// Table backgrounds
//
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
@each $color, $value in $theme-colors {
@include table-row-variant($color, theme-color-level($color, $table-bg-level), theme-color-level($color, $table-border-level));
}
@include table-row-variant(active, $table-active-bg);
// Dark styles
//
// Same table markup, but inverted color scheme: dark background and light text.
// stylelint-disable-next-line no-duplicate-selectors
.table {
.thead-dark {
th {
color: $table-dark-color;
background-color: $table-dark-bg;
border-color: $table-dark-border-color;
}
}
.thead-light {
th {
color: $table-head-color;
background-color: $table-head-bg;
border-color: $table-border-color;
}
}
}
.table-dark {
color: $table-dark-color;
background-color: $table-dark-bg;
th,
td,
thead th {
border-color: $table-dark-border-color;
}
&.table-bordered {
border: 0;
}
&.table-striped {
tbody tr:nth-of-type(odd) {
background-color: $table-dark-accent-bg;
}
}
&.table-hover {
tbody tr {
@include hover {
color: $table-dark-hover-color;
background-color: $table-dark-hover-bg;
}
}
}
}
// Responsive tables
//
// Generate series of `.table-responsive-*` classes for configuring the screen
// size of where your table will overflow.
.table-responsive {
@each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints);
{$infix} {
@include media-breakpoint-down($breakpoint) {
display: block;
width: 100%;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
// Prevent double border on horizontal scroll due to use of `display: block;`
> .table-bordered {
border: 0;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_toasts.scss
================================================
.toast {
max-width: $toast-max-width;
overflow: hidden; // cheap rounded corners on nested items
@include font-size($toast-font-size);
color: $toast-color;
background-color: $toast-background-color;
background-clip: padding-box;
border: $toast-border-width solid $toast-border-color;
box-shadow: $toast-box-shadow;
backdrop-filter: blur(10px);
opacity: 0;
@include border-radius($toast-border-radius);
&:not(:last-child) {
margin-bottom: $toast-padding-x;
}
&.showing {
opacity: 1;
}
&.show {
display: block;
opacity: 1;
}
&.hide {
display: none;
}
}
.toast-header {
display: flex;
align-items: center;
padding: $toast-padding-y $toast-padding-x;
color: $toast-header-color;
background-color: $toast-header-background-color;
background-clip: padding-box;
border-bottom: $toast-border-width solid $toast-header-border-color;
}
.toast-body {
padding: $toast-padding-x; // apply to both vertical and horizontal
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_tooltip.scss
================================================
// Base class
.tooltip {
position: absolute;
z-index: $zindex-tooltip;
display: block;
margin: $tooltip-margin;
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
@include reset-text();
@include font-size($tooltip-font-size);
// Allow breaking very long words so they don't overflow the tooltip's bounds
word-wrap: break-word;
opacity: 0;
&.show { opacity: $tooltip-opacity; }
.arrow {
position: absolute;
display: block;
width: $tooltip-arrow-width;
height: $tooltip-arrow-height;
&::before {
position: absolute;
content: "";
border-color: transparent;
border-style: solid;
}
}
}
.bs-tooltip-top {
padding: $tooltip-arrow-height 0;
.arrow {
bottom: 0;
&::before {
top: 0;
border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
border-top-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-right {
padding: 0 $tooltip-arrow-height;
.arrow {
left: 0;
width: $tooltip-arrow-height;
height: $tooltip-arrow-width;
&::before {
right: 0;
border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
border-right-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-bottom {
padding: $tooltip-arrow-height 0;
.arrow {
top: 0;
&::before {
bottom: 0;
border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
border-bottom-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-left {
padding: 0 $tooltip-arrow-height;
.arrow {
right: 0;
width: $tooltip-arrow-height;
height: $tooltip-arrow-width;
&::before {
left: 0;
border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
border-left-color: $tooltip-arrow-color;
}
}
}
.bs-tooltip-auto {
&[x-placement^="top"] {
@extend .bs-tooltip-top;
}
&[x-placement^="right"] {
@extend .bs-tooltip-right;
}
&[x-placement^="bottom"] {
@extend .bs-tooltip-bottom;
}
&[x-placement^="left"] {
@extend .bs-tooltip-left;
}
}
// Wrapper for the tooltip content
.tooltip-inner {
max-width: $tooltip-max-width;
padding: $tooltip-padding-y $tooltip-padding-x;
color: $tooltip-color;
text-align: center;
background-color: $tooltip-bg;
@include border-radius($tooltip-border-radius);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_transitions.scss
================================================
.fade {
@include transition($transition-fade);
&:not(.show) {
opacity: 0;
}
}
.collapse {
&:not(.show) {
display: none;
}
}
.collapsing {
position: relative;
height: 0;
overflow: hidden;
@include transition($transition-collapse);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_type.scss
================================================
// stylelint-disable declaration-no-important, selector-list-comma-newline-after
//
// Headings
//
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6 {
margin-bottom: $headings-margin-bottom;
font-family: $headings-font-family;
font-weight: $headings-font-weight;
line-height: $headings-line-height;
color: $headings-color;
}
h1, .h1 { @include font-size($h1-font-size); }
h2, .h2 { @include font-size($h2-font-size); }
h3, .h3 { @include font-size($h3-font-size); }
h4, .h4 { @include font-size($h4-font-size); }
h5, .h5 { @include font-size($h5-font-size); }
h6, .h6 { @include font-size($h6-font-size); }
.lead {
@include font-size($lead-font-size);
font-weight: $lead-font-weight;
}
// Type display classes
.display-1 {
@include font-size($display1-size);
font-weight: $display1-weight;
line-height: $display-line-height;
}
.display-2 {
@include font-size($display2-size);
font-weight: $display2-weight;
line-height: $display-line-height;
}
.display-3 {
@include font-size($display3-size);
font-weight: $display3-weight;
line-height: $display-line-height;
}
.display-4 {
@include font-size($display4-size);
font-weight: $display4-weight;
line-height: $display-line-height;
}
//
// Horizontal rules
//
hr {
margin-top: $hr-margin-y;
margin-bottom: $hr-margin-y;
border: 0;
border-top: $hr-border-width solid $hr-border-color;
}
//
// Emphasis
//
small,
.small {
@include font-size($small-font-size);
font-weight: $font-weight-normal;
}
mark,
.mark {
padding: $mark-padding;
background-color: $mark-bg;
}
//
// Lists
//
.list-unstyled {
@include list-unstyled;
}
// Inline turns list items into inline-block
.list-inline {
@include list-unstyled;
}
.list-inline-item {
display: inline-block;
&:not(:last-child) {
margin-right: $list-inline-padding;
}
}
//
// Misc
//
// Builds on `abbr`
.initialism {
@include font-size(90%);
text-transform: uppercase;
}
// Blockquotes
.blockquote {
margin-bottom: $spacer;
@include font-size($blockquote-font-size);
}
.blockquote-footer {
display: block;
@include font-size($blockquote-small-font-size);
color: $blockquote-small-color;
&::before {
content: "\2014\00A0"; // em dash, nbsp
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/_utilities.scss
================================================
@import "utilities/align";
@import "utilities/background";
@import "utilities/borders";
@import "utilities/clearfix";
@import "utilities/display";
@import "utilities/embed";
@import "utilities/flex";
@import "utilities/float";
@import "utilities/overflow";
@import "utilities/position";
@import "utilities/screenreaders";
@import "utilities/shadows";
@import "utilities/sizing";
@import "utilities/stretched-link";
@import "utilities/spacing";
@import "utilities/text";
@import "utilities/visibility";
================================================
FILE: docs/current-version/assets/scss/bootstrap/_variables.scss
================================================
// Variables
//
// Variables should follow the `$component-state-property-size` formula for
// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.
// Color system
$white: #fff !default;
$gray-100: #f8f9fa !default;
$gray-200: #e9ecef !default;
$gray-300: #dee2e6 !default;
$gray-400: #ced4da !default;
$gray-500: #adb5bd !default;
$gray-600: #6c757d !default;
$gray-700: #495057 !default;
$gray-800: #343a40 !default;
$gray-900: #212529 !default;
$black: #000 !default;
$grays: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$grays: map-merge(
(
"100": $gray-100,
"200": $gray-200,
"300": $gray-300,
"400": $gray-400,
"500": $gray-500,
"600": $gray-600,
"700": $gray-700,
"800": $gray-800,
"900": $gray-900
),
$grays
);
$blue: #007bff !default;
$indigo: #6610f2 !default;
$purple: #6f42c1 !default;
$pink: #e83e8c !default;
$red: #dc3545 !default;
$orange: #fd7e14 !default;
$yellow: #ffc107 !default;
$green: #28a745 !default;
$teal: #20c997 !default;
$cyan: #17a2b8 !default;
$colors: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$colors: map-merge(
(
"blue": $blue,
"indigo": $indigo,
"purple": $purple,
"pink": $pink,
"red": $red,
"orange": $orange,
"yellow": $yellow,
"green": $green,
"teal": $teal,
"cyan": $cyan,
"white": $white,
"gray": $gray-600,
"gray-dark": $gray-800
),
$colors
);
$primary: $blue !default;
$secondary: $gray-600 !default;
$success: $green !default;
$info: $cyan !default;
$warning: $yellow !default;
$danger: $red !default;
$light: $gray-100 !default;
$dark: $gray-800 !default;
$theme-colors: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$theme-colors: map-merge(
(
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark
),
$theme-colors
);
// Set a specific jump point for requesting color jumps
$theme-color-interval: 8% !default;
// The yiq lightness value that determines when the lightness of color changes from "dark" to "light". Acceptable values are between 0 and 255.
$yiq-contrasted-threshold: 150 !default;
// Customize the light and dark text colors for use in our YIQ color contrast function.
$yiq-text-dark: $gray-900 !default;
$yiq-text-light: $white !default;
// Options
//
// Quickly modify global styling by enabling or disabling optional features.
$enable-caret: true !default;
$enable-rounded: true !default;
$enable-shadows: false !default;
$enable-gradients: false !default;
$enable-transitions: true !default;
$enable-prefers-reduced-motion-media-query: true !default;
$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS
$enable-grid-classes: true !default;
$enable-pointer-cursor-for-buttons: true !default;
$enable-print-styles: true !default;
$enable-responsive-font-sizes: false !default;
$enable-validation-icons: true !default;
$enable-deprecation-messages: true !default;
// Spacing
//
// Control the default styling of most Bootstrap elements by modifying these
// variables. Mostly focused on spacing.
// You can add more entries to the $spacers map, should you need more variation.
$spacer: 1rem !default;
$spacers: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$spacers: map-merge(
(
0: 0,
1: ($spacer * .25),
2: ($spacer * .5),
3: $spacer,
4: ($spacer * 1.5),
5: ($spacer * 3)
),
$spacers
);
// This variable affects the `.h-*` and `.w-*` classes.
$sizes: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$sizes: map-merge(
(
25: 25%,
50: 50%,
75: 75%,
100: 100%,
auto: auto
),
$sizes
);
// Body
//
// Settings for the `` element.
$body-bg: $white !default;
$body-color: $gray-900 !default;
// Links
//
// Style anchor elements.
$link-color: theme-color("primary") !default;
$link-decoration: none !default;
$link-hover-color: darken($link-color, 15%) !default;
$link-hover-decoration: underline !default;
// Darken percentage for links with `.text-*` class (e.g. `.text-success`)
$emphasized-link-hover-darken-percentage: 15% !default;
// Paragraphs
//
// Style p element.
$paragraph-margin-bottom: 1rem !default;
// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
@include _assert-ascending($grid-breakpoints, "$grid-breakpoints");
@include _assert-starts-at-zero($grid-breakpoints, "$grid-breakpoints");
// Grid containers
//
// Define the maximum width of `.container` for different screen sizes.
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
) !default;
@include _assert-ascending($container-max-widths, "$container-max-widths");
// Grid columns
//
// Set the number of columns and specify the width of the gutters.
$grid-columns: 12 !default;
$grid-gutter-width: 30px !default;
// Components
//
// Define common padding and border radius sizes and more.
$line-height-lg: 1.5 !default;
$line-height-sm: 1.5 !default;
$border-width: 1px !default;
$border-color: $gray-300 !default;
$border-radius: .25rem !default;
$border-radius-lg: .3rem !default;
$border-radius-sm: .2rem !default;
$rounded-pill: 50rem !default;
$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;
$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;
$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;
$component-active-color: $white !default;
$component-active-bg: theme-color("primary") !default;
$caret-width: .3em !default;
$caret-vertical-align: $caret-width * .85 !default;
$caret-spacing: $caret-width * .85 !default;
$transition-base: all .2s ease-in-out !default;
$transition-fade: opacity .15s linear !default;
$transition-collapse: height .35s ease !default;
$embed-responsive-aspect-ratios: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$embed-responsive-aspect-ratios: join(
(
(21 9),
(16 9),
(4 3),
(1 1),
),
$embed-responsive-aspect-ratios
);
// Typography
//
// Font, line-height, and color for body text, headings, and more.
// stylelint-disable value-keyword-case
$font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" !default;
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !default;
$font-family-base: $font-family-sans-serif !default;
// stylelint-enable value-keyword-case
$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`
$font-size-lg: $font-size-base * 1.25 !default;
$font-size-sm: $font-size-base * .875 !default;
$font-weight-lighter: lighter !default;
$font-weight-light: 300 !default;
$font-weight-normal: 400 !default;
$font-weight-bold: 700 !default;
$font-weight-bolder: bolder !default;
$font-weight-base: $font-weight-normal !default;
$line-height-base: 1.5 !default;
$h1-font-size: $font-size-base * 2.5 !default;
$h2-font-size: $font-size-base * 2 !default;
$h3-font-size: $font-size-base * 1.75 !default;
$h4-font-size: $font-size-base * 1.5 !default;
$h5-font-size: $font-size-base * 1.25 !default;
$h6-font-size: $font-size-base !default;
$headings-margin-bottom: $spacer / 2 !default;
$headings-font-family: null !default;
$headings-font-weight: 500 !default;
$headings-line-height: 1.2 !default;
$headings-color: null !default;
$display1-size: 6rem !default;
$display2-size: 5.5rem !default;
$display3-size: 4.5rem !default;
$display4-size: 3.5rem !default;
$display1-weight: 300 !default;
$display2-weight: 300 !default;
$display3-weight: 300 !default;
$display4-weight: 300 !default;
$display-line-height: $headings-line-height !default;
$lead-font-size: $font-size-base * 1.25 !default;
$lead-font-weight: 300 !default;
$small-font-size: 80% !default;
$text-muted: $gray-600 !default;
$blockquote-small-color: $gray-600 !default;
$blockquote-small-font-size: $small-font-size !default;
$blockquote-font-size: $font-size-base * 1.25 !default;
$hr-border-color: rgba($black, .1) !default;
$hr-border-width: $border-width !default;
$mark-padding: .2em !default;
$dt-font-weight: $font-weight-bold !default;
$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;
$nested-kbd-font-weight: $font-weight-bold !default;
$list-inline-padding: .5rem !default;
$mark-bg: #fcf8e3 !default;
$hr-margin-y: $spacer !default;
// Tables
//
// Customizes the `.table` component with basic values, each used across all table variations.
$table-cell-padding: .75rem !default;
$table-cell-padding-sm: .3rem !default;
$table-color: $body-color !default;
$table-bg: null !default;
$table-accent-bg: rgba($black, .05) !default;
$table-hover-color: $table-color !default;
$table-hover-bg: rgba($black, .075) !default;
$table-active-bg: $table-hover-bg !default;
$table-border-width: $border-width !default;
$table-border-color: $border-color !default;
$table-head-bg: $gray-200 !default;
$table-head-color: $gray-700 !default;
$table-dark-color: $white !default;
$table-dark-bg: $gray-800 !default;
$table-dark-accent-bg: rgba($white, .05) !default;
$table-dark-hover-color: $table-dark-color !default;
$table-dark-hover-bg: rgba($white, .075) !default;
$table-dark-border-color: lighten($table-dark-bg, 7.5%) !default;
$table-dark-color: $white !default;
$table-striped-order: odd !default;
$table-caption-color: $text-muted !default;
$table-bg-level: -9 !default;
$table-border-level: -6 !default;
// Buttons + Forms
//
// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.
$input-btn-padding-y: .375rem !default;
$input-btn-padding-x: .75rem !default;
$input-btn-font-family: null !default;
$input-btn-font-size: $font-size-base !default;
$input-btn-line-height: $line-height-base !default;
$input-btn-focus-width: .2rem !default;
$input-btn-focus-color: rgba($component-active-bg, .25) !default;
$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;
$input-btn-padding-y-sm: .25rem !default;
$input-btn-padding-x-sm: .5rem !default;
$input-btn-font-size-sm: $font-size-sm !default;
$input-btn-line-height-sm: $line-height-sm !default;
$input-btn-padding-y-lg: .5rem !default;
$input-btn-padding-x-lg: 1rem !default;
$input-btn-font-size-lg: $font-size-lg !default;
$input-btn-line-height-lg: $line-height-lg !default;
$input-btn-border-width: $border-width !default;
// Buttons
//
// For each of Bootstrap's buttons, define text, background, and border color.
$btn-padding-y: $input-btn-padding-y !default;
$btn-padding-x: $input-btn-padding-x !default;
$btn-font-family: $input-btn-font-family !default;
$btn-font-size: $input-btn-font-size !default;
$btn-line-height: $input-btn-line-height !default;
$btn-padding-y-sm: $input-btn-padding-y-sm !default;
$btn-padding-x-sm: $input-btn-padding-x-sm !default;
$btn-font-size-sm: $input-btn-font-size-sm !default;
$btn-line-height-sm: $input-btn-line-height-sm !default;
$btn-padding-y-lg: $input-btn-padding-y-lg !default;
$btn-padding-x-lg: $input-btn-padding-x-lg !default;
$btn-font-size-lg: $input-btn-font-size-lg !default;
$btn-line-height-lg: $input-btn-line-height-lg !default;
$btn-border-width: $input-btn-border-width !default;
$btn-font-weight: $font-weight-normal !default;
$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;
$btn-focus-width: $input-btn-focus-width !default;
$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;
$btn-disabled-opacity: .65 !default;
$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;
$btn-link-disabled-color: $gray-600 !default;
$btn-block-spacing-y: .5rem !default;
// Allows for customizing button radius independently from global border radius
$btn-border-radius: $border-radius !default;
$btn-border-radius-lg: $border-radius-lg !default;
$btn-border-radius-sm: $border-radius-sm !default;
$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
// Forms
$label-margin-bottom: .5rem !default;
$input-padding-y: $input-btn-padding-y !default;
$input-padding-x: $input-btn-padding-x !default;
$input-font-family: $input-btn-font-family !default;
$input-font-size: $input-btn-font-size !default;
$input-font-weight: $font-weight-base !default;
$input-line-height: $input-btn-line-height !default;
$input-padding-y-sm: $input-btn-padding-y-sm !default;
$input-padding-x-sm: $input-btn-padding-x-sm !default;
$input-font-size-sm: $input-btn-font-size-sm !default;
$input-line-height-sm: $input-btn-line-height-sm !default;
$input-padding-y-lg: $input-btn-padding-y-lg !default;
$input-padding-x-lg: $input-btn-padding-x-lg !default;
$input-font-size-lg: $input-btn-font-size-lg !default;
$input-line-height-lg: $input-btn-line-height-lg !default;
$input-bg: $white !default;
$input-disabled-bg: $gray-200 !default;
$input-color: $gray-700 !default;
$input-border-color: $gray-400 !default;
$input-border-width: $input-btn-border-width !default;
$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;
$input-border-radius: $border-radius !default;
$input-border-radius-lg: $border-radius-lg !default;
$input-border-radius-sm: $border-radius-sm !default;
$input-focus-bg: $input-bg !default;
$input-focus-border-color: lighten($component-active-bg, 25%) !default;
$input-focus-color: $input-color !default;
$input-focus-width: $input-btn-focus-width !default;
$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
$input-placeholder-color: $gray-600 !default;
$input-plaintext-color: $body-color !default;
$input-height-border: $input-border-width * 2 !default;
$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;
$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;
$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{$input-padding-y / 2}) !default;
$input-height: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}) !default;
$input-height-sm: calc(#{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}) !default;
$input-height-lg: calc(#{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}) !default;
$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
$form-text-margin-top: .25rem !default;
$form-check-input-gutter: 1.25rem !default;
$form-check-input-margin-y: .3rem !default;
$form-check-input-margin-x: .25rem !default;
$form-check-inline-margin-x: .75rem !default;
$form-check-inline-input-margin-x: .3125rem !default;
$form-grid-gutter-width: 10px !default;
$form-group-margin-bottom: 1rem !default;
$input-group-addon-color: $input-color !default;
$input-group-addon-bg: $gray-200 !default;
$input-group-addon-border-color: $input-border-color !default;
$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
$custom-control-gutter: .5rem !default;
$custom-control-spacer-x: 1rem !default;
$custom-control-indicator-size: 1rem !default;
$custom-control-indicator-bg: $input-bg !default;
$custom-control-indicator-bg-size: 50% 50% !default;
$custom-control-indicator-box-shadow: $input-box-shadow !default;
$custom-control-indicator-border-color: $gray-500 !default;
$custom-control-indicator-border-width: $input-border-width !default;
$custom-control-indicator-disabled-bg: $input-disabled-bg !default;
$custom-control-label-disabled-color: $gray-600 !default;
$custom-control-indicator-checked-color: $component-active-color !default;
$custom-control-indicator-checked-bg: $component-active-bg !default;
$custom-control-indicator-checked-disabled-bg: rgba(theme-color("primary"), .5) !default;
$custom-control-indicator-checked-box-shadow: none !default;
$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;
$custom-control-indicator-focus-box-shadow: $input-focus-box-shadow !default;
$custom-control-indicator-focus-border-color: $input-focus-border-color !default;
$custom-control-indicator-active-color: $component-active-color !default;
$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;
$custom-control-indicator-active-box-shadow: none !default;
$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;
$custom-checkbox-indicator-border-radius: $border-radius !default;
$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3e%3c/svg%3e"), "#", "%23") !default;
$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;
$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;
$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3e%3cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3e%3c/svg%3e"), "#", "%23") !default;
$custom-checkbox-indicator-indeterminate-box-shadow: none !default;
$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;
$custom-radio-indicator-border-radius: 50% !default;
$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
$custom-switch-width: $custom-control-indicator-size * 1.75 !default;
$custom-switch-indicator-border-radius: $custom-control-indicator-size / 2 !default;
$custom-switch-indicator-size: calc(#{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}) !default;
$custom-select-padding-y: $input-padding-y !default;
$custom-select-padding-x: $input-padding-x !default;
$custom-select-font-family: $input-font-family !default;
$custom-select-font-size: $input-font-size !default;
$custom-select-height: $input-height !default;
$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator
$custom-select-font-weight: $input-font-weight !default;
$custom-select-line-height: $input-line-height !default;
$custom-select-color: $input-color !default;
$custom-select-disabled-color: $gray-600 !default;
$custom-select-bg: $input-bg !default;
$custom-select-disabled-bg: $gray-200 !default;
$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions
$custom-select-indicator-color: $gray-800 !default;
$custom-select-indicator: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e"), "#", "%23") !default;
$custom-select-background: $custom-select-indicator no-repeat right $custom-select-padding-x center / $custom-select-bg-size !default; // Used so we can have multiple background elements (e.g., arrow and feedback icon)
$custom-select-feedback-icon-padding-right: calc((1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}) !default;
$custom-select-feedback-icon-position: center right ($custom-select-padding-x + $custom-select-indicator-padding) !default;
$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;
$custom-select-border-width: $input-border-width !default;
$custom-select-border-color: $input-border-color !default;
$custom-select-border-radius: $border-radius !default;
$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;
$custom-select-focus-border-color: $input-focus-border-color !default;
$custom-select-focus-width: $input-focus-width !default;
$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width $input-btn-focus-color !default;
$custom-select-padding-y-sm: $input-padding-y-sm !default;
$custom-select-padding-x-sm: $input-padding-x-sm !default;
$custom-select-font-size-sm: $input-font-size-sm !default;
$custom-select-height-sm: $input-height-sm !default;
$custom-select-padding-y-lg: $input-padding-y-lg !default;
$custom-select-padding-x-lg: $input-padding-x-lg !default;
$custom-select-font-size-lg: $input-font-size-lg !default;
$custom-select-height-lg: $input-height-lg !default;
$custom-range-track-width: 100% !default;
$custom-range-track-height: .5rem !default;
$custom-range-track-cursor: pointer !default;
$custom-range-track-bg: $gray-300 !default;
$custom-range-track-border-radius: 1rem !default;
$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;
$custom-range-thumb-width: 1rem !default;
$custom-range-thumb-height: $custom-range-thumb-width !default;
$custom-range-thumb-bg: $component-active-bg !default;
$custom-range-thumb-border: 0 !default;
$custom-range-thumb-border-radius: 1rem !default;
$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;
$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;
$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge
$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;
$custom-range-thumb-disabled-bg: $gray-500 !default;
$custom-file-height: $input-height !default;
$custom-file-height-inner: $input-height-inner !default;
$custom-file-focus-border-color: $input-focus-border-color !default;
$custom-file-focus-box-shadow: $input-focus-box-shadow !default;
$custom-file-disabled-bg: $input-disabled-bg !default;
$custom-file-padding-y: $input-padding-y !default;
$custom-file-padding-x: $input-padding-x !default;
$custom-file-line-height: $input-line-height !default;
$custom-file-font-family: $input-font-family !default;
$custom-file-font-weight: $input-font-weight !default;
$custom-file-color: $input-color !default;
$custom-file-bg: $input-bg !default;
$custom-file-border-width: $input-border-width !default;
$custom-file-border-color: $input-border-color !default;
$custom-file-border-radius: $input-border-radius !default;
$custom-file-box-shadow: $input-box-shadow !default;
$custom-file-button-color: $custom-file-color !default;
$custom-file-button-bg: $input-group-addon-bg !default;
$custom-file-text: (
en: "Browse"
) !default;
// Form validation
$form-feedback-margin-top: $form-text-margin-top !default;
$form-feedback-font-size: $small-font-size !default;
$form-feedback-valid-color: theme-color("success") !default;
$form-feedback-invalid-color: theme-color("danger") !default;
$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
$form-feedback-icon-valid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"), "#", "%23") !default;
$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
$form-feedback-icon-invalid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"), "#", "%23") !default;
$form-validation-states: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
$form-validation-states: map-merge(
(
"valid": (
"color": $form-feedback-valid-color,
"icon": $form-feedback-icon-valid
),
"invalid": (
"color": $form-feedback-invalid-color,
"icon": $form-feedback-icon-invalid
),
),
$form-validation-states
);
// Z-index master list
//
// Warning: Avoid customizing these values. They're used for a bird's eye view
// of components dependent on the z-axis and are designed to all work together.
$zindex-dropdown: 1000 !default;
$zindex-sticky: 1020 !default;
$zindex-fixed: 1030 !default;
$zindex-modal-backdrop: 1040 !default;
$zindex-modal: 1050 !default;
$zindex-popover: 1060 !default;
$zindex-tooltip: 1070 !default;
// Navs
$nav-link-padding-y: .5rem !default;
$nav-link-padding-x: 1rem !default;
$nav-link-disabled-color: $gray-600 !default;
$nav-tabs-border-color: $gray-300 !default;
$nav-tabs-border-width: $border-width !default;
$nav-tabs-border-radius: $border-radius !default;
$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;
$nav-tabs-link-active-color: $gray-700 !default;
$nav-tabs-link-active-bg: $body-bg !default;
$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;
$nav-pills-border-radius: $border-radius !default;
$nav-pills-link-active-color: $component-active-color !default;
$nav-pills-link-active-bg: $component-active-bg !default;
$nav-divider-color: $gray-200 !default;
$nav-divider-margin-y: $spacer / 2 !default;
// Navbar
$navbar-padding-y: $spacer / 2 !default;
$navbar-padding-x: $spacer !default;
$navbar-nav-link-padding-x: .5rem !default;
$navbar-brand-font-size: $font-size-lg !default;
// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link
$nav-link-height: $font-size-base * $line-height-base + $nav-link-padding-y * 2 !default;
$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;
$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;
$navbar-toggler-padding-y: .25rem !default;
$navbar-toggler-padding-x: .75rem !default;
$navbar-toggler-font-size: $font-size-lg !default;
$navbar-toggler-border-radius: $btn-border-radius !default;
$navbar-dark-color: rgba($white, .5) !default;
$navbar-dark-hover-color: rgba($white, .75) !default;
$navbar-dark-active-color: $white !default;
$navbar-dark-disabled-color: rgba($white, .25) !default;
$navbar-dark-toggler-icon-bg: str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
$navbar-dark-toggler-border-color: rgba($white, .1) !default;
$navbar-light-color: rgba($black, .5) !default;
$navbar-light-hover-color: rgba($black, .7) !default;
$navbar-light-active-color: rgba($black, .9) !default;
$navbar-light-disabled-color: rgba($black, .3) !default;
$navbar-light-toggler-icon-bg: str-replace(url("data:image/svg+xml,%3csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3e%3cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e"), "#", "%23") !default;
$navbar-light-toggler-border-color: rgba($black, .1) !default;
$navbar-light-brand-color: $navbar-light-active-color !default;
$navbar-light-brand-hover-color: $navbar-light-active-color !default;
$navbar-dark-brand-color: $navbar-dark-active-color !default;
$navbar-dark-brand-hover-color: $navbar-dark-active-color !default;
// Dropdowns
//
// Dropdown menu container and contents.
$dropdown-min-width: 10rem !default;
$dropdown-padding-y: .5rem !default;
$dropdown-spacer: .125rem !default;
$dropdown-font-size: $font-size-base !default;
$dropdown-color: $body-color !default;
$dropdown-bg: $white !default;
$dropdown-border-color: rgba($black, .15) !default;
$dropdown-border-radius: $border-radius !default;
$dropdown-border-width: $border-width !default;
$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;
$dropdown-divider-bg: $gray-200 !default;
$dropdown-divider-margin-y: $nav-divider-margin-y !default;
$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;
$dropdown-link-color: $gray-900 !default;
$dropdown-link-hover-color: darken($gray-900, 5%) !default;
$dropdown-link-hover-bg: $gray-100 !default;
$dropdown-link-active-color: $component-active-color !default;
$dropdown-link-active-bg: $component-active-bg !default;
$dropdown-link-disabled-color: $gray-600 !default;
$dropdown-item-padding-y: .25rem !default;
$dropdown-item-padding-x: 1.5rem !default;
$dropdown-header-color: $gray-600 !default;
// Pagination
$pagination-padding-y: .5rem !default;
$pagination-padding-x: .75rem !default;
$pagination-padding-y-sm: .25rem !default;
$pagination-padding-x-sm: .5rem !default;
$pagination-padding-y-lg: .75rem !default;
$pagination-padding-x-lg: 1.5rem !default;
$pagination-line-height: 1.25 !default;
$pagination-color: $link-color !default;
$pagination-bg: $white !default;
$pagination-border-width: $border-width !default;
$pagination-border-color: $gray-300 !default;
$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;
$pagination-focus-outline: 0 !default;
$pagination-hover-color: $link-hover-color !default;
$pagination-hover-bg: $gray-200 !default;
$pagination-hover-border-color: $gray-300 !default;
$pagination-active-color: $component-active-color !default;
$pagination-active-bg: $component-active-bg !default;
$pagination-active-border-color: $pagination-active-bg !default;
$pagination-disabled-color: $gray-600 !default;
$pagination-disabled-bg: $white !default;
$pagination-disabled-border-color: $gray-300 !default;
// Jumbotron
$jumbotron-padding: 2rem !default;
$jumbotron-color: null !default;
$jumbotron-bg: $gray-200 !default;
// Cards
$card-spacer-y: .75rem !default;
$card-spacer-x: 1.25rem !default;
$card-border-width: $border-width !default;
$card-border-radius: $border-radius !default;
$card-border-color: rgba($black, .125) !default;
$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;
$card-cap-bg: rgba($black, .03) !default;
$card-cap-color: null !default;
$card-color: null !default;
$card-bg: $white !default;
$card-img-overlay-padding: 1.25rem !default;
$card-group-margin: $grid-gutter-width / 2 !default;
$card-deck-margin: $card-group-margin !default;
$card-columns-count: 3 !default;
$card-columns-gap: 1.25rem !default;
$card-columns-margin: $card-spacer-y !default;
// Tooltips
$tooltip-font-size: $font-size-sm !default;
$tooltip-max-width: 200px !default;
$tooltip-color: $white !default;
$tooltip-bg: $black !default;
$tooltip-border-radius: $border-radius !default;
$tooltip-opacity: .9 !default;
$tooltip-padding-y: .25rem !default;
$tooltip-padding-x: .5rem !default;
$tooltip-margin: 0 !default;
$tooltip-arrow-width: .8rem !default;
$tooltip-arrow-height: .4rem !default;
$tooltip-arrow-color: $tooltip-bg !default;
// Form tooltips must come after regular tooltips
$form-feedback-tooltip-padding-y: $tooltip-padding-y !default;
$form-feedback-tooltip-padding-x: $tooltip-padding-x !default;
$form-feedback-tooltip-font-size: $tooltip-font-size !default;
$form-feedback-tooltip-line-height: $line-height-base !default;
$form-feedback-tooltip-opacity: $tooltip-opacity !default;
$form-feedback-tooltip-border-radius: $tooltip-border-radius !default;
// Popovers
$popover-font-size: $font-size-sm !default;
$popover-bg: $white !default;
$popover-max-width: 276px !default;
$popover-border-width: $border-width !default;
$popover-border-color: rgba($black, .2) !default;
$popover-border-radius: $border-radius-lg !default;
$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;
$popover-header-bg: darken($popover-bg, 3%) !default;
$popover-header-color: $headings-color !default;
$popover-header-padding-y: .5rem !default;
$popover-header-padding-x: .75rem !default;
$popover-body-color: $body-color !default;
$popover-body-padding-y: $popover-header-padding-y !default;
$popover-body-padding-x: $popover-header-padding-x !default;
$popover-arrow-width: 1rem !default;
$popover-arrow-height: .5rem !default;
$popover-arrow-color: $popover-bg !default;
$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;
// Toasts
$toast-max-width: 350px !default;
$toast-padding-x: .75rem !default;
$toast-padding-y: .25rem !default;
$toast-font-size: .875rem !default;
$toast-color: null !default;
$toast-background-color: rgba($white, .85) !default;
$toast-border-width: 1px !default;
$toast-border-color: rgba(0, 0, 0, .1) !default;
$toast-border-radius: .25rem !default;
$toast-box-shadow: 0 .25rem .75rem rgba($black, .1) !default;
$toast-header-color: $gray-600 !default;
$toast-header-background-color: rgba($white, .85) !default;
$toast-header-border-color: rgba(0, 0, 0, .05) !default;
// Badges
$badge-font-size: 75% !default;
$badge-font-weight: $font-weight-bold !default;
$badge-padding-y: .25em !default;
$badge-padding-x: .4em !default;
$badge-border-radius: $border-radius !default;
$badge-transition: $btn-transition !default;
$badge-focus-width: $input-btn-focus-width !default;
$badge-pill-padding-x: .6em !default;
// Use a higher than normal value to ensure completely rounded edges when
// customizing padding or font-size on labels.
$badge-pill-border-radius: 10rem !default;
// Modals
// Padding applied to the modal body
$modal-inner-padding: 1rem !default;
$modal-dialog-margin: .5rem !default;
$modal-dialog-margin-y-sm-up: 1.75rem !default;
$modal-title-line-height: $line-height-base !default;
$modal-content-color: null !default;
$modal-content-bg: $white !default;
$modal-content-border-color: rgba($black, .2) !default;
$modal-content-border-width: $border-width !default;
$modal-content-border-radius: $border-radius-lg !default;
$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;
$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;
$modal-backdrop-bg: $black !default;
$modal-backdrop-opacity: .5 !default;
$modal-header-border-color: $border-color !default;
$modal-footer-border-color: $modal-header-border-color !default;
$modal-header-border-width: $modal-content-border-width !default;
$modal-footer-border-width: $modal-header-border-width !default;
$modal-header-padding-y: 1rem !default;
$modal-header-padding-x: 1rem !default;
$modal-header-padding: $modal-header-padding-y $modal-header-padding-x !default; // Keep this for backwards compatibility
$modal-xl: 1140px !default;
$modal-lg: 800px !default;
$modal-md: 500px !default;
$modal-sm: 300px !default;
$modal-fade-transform: translate(0, -50px) !default;
$modal-show-transform: none !default;
$modal-transition: transform .3s ease-out !default;
// Alerts
//
// Define alert colors, border radius, and padding.
$alert-padding-y: .75rem !default;
$alert-padding-x: 1.25rem !default;
$alert-margin-bottom: 1rem !default;
$alert-border-radius: $border-radius !default;
$alert-link-font-weight: $font-weight-bold !default;
$alert-border-width: $border-width !default;
$alert-bg-level: -10 !default;
$alert-border-level: -9 !default;
$alert-color-level: 6 !default;
// Progress bars
$progress-height: 1rem !default;
$progress-font-size: $font-size-base * .75 !default;
$progress-bg: $gray-200 !default;
$progress-border-radius: $border-radius !default;
$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;
$progress-bar-color: $white !default;
$progress-bar-bg: theme-color("primary") !default;
$progress-bar-animation-timing: 1s linear infinite !default;
$progress-bar-transition: width .6s ease !default;
// List group
$list-group-color: null !default;
$list-group-bg: $white !default;
$list-group-border-color: rgba($black, .125) !default;
$list-group-border-width: $border-width !default;
$list-group-border-radius: $border-radius !default;
$list-group-item-padding-y: .75rem !default;
$list-group-item-padding-x: 1.25rem !default;
$list-group-hover-bg: $gray-100 !default;
$list-group-active-color: $component-active-color !default;
$list-group-active-bg: $component-active-bg !default;
$list-group-active-border-color: $list-group-active-bg !default;
$list-group-disabled-color: $gray-600 !default;
$list-group-disabled-bg: $list-group-bg !default;
$list-group-action-color: $gray-700 !default;
$list-group-action-hover-color: $list-group-action-color !default;
$list-group-action-active-color: $body-color !default;
$list-group-action-active-bg: $gray-200 !default;
// Image thumbnails
$thumbnail-padding: .25rem !default;
$thumbnail-bg: $body-bg !default;
$thumbnail-border-width: $border-width !default;
$thumbnail-border-color: $gray-300 !default;
$thumbnail-border-radius: $border-radius !default;
$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;
// Figures
$figure-caption-font-size: 90% !default;
$figure-caption-color: $gray-600 !default;
// Breadcrumbs
$breadcrumb-padding-y: .75rem !default;
$breadcrumb-padding-x: 1rem !default;
$breadcrumb-item-padding: .5rem !default;
$breadcrumb-margin-bottom: 1rem !default;
$breadcrumb-bg: $gray-200 !default;
$breadcrumb-divider-color: $gray-600 !default;
$breadcrumb-active-color: $gray-600 !default;
$breadcrumb-divider: quote("/") !default;
$breadcrumb-border-radius: $border-radius !default;
// Carousel
$carousel-control-color: $white !default;
$carousel-control-width: 15% !default;
$carousel-control-opacity: .5 !default;
$carousel-control-hover-opacity: .9 !default;
$carousel-control-transition: opacity .15s ease !default;
$carousel-indicator-width: 30px !default;
$carousel-indicator-height: 3px !default;
$carousel-indicator-hit-area-height: 10px !default;
$carousel-indicator-spacer: 3px !default;
$carousel-indicator-active-bg: $white !default;
$carousel-indicator-transition: opacity .6s ease !default;
$carousel-caption-width: 70% !default;
$carousel-caption-color: $white !default;
$carousel-control-icon-width: 20px !default;
$carousel-control-prev-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3e%3c/svg%3e"), "#", "%23") !default;
$carousel-control-next-icon-bg: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3e%3cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3e%3c/svg%3e"), "#", "%23") !default;
$carousel-transition-duration: .6s !default;
$carousel-transition: transform $carousel-transition-duration ease-in-out !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)
// Spinners
$spinner-width: 2rem !default;
$spinner-height: $spinner-width !default;
$spinner-border-width: .25em !default;
$spinner-width-sm: 1rem !default;
$spinner-height-sm: $spinner-width-sm !default;
$spinner-border-width-sm: .2em !default;
// Close
$close-font-size: $font-size-base * 1.5 !default;
$close-font-weight: $font-weight-bold !default;
$close-color: $black !default;
$close-text-shadow: 0 1px 0 $white !default;
// Code
$code-font-size: 87.5% !default;
$code-color: $pink !default;
$kbd-padding-y: .2rem !default;
$kbd-padding-x: .4rem !default;
$kbd-font-size: $code-font-size !default;
$kbd-color: $white !default;
$kbd-bg: $gray-900 !default;
$pre-color: $gray-900 !default;
$pre-scrollable-max-height: 340px !default;
// Utilities
$displays: none, inline, inline-block, block, table, table-row, table-cell, flex, inline-flex !default;
$overflows: auto, hidden !default;
$positions: static, relative, absolute, fixed, sticky !default;
// Printing
$print-page-size: a3 !default;
$print-body-min-width: map-get($grid-breakpoints, "lg") !default;
================================================
FILE: docs/current-version/assets/scss/bootstrap/bootstrap-grid.scss
================================================
/*!
* Bootstrap Grid v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
html {
box-sizing: border-box;
-ms-overflow-style: scrollbar;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
@import "functions";
@import "variables";
@import "mixins/breakpoints";
@import "mixins/grid-framework";
@import "mixins/grid";
@import "grid";
@import "utilities/display";
@import "utilities/flex";
@import "utilities/spacing";
================================================
FILE: docs/current-version/assets/scss/bootstrap/bootstrap-reboot.scss
================================================
/*!
* Bootstrap Reboot v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/
@import "functions";
@import "variables";
@import "mixins";
@import "reboot";
================================================
FILE: docs/current-version/assets/scss/bootstrap/bootstrap.scss
================================================
/*!
* Bootstrap v4.3.1 (https://getbootstrap.com/)
* Copyright 2011-2019 The Bootstrap Authors
* Copyright 2011-2019 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/
@import "functions";
@import "variables";
@import "mixins";
@import "root";
@import "reboot";
@import "type";
@import "images";
@import "code";
@import "grid";
@import "tables";
@import "forms";
@import "buttons";
@import "transitions";
@import "dropdown";
@import "button-group";
@import "input-group";
@import "custom-forms";
@import "nav";
@import "navbar";
@import "card";
@import "breadcrumb";
@import "pagination";
@import "badge";
@import "jumbotron";
@import "alert";
@import "progress";
@import "media";
@import "list-group";
@import "close";
@import "toasts";
@import "modal";
@import "tooltip";
@import "popover";
@import "carousel";
@import "spinners";
@import "utilities";
@import "print";
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_alert.scss
================================================
@mixin alert-variant($background, $border, $color) {
color: $color;
@include gradient-bg($background);
border-color: $border;
hr {
border-top-color: darken($border, 5%);
}
.alert-link {
color: darken($color, 10%);
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_background-variant.scss
================================================
// stylelint-disable declaration-no-important
// Contextual backgrounds
@mixin bg-variant($parent, $color) {
#{$parent} {
background-color: $color !important;
}
a#{$parent},
button#{$parent} {
@include hover-focus {
background-color: darken($color, 10%) !important;
}
}
}
@mixin bg-gradient-variant($parent, $color) {
#{$parent} {
background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_badge.scss
================================================
@mixin badge-variant($bg) {
color: color-yiq($bg);
background-color: $bg;
@at-root a#{&} {
@include hover-focus {
color: color-yiq($bg);
background-color: darken($bg, 10%);
}
&:focus,
&.focus {
outline: 0;
box-shadow: 0 0 0 $badge-focus-width rgba($bg, .5);
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_border-radius.scss
================================================
// stylelint-disable property-blacklist
// Single side border-radius
@mixin border-radius($radius: $border-radius, $fallback-border-radius: false) {
@if $enable-rounded {
border-radius: $radius;
}
@else if $fallback-border-radius != false {
border-radius: $fallback-border-radius;
}
}
@mixin border-top-radius($radius) {
@if $enable-rounded {
border-top-left-radius: $radius;
border-top-right-radius: $radius;
}
}
@mixin border-right-radius($radius) {
@if $enable-rounded {
border-top-right-radius: $radius;
border-bottom-right-radius: $radius;
}
}
@mixin border-bottom-radius($radius) {
@if $enable-rounded {
border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius;
}
}
@mixin border-left-radius($radius) {
@if $enable-rounded {
border-top-left-radius: $radius;
border-bottom-left-radius: $radius;
}
}
@mixin border-top-left-radius($radius) {
@if $enable-rounded {
border-top-left-radius: $radius;
}
}
@mixin border-top-right-radius($radius) {
@if $enable-rounded {
border-top-right-radius: $radius;
}
}
@mixin border-bottom-right-radius($radius) {
@if $enable-rounded {
border-bottom-right-radius: $radius;
}
}
@mixin border-bottom-left-radius($radius) {
@if $enable-rounded {
border-bottom-left-radius: $radius;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_box-shadow.scss
================================================
@mixin box-shadow($shadow...) {
@if $enable-shadows {
$result: ();
@if (length($shadow) == 1) {
// We can pass `@include box-shadow(none);`
$result: $shadow;
} @else {
// Filter to avoid invalid properties for example `box-shadow: none, 1px 1px black;`
@for $i from 1 through length($shadow) {
@if nth($shadow, $i) != "none" {
$result: append($result, nth($shadow, $i), "comma");
}
}
}
@if (length($result) > 0) {
box-shadow: $result;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_breakpoints.scss
================================================
// Breakpoint viewport sizes and media queries.
//
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
//
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
//
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
// Name of the next breakpoint, or null for the last breakpoint.
//
// >> breakpoint-next(sm)
// md
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// md
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
// md
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
$n: index($breakpoint-names, $name);
@return if($n != null and $n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
}
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
// Maximum breakpoint width. Null for the largest (last) breakpoint.
// The maximum value is calculated as the minimum of the next one less 0.02px
// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.
// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
// See https://bugs.webkit.org/show_bug.cgi?id=178261
//
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 767.98px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
$next: breakpoint-next($name, $breakpoints);
@return if($next, breakpoint-min($next, $breakpoints) - .02, null);
}
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.
// Useful for making responsive utilities.
//
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
// Makes the @content apply to the given breakpoint and narrower.
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
$max: breakpoint-max($name, $breakpoints);
@if $max {
@media (max-width: $max) {
@content;
}
} @else {
@content;
}
}
// Media that spans multiple breakpoint widths.
// Makes the @content apply between the min and max breakpoints
@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($lower, $breakpoints);
$max: breakpoint-max($upper, $breakpoints);
@if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) {
@content;
}
} @else if $max == null {
@include media-breakpoint-up($lower, $breakpoints) {
@content;
}
} @else if $min == null {
@include media-breakpoint-down($upper, $breakpoints) {
@content;
}
}
}
// Media between the breakpoint's minimum and maximum widths.
// No minimum for the smallest breakpoint, and no maximum for the largest one.
// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
$max: breakpoint-max($name, $breakpoints);
@if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) {
@content;
}
} @else if $max == null {
@include media-breakpoint-up($name, $breakpoints) {
@content;
}
} @else if $min == null {
@include media-breakpoint-down($name, $breakpoints) {
@content;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_buttons.scss
================================================
// Button variants
//
// Easily pump out default styles, as well as :hover, :focus, :active,
// and disabled options for all buttons
@mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) {
color: color-yiq($background);
@include gradient-bg($background);
border-color: $border;
@include box-shadow($btn-box-shadow);
@include hover {
color: color-yiq($hover-background);
@include gradient-bg($hover-background);
border-color: $hover-border;
}
&:focus,
&.focus {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
} @else {
box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
}
}
// Disabled comes first so active can properly restyle
&.disabled,
&:disabled {
color: color-yiq($background);
background-color: $background;
border-color: $border;
// Remove CSS gradients if they're enabled
@if $enable-gradients {
background-image: none;
}
}
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active,
.show > &.dropdown-toggle {
color: color-yiq($active-background);
background-color: $active-background;
@if $enable-gradients {
background-image: none; // Remove the gradient for the pressed/active state
}
border-color: $active-border;
&:focus {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows and $btn-active-box-shadow != none {
box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
} @else {
box-shadow: 0 0 0 $btn-focus-width rgba(mix(color-yiq($background), $border, 15%), .5);
}
}
}
}
@mixin button-outline-variant($color, $color-hover: color-yiq($color), $active-background: $color, $active-border: $color) {
color: $color;
border-color: $color;
@include hover {
color: $color-hover;
background-color: $active-background;
border-color: $active-border;
}
&:focus,
&.focus {
box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
}
&.disabled,
&:disabled {
color: $color;
background-color: transparent;
}
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active,
.show > &.dropdown-toggle {
color: color-yiq($active-background);
background-color: $active-background;
border-color: $active-border;
&:focus {
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows and $btn-active-box-shadow != none {
box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5);
} @else {
box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
}
}
}
}
// Button sizes
@mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
padding: $padding-y $padding-x;
@include font-size($font-size);
line-height: $line-height;
// Manually declare to provide an override to the browser default
@include border-radius($border-radius, 0);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_caret.scss
================================================
@mixin caret-down {
border-top: $caret-width solid;
border-right: $caret-width solid transparent;
border-bottom: 0;
border-left: $caret-width solid transparent;
}
@mixin caret-up {
border-top: 0;
border-right: $caret-width solid transparent;
border-bottom: $caret-width solid;
border-left: $caret-width solid transparent;
}
@mixin caret-right {
border-top: $caret-width solid transparent;
border-right: 0;
border-bottom: $caret-width solid transparent;
border-left: $caret-width solid;
}
@mixin caret-left {
border-top: $caret-width solid transparent;
border-right: $caret-width solid;
border-bottom: $caret-width solid transparent;
}
@mixin caret($direction: down) {
@if $enable-caret {
&::after {
display: inline-block;
margin-left: $caret-spacing;
vertical-align: $caret-vertical-align;
content: "";
@if $direction == down {
@include caret-down;
} @else if $direction == up {
@include caret-up;
} @else if $direction == right {
@include caret-right;
}
}
@if $direction == left {
&::after {
display: none;
}
&::before {
display: inline-block;
margin-right: $caret-spacing;
vertical-align: $caret-vertical-align;
content: "";
@include caret-left;
}
}
&:empty::after {
margin-left: 0;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_clearfix.scss
================================================
@mixin clearfix() {
&::after {
display: block;
clear: both;
content: "";
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_deprecate.scss
================================================
// Deprecate mixin
//
// This mixin can be used to deprecate mixins or functions.
// `$enable-deprecation-messages` is a global variable, `$ignore-warning` is a variable that can be passed to
// some deprecated mixins to suppress the warning (for example if the mixin is still be used in the current version of Bootstrap)
@mixin deprecate($name, $deprecate-version, $remove-version, $ignore-warning: false) {
@if ($enable-deprecation-messages != false and $ignore-warning != true) {
@warn "#{$name} has been deprecated as of #{$deprecate-version}. It will be removed entirely in #{$remove-version}.";
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_float.scss
================================================
// stylelint-disable declaration-no-important
@mixin float-left {
float: left !important;
@include deprecate("The `float-left` mixin", "v4.3.0", "v5");
}
@mixin float-right {
float: right !important;
@include deprecate("The `float-right` mixin", "v4.3.0", "v5");
}
@mixin float-none {
float: none !important;
@include deprecate("The `float-none` mixin", "v4.3.0", "v5");
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_forms.scss
================================================
// Form control focus state
//
// Generate a customized focus state and for any input with the specified color,
// which defaults to the `$input-focus-border-color` variable.
//
// We highly encourage you to not customize the default value, but instead use
// this to tweak colors on an as-needed basis. This aesthetic change is based on
// WebKit's default styles, but applicable to a wider range of browsers. Its
// usability and accessibility should be taken into account with any change.
//
// Example usage: change the default blue border and shadow to white for better
// contrast against a dark gray background.
@mixin form-control-focus() {
&:focus {
color: $input-focus-color;
background-color: $input-focus-bg;
border-color: $input-focus-border-color;
outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows {
box-shadow: $input-box-shadow, $input-focus-box-shadow;
} @else {
box-shadow: $input-focus-box-shadow;
}
}
}
@mixin form-validation-state($state, $color, $icon) {
.#{$state}-feedback {
display: none;
width: 100%;
margin-top: $form-feedback-margin-top;
@include font-size($form-feedback-font-size);
color: $color;
}
.#{$state}-tooltip {
position: absolute;
top: 100%;
z-index: 5;
display: none;
max-width: 100%; // Contain to parent when possible
padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
margin-top: .1rem;
@include font-size($form-feedback-tooltip-font-size);
line-height: $form-feedback-tooltip-line-height;
color: color-yiq($color);
background-color: rgba($color, $form-feedback-tooltip-opacity);
@include border-radius($form-feedback-tooltip-border-radius);
}
.form-control {
.was-validated &:#{$state},
&.is-#{$state} {
border-color: $color;
@if $enable-validation-icons {
padding-right: $input-height-inner;
background-image: $icon;
background-repeat: no-repeat;
background-position: center right $input-height-inner-quarter;
background-size: $input-height-inner-half $input-height-inner-half;
}
&:focus {
border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
}
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
}
}
// stylelint-disable-next-line selector-no-qualifying-type
textarea.form-control {
.was-validated &:#{$state},
&.is-#{$state} {
@if $enable-validation-icons {
padding-right: $input-height-inner;
background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
}
}
}
.custom-select {
.was-validated &:#{$state},
&.is-#{$state} {
border-color: $color;
@if $enable-validation-icons {
padding-right: $custom-select-feedback-icon-padding-right;
background: $custom-select-background, $icon $custom-select-bg no-repeat $custom-select-feedback-icon-position / $custom-select-feedback-icon-size;
}
&:focus {
border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
}
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
}
}
.form-control-file {
.was-validated &:#{$state},
&.is-#{$state} {
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
}
}
.form-check-input {
.was-validated &:#{$state},
&.is-#{$state} {
~ .form-check-label {
color: $color;
}
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
}
}
.custom-control-input {
.was-validated &:#{$state},
&.is-#{$state} {
~ .custom-control-label {
color: $color;
&::before {
border-color: $color;
}
}
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
&:checked {
~ .custom-control-label::before {
border-color: lighten($color, 10%);
@include gradient-bg(lighten($color, 10%));
}
}
&:focus {
~ .custom-control-label::before {
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
}
&:not(:checked) ~ .custom-control-label::before {
border-color: $color;
}
}
}
}
// custom file
.custom-file-input {
.was-validated &:#{$state},
&.is-#{$state} {
~ .custom-file-label {
border-color: $color;
}
~ .#{$state}-feedback,
~ .#{$state}-tooltip {
display: block;
}
&:focus {
~ .custom-file-label {
border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_gradients.scss
================================================
// Gradients
@mixin gradient-bg($color) {
@if $enable-gradients {
background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x;
} @else {
background-color: $color;
}
}
// Horizontal gradient, from left to right
//
// Creates two color stops, start and end, by specifying a color and position for each color stop.
@mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);
background-repeat: repeat-x;
}
// Vertical gradient, from top to bottom
//
// Creates two color stops, start and end, by specifying a color and position for each color stop.
@mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);
background-repeat: repeat-x;
}
@mixin gradient-directional($start-color: $gray-700, $end-color: $gray-800, $deg: 45deg) {
background-image: linear-gradient($deg, $start-color, $end-color);
background-repeat: repeat-x;
}
@mixin gradient-x-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);
background-repeat: no-repeat;
}
@mixin gradient-y-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
background-repeat: no-repeat;
}
@mixin gradient-radial($inner-color: $gray-700, $outer-color: $gray-800) {
background-image: radial-gradient(circle, $inner-color, $outer-color);
background-repeat: no-repeat;
}
@mixin gradient-striped($color: rgba($white, .15), $angle: 45deg) {
background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_grid-framework.scss
================================================
// Framework grid generation
//
// Used only by Bootstrap to generate the correct number of grid classes given
// any value of `$grid-columns`.
@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
// Common properties for all breakpoints
%grid-column {
position: relative;
width: 100%;
padding-right: $gutter / 2;
padding-left: $gutter / 2;
}
@each $breakpoint in map-keys($breakpoints) {
$infix: breakpoint-infix($breakpoint, $breakpoints);
// Allow columns to stretch full width below their breakpoints
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@extend %grid-column;
}
}
.col#{$infix},
.col#{$infix}-auto {
@extend %grid-column;
}
@include media-breakpoint-up($breakpoint, $breakpoints) {
// Provide basic `.col-{bp}` classes for equal-width flexbox columns
.col#{$infix} {
flex-basis: 0;
flex-grow: 1;
max-width: 100%;
}
.col#{$infix}-auto {
flex: 0 0 auto;
width: auto;
max-width: 100%; // Reset earlier grid tiers
}
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@include make-col($i, $columns);
}
}
.order#{$infix}-first { order: -1; }
.order#{$infix}-last { order: $columns + 1; }
@for $i from 0 through $columns {
.order#{$infix}-#{$i} { order: $i; }
}
// `$columns - 1` because offsetting by the width of an entire row isn't possible
@for $i from 0 through ($columns - 1) {
@if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
.offset#{$infix}-#{$i} {
@include make-col-offset($i, $columns);
}
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_grid.scss
================================================
/// Grid system
//
// Generate semantic grid columns with these mixins.
@mixin make-container($gutter: $grid-gutter-width) {
width: 100%;
padding-right: $gutter / 2;
padding-left: $gutter / 2;
margin-right: auto;
margin-left: auto;
}
// For each breakpoint, define the maximum width of the container in a media query
@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {
@each $breakpoint, $container-max-width in $max-widths {
@include media-breakpoint-up($breakpoint, $breakpoints) {
max-width: $container-max-width;
}
}
}
@mixin make-row($gutter: $grid-gutter-width) {
display: flex;
flex-wrap: wrap;
margin-right: -$gutter / 2;
margin-left: -$gutter / 2;
}
@mixin make-col-ready($gutter: $grid-gutter-width) {
position: relative;
// Prevent columns from becoming too narrow when at smaller grid tiers by
// always setting `width: 100%;`. This works because we use `flex` values
// later on to override this initial width.
width: 100%;
padding-right: $gutter / 2;
padding-left: $gutter / 2;
}
@mixin make-col($size, $columns: $grid-columns) {
flex: 0 0 percentage($size / $columns);
// Add a `max-width` to ensure content within each column does not blow out
// the width of the column. Applies to IE10+ and Firefox. Chrome and Safari
// do not appear to require this.
max-width: percentage($size / $columns);
}
@mixin make-col-offset($size, $columns: $grid-columns) {
$num: $size / $columns;
margin-left: if($num == 0, 0, percentage($num));
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_hover.scss
================================================
// Hover mixin and `$enable-hover-media-query` are deprecated.
//
// Originally added during our alphas and maintained during betas, this mixin was
// designed to prevent `:hover` stickiness on iOS-an issue where hover styles
// would persist after initial touch.
//
// For backward compatibility, we've kept these mixins and updated them to
// always return their regular pseudo-classes instead of a shimmed media query.
//
// Issue: https://github.com/twbs/bootstrap/issues/25195
@mixin hover {
&:hover { @content; }
}
@mixin hover-focus {
&:hover,
&:focus {
@content;
}
}
@mixin plain-hover-focus {
&,
&:hover,
&:focus {
@content;
}
}
@mixin hover-focus-active {
&:hover,
&:focus,
&:active {
@content;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_image.scss
================================================
// Image Mixins
// - Responsive image
// - Retina image
// Responsive image
//
// Keep images from scaling beyond the width of their parents.
@mixin img-fluid {
// Part 1: Set a maximum relative to the parent
max-width: 100%;
// Part 2: Override the height to auto, otherwise images will be stretched
// when setting a width and height attribute on the img element.
height: auto;
}
// Retina image
//
// Short retina mixin for setting background-image and -size.
@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
background-image: url($file-1x);
// Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,
// but doesn't convert dppx=>dpi.
// There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.
// Compatibility info: https://caniuse.com/#feat=css-media-resolution
@media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx
only screen and (min-resolution: 2dppx) { // Standardized
background-image: url($file-2x);
background-size: $width-1x $height-1x;
}
@include deprecate("`img-retina()`", "v4.3.0", "v5");
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_list-group.scss
================================================
// List Groups
@mixin list-group-item-variant($state, $background, $color) {
.list-group-item-#{$state} {
color: $color;
background-color: $background;
&.list-group-item-action {
@include hover-focus {
color: $color;
background-color: darken($background, 5%);
}
&.active {
color: $white;
background-color: $color;
border-color: $color;
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_lists.scss
================================================
// Lists
// Unstyled keeps list items block level, just removes default browser padding and list-style
@mixin list-unstyled {
padding-left: 0;
list-style: none;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_nav-divider.scss
================================================
// Horizontal dividers
//
// Dividers (basically an hr) within dropdowns and nav lists
@mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y) {
height: 0;
margin: $margin-y 0;
overflow: hidden;
border-top: 1px solid $color;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_pagination.scss
================================================
// Pagination
@mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
.page-link {
padding: $padding-y $padding-x;
@include font-size($font-size);
line-height: $line-height;
}
.page-item {
&:first-child {
.page-link {
@include border-left-radius($border-radius);
}
}
&:last-child {
.page-link {
@include border-right-radius($border-radius);
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_reset-text.scss
================================================
@mixin reset-text {
font-family: $font-family-base;
// We deliberately do NOT reset font-size or word-wrap.
font-style: normal;
font-weight: $font-weight-normal;
line-height: $line-height-base;
text-align: left; // Fallback for where `start` is not supported
text-align: start;
text-decoration: none;
text-shadow: none;
text-transform: none;
letter-spacing: normal;
word-break: normal;
word-spacing: normal;
white-space: normal;
line-break: auto;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_resize.scss
================================================
// Resize anything
@mixin resizable($direction) {
overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
resize: $direction; // Options: horizontal, vertical, both
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_screen-reader.scss
================================================
// Only display content to screen readers
//
// See: https://a11yproject.com/posts/how-to-hide-content/
// See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
@mixin sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
// Use in conjunction with .sr-only to only display content when it's focused.
//
// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
//
// Credit: HTML5 Boilerplate
@mixin sr-only-focusable {
&:active,
&:focus {
position: static;
width: auto;
height: auto;
overflow: visible;
clip: auto;
white-space: normal;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_size.scss
================================================
// Sizing shortcuts
@mixin size($width, $height: $width) {
width: $width;
height: $height;
@include deprecate("`size()`", "v4.3.0", "v5");
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_table-row.scss
================================================
// Tables
@mixin table-row-variant($state, $background, $border: null) {
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
.table-#{$state} {
&,
> th,
> td {
background-color: $background;
}
@if $border != null {
th,
td,
thead th,
tbody + tbody {
border-color: $border;
}
}
}
// Hover states for `.table-hover`
// Note: this is not available for cells or rows within `thead` or `tfoot`.
.table-hover {
$hover-background: darken($background, 5%);
.table-#{$state} {
@include hover {
background-color: $hover-background;
> td,
> th {
background-color: $hover-background;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_text-emphasis.scss
================================================
// stylelint-disable declaration-no-important
// Typography
@mixin text-emphasis-variant($parent, $color) {
#{$parent} {
color: $color !important;
}
@if $emphasized-link-hover-darken-percentage != 0 {
a#{$parent} {
@include hover-focus {
color: darken($color, $emphasized-link-hover-darken-percentage) !important;
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_text-hide.scss
================================================
// CSS image replacement
@mixin text-hide($ignore-warning: false) {
// stylelint-disable-next-line font-family-no-missing-generic-family-keyword
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
@include deprecate("`text-hide()`", "v4.1.0", "v5", $ignore-warning);
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_text-truncate.scss
================================================
// Text truncate
// Requires inline-block or block for proper styling
@mixin text-truncate() {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_transition.scss
================================================
// stylelint-disable property-blacklist
@mixin transition($transition...) {
@if $enable-transitions {
@if length($transition) == 0 {
transition: $transition-base;
} @else {
transition: $transition;
}
}
@if $enable-prefers-reduced-motion-media-query {
@media (prefers-reduced-motion: reduce) {
transition: none;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/mixins/_visibility.scss
================================================
// stylelint-disable declaration-no-important
// Visibility
@mixin invisible($visibility) {
visibility: $visibility !important;
@include deprecate("`invisible()`", "v4.3.0", "v5");
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_align.scss
================================================
// stylelint-disable declaration-no-important
.align-baseline { vertical-align: baseline !important; } // Browser default
.align-top { vertical-align: top !important; }
.align-middle { vertical-align: middle !important; }
.align-bottom { vertical-align: bottom !important; }
.align-text-bottom { vertical-align: text-bottom !important; }
.align-text-top { vertical-align: text-top !important; }
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_background.scss
================================================
// stylelint-disable declaration-no-important
@each $color, $value in $theme-colors {
@include bg-variant(".bg-#{$color}", $value);
}
@if $enable-gradients {
@each $color, $value in $theme-colors {
@include bg-gradient-variant(".bg-gradient-#{$color}", $value);
}
}
.bg-white {
background-color: $white !important;
}
.bg-transparent {
background-color: transparent !important;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_borders.scss
================================================
// stylelint-disable property-blacklist, declaration-no-important
//
// Border
//
.border { border: $border-width solid $border-color !important; }
.border-top { border-top: $border-width solid $border-color !important; }
.border-right { border-right: $border-width solid $border-color !important; }
.border-bottom { border-bottom: $border-width solid $border-color !important; }
.border-left { border-left: $border-width solid $border-color !important; }
.border-0 { border: 0 !important; }
.border-top-0 { border-top: 0 !important; }
.border-right-0 { border-right: 0 !important; }
.border-bottom-0 { border-bottom: 0 !important; }
.border-left-0 { border-left: 0 !important; }
@each $color, $value in $theme-colors {
.border-#{$color} {
border-color: $value !important;
}
}
.border-white {
border-color: $white !important;
}
//
// Border-radius
//
.rounded-sm {
border-radius: $border-radius-sm !important;
}
.rounded {
border-radius: $border-radius !important;
}
.rounded-top {
border-top-left-radius: $border-radius !important;
border-top-right-radius: $border-radius !important;
}
.rounded-right {
border-top-right-radius: $border-radius !important;
border-bottom-right-radius: $border-radius !important;
}
.rounded-bottom {
border-bottom-right-radius: $border-radius !important;
border-bottom-left-radius: $border-radius !important;
}
.rounded-left {
border-top-left-radius: $border-radius !important;
border-bottom-left-radius: $border-radius !important;
}
.rounded-lg {
border-radius: $border-radius-lg !important;
}
.rounded-circle {
border-radius: 50% !important;
}
.rounded-pill {
border-radius: $rounded-pill !important;
}
.rounded-0 {
border-radius: 0 !important;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_clearfix.scss
================================================
.clearfix {
@include clearfix();
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_display.scss
================================================
// stylelint-disable declaration-no-important
//
// Utilities for common `display` values
//
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@each $value in $displays {
.d#{$infix}-#{$value} { display: $value !important; }
}
}
}
//
// Utilities for toggling `display` in print
//
@media print {
@each $value in $displays {
.d-print-#{$value} { display: $value !important; }
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_embed.scss
================================================
// Credit: Nicolas Gallagher and SUIT CSS.
.embed-responsive {
position: relative;
display: block;
width: 100%;
padding: 0;
overflow: hidden;
&::before {
display: block;
content: "";
}
.embed-responsive-item,
iframe,
embed,
object,
video {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
}
@each $embed-responsive-aspect-ratio in $embed-responsive-aspect-ratios {
$embed-responsive-aspect-ratio-x: nth($embed-responsive-aspect-ratio, 1);
$embed-responsive-aspect-ratio-y: nth($embed-responsive-aspect-ratio, 2);
.embed-responsive-#{$embed-responsive-aspect-ratio-x}by#{$embed-responsive-aspect-ratio-y} {
&::before {
padding-top: percentage($embed-responsive-aspect-ratio-y / $embed-responsive-aspect-ratio-x);
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_flex.scss
================================================
// stylelint-disable declaration-no-important
// Flex variation
//
// Custom styles for additional flex alignment options.
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.flex#{$infix}-row { flex-direction: row !important; }
.flex#{$infix}-column { flex-direction: column !important; }
.flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }
.flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }
.flex#{$infix}-wrap { flex-wrap: wrap !important; }
.flex#{$infix}-nowrap { flex-wrap: nowrap !important; }
.flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }
.flex#{$infix}-fill { flex: 1 1 auto !important; }
.flex#{$infix}-grow-0 { flex-grow: 0 !important; }
.flex#{$infix}-grow-1 { flex-grow: 1 !important; }
.flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }
.flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }
.justify-content#{$infix}-start { justify-content: flex-start !important; }
.justify-content#{$infix}-end { justify-content: flex-end !important; }
.justify-content#{$infix}-center { justify-content: center !important; }
.justify-content#{$infix}-between { justify-content: space-between !important; }
.justify-content#{$infix}-around { justify-content: space-around !important; }
.align-items#{$infix}-start { align-items: flex-start !important; }
.align-items#{$infix}-end { align-items: flex-end !important; }
.align-items#{$infix}-center { align-items: center !important; }
.align-items#{$infix}-baseline { align-items: baseline !important; }
.align-items#{$infix}-stretch { align-items: stretch !important; }
.align-content#{$infix}-start { align-content: flex-start !important; }
.align-content#{$infix}-end { align-content: flex-end !important; }
.align-content#{$infix}-center { align-content: center !important; }
.align-content#{$infix}-between { align-content: space-between !important; }
.align-content#{$infix}-around { align-content: space-around !important; }
.align-content#{$infix}-stretch { align-content: stretch !important; }
.align-self#{$infix}-auto { align-self: auto !important; }
.align-self#{$infix}-start { align-self: flex-start !important; }
.align-self#{$infix}-end { align-self: flex-end !important; }
.align-self#{$infix}-center { align-self: center !important; }
.align-self#{$infix}-baseline { align-self: baseline !important; }
.align-self#{$infix}-stretch { align-self: stretch !important; }
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_float.scss
================================================
// stylelint-disable declaration-no-important
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.float#{$infix}-left { float: left !important; }
.float#{$infix}-right { float: right !important; }
.float#{$infix}-none { float: none !important; }
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_overflow.scss
================================================
// stylelint-disable declaration-no-important
@each $value in $overflows {
.overflow-#{$value} { overflow: $value !important; }
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_position.scss
================================================
// stylelint-disable declaration-no-important
// Common values
@each $position in $positions {
.position-#{$position} { position: $position !important; }
}
// Shorthand
.fixed-top {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: $zindex-fixed;
}
.fixed-bottom {
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: $zindex-fixed;
}
.sticky-top {
@supports (position: sticky) {
position: sticky;
top: 0;
z-index: $zindex-sticky;
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_screenreaders.scss
================================================
//
// Screenreaders
//
.sr-only {
@include sr-only();
}
.sr-only-focusable {
@include sr-only-focusable();
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_shadows.scss
================================================
// stylelint-disable declaration-no-important
.shadow-sm { box-shadow: $box-shadow-sm !important; }
.shadow { box-shadow: $box-shadow !important; }
.shadow-lg { box-shadow: $box-shadow-lg !important; }
.shadow-none { box-shadow: none !important; }
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_sizing.scss
================================================
// stylelint-disable declaration-no-important
// Width and height
@each $prop, $abbrev in (width: w, height: h) {
@each $size, $length in $sizes {
.#{$abbrev}-#{$size} { #{$prop}: $length !important; }
}
}
.mw-100 { max-width: 100% !important; }
.mh-100 { max-height: 100% !important; }
// Viewport additional helpers
.min-vw-100 { min-width: 100vw !important; }
.min-vh-100 { min-height: 100vh !important; }
.vw-100 { width: 100vw !important; }
.vh-100 { height: 100vh !important; }
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_spacing.scss
================================================
// stylelint-disable declaration-no-important
// Margin and Padding
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
@each $prop, $abbrev in (margin: m, padding: p) {
@each $size, $length in $spacers {
.#{$abbrev}#{$infix}-#{$size} { #{$prop}: $length !important; }
.#{$abbrev}t#{$infix}-#{$size},
.#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-top: $length !important;
}
.#{$abbrev}r#{$infix}-#{$size},
.#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-right: $length !important;
}
.#{$abbrev}b#{$infix}-#{$size},
.#{$abbrev}y#{$infix}-#{$size} {
#{$prop}-bottom: $length !important;
}
.#{$abbrev}l#{$infix}-#{$size},
.#{$abbrev}x#{$infix}-#{$size} {
#{$prop}-left: $length !important;
}
}
}
// Negative margins (e.g., where `.mb-n1` is negative version of `.mb-1`)
@each $size, $length in $spacers {
@if $size != 0 {
.m#{$infix}-n#{$size} { margin: -$length !important; }
.mt#{$infix}-n#{$size},
.my#{$infix}-n#{$size} {
margin-top: -$length !important;
}
.mr#{$infix}-n#{$size},
.mx#{$infix}-n#{$size} {
margin-right: -$length !important;
}
.mb#{$infix}-n#{$size},
.my#{$infix}-n#{$size} {
margin-bottom: -$length !important;
}
.ml#{$infix}-n#{$size},
.mx#{$infix}-n#{$size} {
margin-left: -$length !important;
}
}
}
// Some special margin utils
.m#{$infix}-auto { margin: auto !important; }
.mt#{$infix}-auto,
.my#{$infix}-auto {
margin-top: auto !important;
}
.mr#{$infix}-auto,
.mx#{$infix}-auto {
margin-right: auto !important;
}
.mb#{$infix}-auto,
.my#{$infix}-auto {
margin-bottom: auto !important;
}
.ml#{$infix}-auto,
.mx#{$infix}-auto {
margin-left: auto !important;
}
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_stretched-link.scss
================================================
//
// Stretched link
//
.stretched-link {
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
// Just in case `pointer-events: none` is set on a parent
pointer-events: auto;
content: "";
// IE10 bugfix, see https://stackoverflow.com/questions/16947967/ie10-hover-pseudo-class-doesnt-work-without-background-color
background-color: rgba(0, 0, 0, 0);
}
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_text.scss
================================================
// stylelint-disable declaration-no-important
//
// Text
//
.text-monospace { font-family: $font-family-monospace !important; }
// Alignment
.text-justify { text-align: justify !important; }
.text-wrap { white-space: normal !important; }
.text-nowrap { white-space: nowrap !important; }
.text-truncate { @include text-truncate; }
// Responsive alignment
@each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.text#{$infix}-left { text-align: left !important; }
.text#{$infix}-right { text-align: right !important; }
.text#{$infix}-center { text-align: center !important; }
}
}
// Transformation
.text-lowercase { text-transform: lowercase !important; }
.text-uppercase { text-transform: uppercase !important; }
.text-capitalize { text-transform: capitalize !important; }
// Weight and italics
.font-weight-light { font-weight: $font-weight-light !important; }
.font-weight-lighter { font-weight: $font-weight-lighter !important; }
.font-weight-normal { font-weight: $font-weight-normal !important; }
.font-weight-bold { font-weight: $font-weight-bold !important; }
.font-weight-bolder { font-weight: $font-weight-bolder !important; }
.font-italic { font-style: italic !important; }
// Contextual colors
.text-white { color: $white !important; }
@each $color, $value in $theme-colors {
@include text-emphasis-variant(".text-#{$color}", $value);
}
.text-body { color: $body-color !important; }
.text-muted { color: $text-muted !important; }
.text-black-50 { color: rgba($black, .5) !important; }
.text-white-50 { color: rgba($white, .5) !important; }
// Misc
.text-hide {
@include text-hide($ignore-warning: true);
}
.text-decoration-none { text-decoration: none !important; }
.text-break {
word-break: break-word !important; // IE & < Edge 18
overflow-wrap: break-word !important;
}
// Reset
.text-reset { color: inherit !important; }
================================================
FILE: docs/current-version/assets/scss/bootstrap/utilities/_visibility.scss
================================================
// stylelint-disable declaration-no-important
//
// Visibility utilities
//
.visible {
visibility: visible !important;
}
.invisible {
visibility: hidden !important;
}
================================================
FILE: docs/current-version/assets/scss/bootstrap/vendor/_rfs.scss
================================================
// stylelint-disable property-blacklist, scss/dollar-variable-default
// SCSS RFS mixin
//
// Automated font-resizing
//
// See https://github.com/twbs/rfs
// Configuration
// Base font size
$rfs-base-font-size: 1.25rem !default;
$rfs-font-size-unit: rem !default;
// Breakpoint at where font-size starts decreasing if screen width is smaller
$rfs-breakpoint: 1200px !default;
$rfs-breakpoint-unit: px !default;
// Resize font-size based on screen height and width
$rfs-two-dimensional: false !default;
// Factor of decrease
$rfs-factor: 10 !default;
@if type-of($rfs-factor) != "number" or $rfs-factor <= 1 {
@error "`#{$rfs-factor}` is not a valid $rfs-factor, it must be greater than 1.";
}
// Generate enable or disable classes. Possibilities: false, "enable" or "disable"
$rfs-class: false !default;
// 1 rem = $rfs-rem-value px
$rfs-rem-value: 16 !default;
// Safari iframe resize bug: https://github.com/twbs/rfs/issues/14
$rfs-safari-iframe-resize-bug-fix: false !default;
// Disable RFS by setting $enable-responsive-font-sizes to false
$enable-responsive-font-sizes: true !default;
// Cache $rfs-base-font-size unit
$rfs-base-font-size-unit: unit($rfs-base-font-size);
// Remove px-unit from $rfs-base-font-size for calculations
@if $rfs-base-font-size-unit == "px" {
$rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1);
}
@else if $rfs-base-font-size-unit == "rem" {
$rfs-base-font-size: $rfs-base-font-size / ($rfs-base-font-size * 0 + 1 / $rfs-rem-value);
}
// Cache $rfs-breakpoint unit to prevent multiple calls
$rfs-breakpoint-unit-cache: unit($rfs-breakpoint);
// Remove unit from $rfs-breakpoint for calculations
@if $rfs-breakpoint-unit-cache == "px" {
$rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1);
}
@else if $rfs-breakpoint-unit-cache == "rem" or $rfs-breakpoint-unit-cache == "em" {
$rfs-breakpoint: $rfs-breakpoint / ($rfs-breakpoint * 0 + 1 / $rfs-rem-value);
}
// Responsive font-size mixin
@mixin rfs($fs, $important: false) {
// Cache $fs unit
$fs-unit: if(type-of($fs) == "number", unit($fs), false);
// Add !important suffix if needed
$rfs-suffix: if($important, " !important", "");
// If $fs isn't a number (like inherit) or $fs has a unit (not px or rem, like 1.5em) or $ is 0, just print the value
@if not $fs-unit or $fs-unit != "" and $fs-unit != "px" and $fs-unit != "rem" or $fs == 0 {
font-size: #{$fs}#{$rfs-suffix};
}
@else {
// Variables for storing static and fluid rescaling
$rfs-static: null;
$rfs-fluid: null;
// Remove px-unit from $fs for calculations
@if $fs-unit == "px" {
$fs: $fs / ($fs * 0 + 1);
}
@else if $fs-unit == "rem" {
$fs: $fs / ($fs * 0 + 1 / $rfs-rem-value);
}
// Set default font-size
@if $rfs-font-size-unit == rem {
$rfs-static: #{$fs / $rfs-rem-value}rem#{$rfs-suffix};
}
@else if $rfs-font-size-unit == px {
$rfs-static: #{$fs}px#{$rfs-suffix};
}
@else {
@error "`#{$rfs-font-size-unit}` is not a valid unit for $rfs-font-size-unit. Use `px` or `rem`.";
}
// Only add media query if font-size is bigger as the minimum font-size
// If $rfs-factor == 1, no rescaling will take place
@if $fs > $rfs-base-font-size and $enable-responsive-font-sizes {
$min-width: null;
$variable-unit: null;
// Calculate minimum font-size for given font-size
$fs-min: $rfs-base-font-size + ($fs - $rfs-base-font-size) / $rfs-factor;
// Calculate difference between given font-size and minimum font-size for given font-size
$fs-diff: $fs - $fs-min;
// Base font-size formatting
// No need to check if the unit is valid, because we did that before
$min-width: if($rfs-font-size-unit == rem, #{$fs-min / $rfs-rem-value}rem, #{$fs-min}px);
// If two-dimensional, use smallest of screen width and height
$variable-unit: if($rfs-two-dimensional, vmin, vw);
// Calculate the variable width between 0 and $rfs-breakpoint
$variable-width: #{$fs-diff * 100 / $rfs-breakpoint}#{$variable-unit};
// Set the calculated font-size.
$rfs-fluid: calc(#{$min-width} + #{$variable-width}) #{$rfs-suffix};
}
// Rendering
@if $rfs-fluid == null {
// Only render static font-size if no fluid font-size is available
font-size: $rfs-static;
}
@else {
$mq-value: null;
// RFS breakpoint formatting
@if $rfs-breakpoint-unit == em or $rfs-breakpoint-unit == rem {
$mq-value: #{$rfs-breakpoint / $rfs-rem-value}#{$rfs-breakpoint-unit};
}
@else if $rfs-breakpoint-unit == px {
$mq-value: #{$rfs-breakpoint}px;
}
@else {
@error "`#{$rfs-breakpoint-unit}` is not a valid unit for $rfs-breakpoint-unit. Use `px`, `em` or `rem`.";
}
@if $rfs-class == "disable" {
// Adding an extra class increases specificity,
// which prevents the media query to override the font size
&,
.disable-responsive-font-size &,
&.disable-responsive-font-size {
font-size: $rfs-static;
}
}
@else {
font-size: $rfs-static;
}
@if $rfs-two-dimensional {
@media (max-width: #{$mq-value}), (max-height: #{$mq-value}) {
@if $rfs-class == "enable" {
.enable-responsive-font-size &,
&.enable-responsive-font-size {
font-size: $rfs-fluid;
}
}
@else {
font-size: $rfs-fluid;
}
@if $rfs-safari-iframe-resize-bug-fix {
// stylelint-disable-next-line length-zero-no-unit
min-width: 0vw;
}
}
}
@else {
@media (max-width: #{$mq-value}) {
@if $rfs-class == "enable" {
.enable-responsive-font-size &,
&.enable-responsive-font-size {
font-size: $rfs-fluid;
}
}
@else {
font-size: $rfs-fluid;
}
@if $rfs-safari-iframe-resize-bug-fix {
// stylelint-disable-next-line length-zero-no-unit
min-width: 0vw;
}
}
}
}
}
}
// The font-size & responsive-font-size mixin uses RFS to rescale font sizes
@mixin font-size($fs, $important: false) {
@include rfs($fs, $important);
}
@mixin responsive-font-size($fs, $important: false) {
@include rfs($fs, $important);
}
================================================
FILE: docs/current-version/assets/scss/components/_anchor.scss
================================================
.content {
.header-anchor {
text-decoration: none;
fill: currentColor;
opacity: 0.6;
}
.header-anchor:hover {
opacity: 1;
}
}
================================================
FILE: docs/current-version/assets/scss/components/_buttons.scss
================================================
.button {
white-space: nowrap;
display: inline-block;
padding: 8px 15px 6px 15px;
background: $primary;
font-weight: normal;
text-transform: uppercase;
color: lighten($primary, 50%);
text-decoration: none;
-webkit-transition: all 0.15s ease;
transition: all 0.15s ease;
border-radius: 3px;
&:hover {
color: #fff;
background-color: lighten($primary, 10%);
text-decoration: none;
}
}
.button-white {
background: none;
color: #fff;
border: 2px solid #fff;
}
================================================
FILE: docs/current-version/assets/scss/components/_content.scss
================================================
.content {
-webkit-font-smoothing: antialiased;
.highlight {
border-radius: 2px;
margin-bottom: 20px;
}
code {
background: #f5f5f5;
padding: 3px 6px;
border-radius: 3px;
font-family: $font-family-mono;
font-size: 0.9rem;
line-height: 1.4;
}
pre {
font-family: $font-family-mono;
font-size: 0.9rem;
line-height: 1.4;
margin: 0;
padding: 10px;
border-radius: 1px;
code {
font-family: $font-family-mono;
font-size: 0.9rem;
line-height: 1.4;
border-radius: none;
padding: 0;
margin: 0;
background: none;
}
}
strong {
font-weight: bold;
}
em {
font-style: italic;
font-weight: normal;
}
ol {
margin-top: 10px;
margin-bottom: 20px;
list-style-type: decimal;
li {
margin-bottom: 5px;
margin-left: 20px;
}
}
ul {
margin-top: 10px;
margin-bottom: 20px;
list-style-type: disc;
li {
margin-bottom: 5px;
margin-left: 20px;
}
}
a {
text-decoration: underline;
}
p {
font-family: $font-family-base;
font-size: 1rem;
line-height: 1.4;
color: lighten($black, 10%);
font-weight: 400;
}
h1 {
font-family: $font-family-base;
font-size: 2.6rem;
line-height: 1.4;
font-weight: 300;
margin-bottom: 20px;
}
h2 {
font-size: 2.2rem;
line-height: 1.4;
font-weight: 300;
letter-spacing: -0.01em;
font-family: $font-family-base;
margin-bottom: 20px;
}
h3 {
font-size: 1.6rem;
line-height: 1.4;
font-weight: 400;
font-family: $font-family-base;
margin-bottom: 20px;
}
h4 {
font-size: 1.5rem;
line-height: 1.4;
font-weight: 500;
font-family: $font-family-base;
margin-bottom: 20px;
}
h5 {
font-size: 1.4rem;
line-height: 1.4;
font-weight: 600;
font-family: $font-family-base;
margin-bottom: 20px;
}
h6 {
font-size: 1.2rem;
line-height: 1.4;
font-weight: 700;
font-family: $font-family-base;
margin-bottom: 20px;
}
blockquote {
background: #f9f9f9;
border-left: 10px solid #ccc;
margin: 1.5em 10px;
padding: 0.5em 10px;
quotes: '\201C''\201D''\2018''\2019';
}
blockquote:before {
color: #ccc;
content: open-quote;
font-size: 4em;
line-height: 0.1em;
margin-right: 0.25em;
vertical-align: -0.4em;
}
blockquote p {
display: inline;
}
table {
@extend .table;
}
img {
max-width: 100%;
height: auto;
}
}
================================================
FILE: docs/current-version/assets/scss/components/_docs-menu.scss
================================================
.docs-menu {
h4 {
font-size: 1rem;
font-weight: bold;
}
ul {
list-style: none;
padding: 0;
margin: 0;
li {
font-size: 0.9rem;
line-height: 1.4;
font-weight: 400;
margin: 0;
padding: 4px 0 4px 0;
&.active {
a {
color: lighten($primary, 10%);
font-weight: 400;
}
}
a {
color: $black;
&:hover {
color: $primary;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_footer.scss
================================================
.footer {
background: #eaeaea;
padding-top: 20px;
padding-bottom: 20px;
.footer-inner {
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: flex-start;
@include media-breakpoint-up(sm) {
justify-content: space-between;
flex-direction: row;
align-items: center;
}
}
.footer-title {
color: #ffffff;
font-size: 1.3rem;
font-family: $font-family-serif;
margin-bottom: 10px;
flex: 0;
@include media-breakpoint-up(sm) {
margin: 0;
flex: 0 0 120px;
}
}
ul.footer-menu {
list-style: none;
margin: 0;
padding: 0;
flex: 1;
li {
display: block;
margin-right: 10px;
color: #333;
font-size: 0.9rem;
line-height: 1.8;
&:last-of-type {
margin-right: 0;
}
a {
color: #333;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
&.copyright {
font-weight: bold;
color: #333;
display: none;
@include media-breakpoint-up(md) {
display: inline-block;
}
}
}
@include media-breakpoint-up(sm) {
height: inherit;
display: flex;
list-style: none;
margin: 0;
padding: 0;
align-items: center;
justify-content: flex-end;
li {
list-style: none;
a {
display: inline-block;
height: 40px;
padding: 10px 8px 10px 8px;
font-weight: 300;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_hamburger.scss
================================================
.hamburger {
padding: 10px 0 10px 10px;
outline: none;
z-index: 30;
cursor: pointer;
@include media-breakpoint-up(md) {
display: none;
}
&:focus {
outline: none;
}
.hamburger-inner,
.hamburger-inner::before,
.hamburger-inner::after {
background: $primary;
}
.hamburger-inner::after {
width: 18px;
right: 0;
}
&.is-active {
.hamburger-inner::after {
width: inherit;
right: unset;
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_header.scss
================================================
.header {
color: $primary;
background-color: #f8f8f8;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0 10px 0;
// box-shadow: 0 1px 15px rgba(50, 50, 93, 0.2);
.container {
display: flex;
justify-content: space-between;
align-items: center;
}
&.header-absolute {
position: absolute;
z-index: 10;
width: 100%;
}
}
.lock-scroll {
.header {
&.header-absolute {
position: static;
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_logo.scss
================================================
.logo {
display: none;
@include media-breakpoint-up(sm) {
display: block;
width: 70px;
}
img {
width: 100%;
height: auto;
}
a {
display: block;
width: 100%;
height: 100%;
}
}
.logo-mobile {
display: block;
width: 54px;
@include media-breakpoint-up(sm) {
display: none;
}
img {
width: 100%;
height: auto;
}
a {
display: block;
width: 100%;
height: 100%;
}
}
================================================
FILE: docs/current-version/assets/scss/components/_main-menu-mobile.scss
================================================
.main-menu-mobile {
position: fixed;
background: $primary;
top: 0;
left: 0;
width: 100%;
height: 100vh;
opacity: 0;
visibility: hidden;
transition: opacity 0.35s, visibility 0.35s, height 0.35s;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
&.open {
opacity: 0.9;
visibility: visible;
height: 100%;
z-index: 20;
li {
animation: fadeInRight 0.5s ease forwards;
animation-delay: 0.35s;
&:nth-of-type(2) {
animation-delay: 0.4s;
}
&:nth-of-type(3) {
animation-delay: 0.45s;
}
&:nth-of-type(4) {
animation-delay: 0.5s;
}
&:nth-of-type(5) {
animation-delay: 0.55s;
}
&:nth-of-type(6) {
animation-delay: 0.6s;
}
}
}
ul {
font-size: 2rem;
font-family: $font-family-base;
text-align: center;
list-style: none;
padding: 0;
margin: 0;
flex: 0;
li {
display: block;
position: relative;
opacity: 0;
a {
display: block;
position: relative;
color: #ffffff;
text-decoration: none;
overflow: hidden;
font-weight: lighter;
&:hover::after,
&:focus::after,
&:active::after {
width: 100%;
}
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
width: 0%;
transform: translateX(-50%);
height: 3px;
background: #ffffff;
transition: 0.35s;
}
}
}
}
}
@keyframes fadeInRight {
0% {
opacity: 0;
left: 20%;
}
100% {
opacity: 1;
left: 0;
}
}
.lock-scroll {
overflow: hidden;
}
================================================
FILE: docs/current-version/assets/scss/components/_main-menu.scss
================================================
.main-menu {
display: none;
@include media-breakpoint-up(md) {
display: block;
}
> ul {
display: flex;
align-items: center;
justify-content: flex-start;
font-family: $font-family-base;
> li {
list-style: none;
font-size: 14px;
> a {
padding: 10px 14px 10px 14px;
display: inline-block;
font-weight: normal;
text-decoration: none;
color: $primary;
&:hover {
text-decoration: underline;
color: $primary;
}
}
&.active {
> a {
font-weight: bold;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_overview.scss
================================================
.overview {
background: lightgoldenrodyellow;
border-radius: 3px;
padding: 4px 10px 4px 10px;
float: right;
}
================================================
FILE: docs/current-version/assets/scss/components/_page.scss
================================================
.page {
display: flex;
min-height: 100vh;
flex-direction: column;
.wrapper {
flex: 1;
}
}
================================================
FILE: docs/current-version/assets/scss/components/_reset.scss
================================================
ul,
ol {
margin: 0;
padding: 0;
list-style: none;
}
================================================
FILE: docs/current-version/assets/scss/components/_strip.scss
================================================
.strip {
background-repeat: no-repeat;
}
.strip-white {
background-color: white;
}
.strip-grey {
background-color: #f4f5fb;
}
.strip-diagonal {
transform: skewY(5deg);
padding-bottom: 50px;
margin-bottom: 65px;
> div {
transform: skewY(-5deg);
}
}
.strip-primary-gradient {
background-image: linear-gradient(to right, $primary, $secondary);
}
.strip-primary-gradient-top-bottom {
background-image: linear-gradient(to bottom, $primary, $secondary);
}
.strip-primary {
background-color: $primary;
}
.strip-secondary {
background-color: $secondary;
}
.strip-diagonal-right {
margin-top: -100px;
transform: skewY(-5deg);
padding-bottom: 100px;
> div {
transform: skewY(5deg);
}
}
.strip-diagonal-left {
margin-top: -100px;
transform: skewY(5deg);
padding-bottom: 100px;
> div {
transform: skewY(-5deg);
}
}
.strip-bg-contain {
background-size: contain;
}
.strip-bg-cover {
background-size: cover;
}
================================================
FILE: docs/current-version/assets/scss/components/_sub-footer.scss
================================================
.sub-footer {
background: #f4f5fb;
padding-top: 20px;
padding-bottom: 20px;
@include media-breakpoint-up(md) {
padding-top: 10px;
padding-bottom: 10px;
}
.sub-footer-inner {
display: flex;
flex-direction: column;
justify-content: flex-end;
@include media-breakpoint-up(md) {
flex-direction: row;
}
ul {
list-style: none;
margin: 0;
padding: 0;
li {
list-style: none;
display: block;
color: #333;
font-size: 0.9rem;
line-height: 1.8;
font-weight: bold;
strong {
font-weight: bold;
color: #ffffff;
}
a {
color: #333;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
span {
display: inline-block;
height: 40px;
padding: 10px 0 10px 8px;
font-weight: bold;
color: #ffffff;
}
&.zerostatic {
a {
color: #333;
}
}
}
@include media-breakpoint-up(sm) {
li {
display: inline-block;
margin-left: 10px;
&:first-of-type {
margin-left: 0;
}
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/components/_title.scss
================================================
.title {
font-size: 2.7rem;
line-height: 1.1;
font-family: $font-family-base;
letter-spacing: -0.2px;
font-weight: 100;
margin-bottom: 20px;
@include media-breakpoint-up(md) {
font-size: 3rem;
margin-bottom: 30px;
}
}
.title-summary {
font-size: 1.6rem;
line-height: 1.4;
font-family: $font-family-base;
letter-spacing: -0.2px;
font-weight: 200;
margin-bottom: 10px;
@include media-breakpoint-up(md) {
font-size: 1.6rem;
}
}
================================================
FILE: docs/current-version/assets/scss/components/_type.scss
================================================
p {
font-family: $font-family-base;
font-size: 1rem;
line-height: 1.4;
color: lighten($black, 10%);
font-weight: 400;
}
================================================
FILE: docs/current-version/assets/scss/components/_whitebox.scss
================================================
@mixin whitebox($padding: 10px) {
border: 1px solid #dcdcdc;
border-radius: 3px;
box-shadow: 0 1px 18px rgba(0, 0, 0, 0.2);
background: #ffffff;
padding: $padding;
}
.whitebox {
@include whitebox();
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/_base.scss
================================================
// Hamburger
// ==================================================
.hamburger {
padding: $hamburger-padding-y $hamburger-padding-x;
display: inline-block;
cursor: pointer;
transition-property: opacity, filter;
transition-duration: 0.15s;
transition-timing-function: linear;
// Normalize (
)
font: inherit;
color: inherit;
text-transform: none;
background-color: transparent;
border: 0;
margin: 0;
overflow: visible;
&:hover {
@if $hamburger-hover-use-filter == true {
filter: $hamburger-hover-filter;
}
@else {
opacity: $hamburger-hover-opacity;
}
}
&.is-active {
&:hover {
@if $hamburger-hover-use-filter == true {
filter: $hamburger-active-hover-filter;
}
@else {
opacity: $hamburger-active-hover-opacity;
}
}
.hamburger-inner,
.hamburger-inner::before,
.hamburger-inner::after {
background-color: $hamburger-active-layer-color;
}
}
}
.hamburger-box {
width: $hamburger-layer-width;
height: $hamburger-layer-height * 3 + $hamburger-layer-spacing * 2;
display: inline-block;
position: relative;
}
.hamburger-inner {
display: block;
top: 50%;
margin-top: $hamburger-layer-height / -2;
&,
&::before,
&::after {
width: $hamburger-layer-width;
height: $hamburger-layer-height;
background-color: $hamburger-layer-color;
border-radius: $hamburger-layer-border-radius;
position: absolute;
transition-property: transform;
transition-duration: 0.15s;
transition-timing-function: ease;
}
&::before,
&::after {
content: "";
display: block;
}
&::before {
top: ($hamburger-layer-spacing + $hamburger-layer-height) * -1;
}
&::after {
bottom: ($hamburger-layer-spacing + $hamburger-layer-height) * -1;
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/hamburgers.scss
================================================
@charset "UTF-8";
/*!
* Hamburgers
* @description Tasty CSS-animated hamburgers
* @author Jonathan Suh @jonsuh
* @site https://jonsuh.com/hamburgers
* @link https://github.com/jonsuh/hamburgers
*/
// Settings
// ==================================================
$hamburger-padding-x : 15px !default;
$hamburger-padding-y : 15px !default;
$hamburger-layer-width : 32px !default;
$hamburger-layer-height : 3px !default;
$hamburger-layer-spacing : 5px !default;
$hamburger-layer-color : $primary !default;
$hamburger-layer-border-radius : 3px !default;
$hamburger-hover-opacity : 0.7 !default;
$hamburger-active-layer-color : #FFF !default;
$hamburger-active-hover-opacity: $hamburger-hover-opacity !default;
// To use CSS filters as the hover effect instead of opacity,
// set $hamburger-hover-use-filter as true and
// change the value of $hamburger-hover-filter accordingly.
$hamburger-hover-use-filter : false !default;
$hamburger-hover-filter : opacity(50%) !default;
$hamburger-active-hover-filter: $hamburger-hover-filter !default;
// Types (Remove or comment out what you don’t need)
// ==================================================
$hamburger-types: (
3dx,
3dx-r,
3dy,
3dy-r,
3dxy,
3dxy-r,
arrow,
arrow-r,
arrowalt,
arrowalt-r,
arrowturn,
arrowturn-r,
boring,
collapse,
collapse-r,
elastic,
elastic-r,
emphatic,
emphatic-r,
minus,
slider,
slider-r,
spin,
spin-r,
spring,
spring-r,
stand,
stand-r,
squeeze,
vortex,
vortex-r
) !default;
// Base Hamburger (We need this)
// ==================================================
@import "base";
// Hamburger types
// ==================================================
// @import "types/3dx";
// @import "types/3dx-r";
// @import "types/3dy";
// @import "types/3dy-r";
// @import "types/3dxy";
// @import "types/3dxy-r";
// @import "types/arrow";
// @import "types/arrow-r";
// @import "types/arrowalt";
// @import "types/arrowalt-r";
// @import "types/arrowturn";
// @import "types/arrowturn-r";
// @import "types/boring";
// @import "types/collapse";
// @import "types/collapse-r";
// @import "types/elastic";
// @import "types/elastic-r";
// @import "types/emphatic";
// @import "types/emphatic-r";
// @import "types/minus";
@import "types/slider";
// @import "types/slider-r";
// @import "types/spin";
// @import "types/spin-r";
// @import "types/spring";
// @import "types/spring-r";
// @import "types/stand";
// @import "types/stand-r";
// @import "types/squeeze";
// @import "types/vortex";
// @import "types/vortex-r";
// ==================================================
// Cooking up additional types:
//
// The Sass for each hamburger type should be nested
// inside an @if directive to check whether or not
// it exists in $hamburger-types so only the CSS for
// included types are generated.
//
// e.g. hamburgers/types/_new-type.scss
//
// @if index($hamburger-types, new-type) {
// .hamburger--new-type {
// ...
// }
// }
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dx-r.scss
================================================
@if index($hamburger-types, 3dx-r) {
/*
* 3DX Reverse
*/
.hamburger--3dx-r {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateY(-180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dx.scss
================================================
@if index($hamburger-types, 3dx) {
/*
* 3DX
*/
.hamburger--3dx {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateY(180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dxy-r.scss
================================================
@if index($hamburger-types, 3dxy-r) {
/*
* 3DXY Reverse
*/
.hamburger--3dxy-r {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateX(180deg) rotateY(180deg) rotateZ(-180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dxy.scss
================================================
@if index($hamburger-types, 3dxy) {
/*
* 3DXY
*/
.hamburger--3dxy {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateX(180deg) rotateY(180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dy-r.scss
================================================
@if index($hamburger-types, 3dy-r) {
/*
* 3DY Reverse
*/
.hamburger--3dy-r {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateX(180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_3dy.scss
================================================
@if index($hamburger-types, 3dy) {
/*
* 3DY
*/
.hamburger--3dy {
.hamburger-box {
perspective: $hamburger-layer-width * 2;
}
.hamburger-inner {
transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1),
background-color 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
&::before,
&::after {
transition: transform 0s 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
}
}
&.is-active {
.hamburger-inner {
background-color: transparent !important;
transform: rotateX(-180deg);
&::before {
transform: translate3d(0, $hamburger-layer-height + $hamburger-layer-spacing, 0) rotate(45deg);
}
&::after {
transform: translate3d(0, ($hamburger-layer-height + $hamburger-layer-spacing) * -1, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrow-r.scss
================================================
@if index($hamburger-types, arrow-r) {
/*
* Arrow Right
*/
.hamburger--arrow-r.is-active {
.hamburger-inner {
&::before {
transform: translate3d($hamburger-layer-width * 0.2, 0, 0) rotate(45deg) scale(0.7, 1);
}
&::after {
transform: translate3d($hamburger-layer-width * 0.2, 0, 0) rotate(-45deg) scale(0.7, 1);
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrow.scss
================================================
@if index($hamburger-types, arrow) {
/*
* Arrow
*/
.hamburger--arrow.is-active {
.hamburger-inner {
&::before {
transform: translate3d($hamburger-layer-width * -0.2, 0, 0) rotate(-45deg) scale(0.7, 1);
}
&::after {
transform: translate3d($hamburger-layer-width * -0.2, 0, 0) rotate(45deg) scale(0.7, 1);
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrowalt-r.scss
================================================
@if index($hamburger-types, arrowalt-r) {
/*
* Arrow Alt Right
*/
.hamburger--arrowalt-r {
.hamburger-inner {
&::before {
transition: top 0.1s 0.1s ease,
transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
}
&::after {
transition: bottom 0.1s 0.1s ease,
transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
}
}
&.is-active {
.hamburger-inner {
&::before {
top: 0;
transform: translate3d($hamburger-layer-width * 0.2, $hamburger-layer-width * -0.25, 0) rotate(45deg) scale(0.7, 1);
transition: top 0.1s ease,
transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
}
&::after {
bottom: 0;
transform: translate3d($hamburger-layer-width * 0.2, $hamburger-layer-width * 0.25, 0) rotate(-45deg) scale(0.7, 1);
transition: bottom 0.1s ease,
transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrowalt.scss
================================================
@if index($hamburger-types, arrowalt) {
/*
* Arrow Alt
*/
.hamburger--arrowalt {
.hamburger-inner {
&::before {
transition: top 0.1s 0.1s ease,
transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
}
&::after {
transition: bottom 0.1s 0.1s ease,
transform 0.1s cubic-bezier(0.165, 0.84, 0.44, 1);
}
}
&.is-active {
.hamburger-inner {
&::before {
top: 0;
transform: translate3d($hamburger-layer-width * -0.2, $hamburger-layer-width * -0.25, 0) rotate(-45deg) scale(0.7, 1);
transition: top 0.1s ease,
transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
}
&::after {
bottom: 0;
transform: translate3d($hamburger-layer-width * -0.2, $hamburger-layer-width * 0.25, 0) rotate(45deg) scale(0.7, 1);
transition: bottom 0.1s ease,
transform 0.1s 0.1s cubic-bezier(0.895, 0.03, 0.685, 0.22);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrowturn-r.scss
================================================
@if index($hamburger-types, arrowturn-r) {
/*
* Arrow Turn Right
*/
.hamburger--arrowturn-r.is-active {
.hamburger-inner {
transform: rotate(-180deg);
&::before {
transform: translate3d(-8px, 0, 0) rotate(-45deg) scale(0.7, 1);
}
&::after {
transform: translate3d(-8px, 0, 0) rotate(45deg) scale(0.7, 1);
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_arrowturn.scss
================================================
@if index($hamburger-types, arrowturn) {
/*
* Arrow Turn
*/
.hamburger--arrowturn.is-active {
.hamburger-inner {
transform: rotate(-180deg);
&::before {
transform: translate3d(8px, 0, 0) rotate(45deg) scale(0.7, 1);
}
&::after {
transform: translate3d(8px, 0, 0) rotate(-45deg) scale(0.7, 1);
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_boring.scss
================================================
@if index($hamburger-types, boring) {
/*
* Boring
*/
.hamburger--boring {
.hamburger-inner {
&,
&::before,
&::after {
transition-property: none;
}
}
&.is-active {
.hamburger-inner {
transform: rotate(45deg);
&::before {
top: 0;
opacity: 0;
}
&::after {
bottom: 0;
transform: rotate(-90deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_collapse-r.scss
================================================
@if index($hamburger-types, collapse-r) {
/*
* Collapse Reverse
*/
.hamburger--collapse-r {
.hamburger-inner {
top: auto;
bottom: 0;
transition-duration: 0.13s;
transition-delay: 0.13s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::after {
top: ($hamburger-layer-spacing * 2 + $hamburger-layer-height * 2) * -1;
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
opacity 0.1s linear;
}
&::before {
transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: translate3d(0, ($hamburger-layer-spacing + $hamburger-layer-height) * -1, 0) rotate(45deg);
transition-delay: 0.22s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::after {
top: 0;
opacity: 0;
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
opacity 0.1s 0.22s linear;
}
&::before {
top: 0;
transform: rotate(90deg);
transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_collapse.scss
================================================
@if index($hamburger-types, collapse) {
/*
* Collapse
*/
.hamburger--collapse {
.hamburger-inner {
top: auto;
bottom: 0;
transition-duration: 0.13s;
transition-delay: 0.13s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::after {
top: ($hamburger-layer-spacing * 2 + $hamburger-layer-height * 2) * -1;
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
opacity 0.1s linear;
}
&::before {
transition: top 0.12s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: translate3d(0, ($hamburger-layer-spacing + $hamburger-layer-height) * -1, 0) rotate(-45deg);
transition-delay: 0.22s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::after {
top: 0;
opacity: 0;
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
opacity 0.1s 0.22s linear;
}
&::before {
top: 0;
transform: rotate(-90deg);
transition: top 0.1s 0.16s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
transform 0.13s 0.25s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_elastic-r.scss
================================================
@if index($hamburger-types, elastic-r) {
/*
* Elastic Reverse
*/
.hamburger--elastic-r {
.hamburger-inner {
top: $hamburger-layer-height / 2;
transition-duration: 0.275s;
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
&::before {
top: $hamburger-layer-height + $hamburger-layer-spacing;
transition: opacity 0.125s 0.275s ease;
}
&::after {
top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2);
transition: transform 0.275s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
}
&.is-active {
.hamburger-inner {
$y-offset: $hamburger-layer-spacing + $hamburger-layer-height;
transform: translate3d(0, $y-offset, 0) rotate(-135deg);
transition-delay: 0.075s;
&::before {
transition-delay: 0s;
opacity: 0;
}
&::after {
transform: translate3d(0, $y-offset * -2, 0) rotate(270deg);
transition-delay: 0.075s;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_elastic.scss
================================================
@if index($hamburger-types, elastic) {
/*
* Elastic
*/
.hamburger--elastic {
.hamburger-inner {
top: $hamburger-layer-height / 2;
transition-duration: 0.275s;
transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
&::before {
top: $hamburger-layer-height + $hamburger-layer-spacing;
transition: opacity 0.125s 0.275s ease;
}
&::after {
top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2);
transition: transform 0.275s cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
}
&.is-active {
.hamburger-inner {
$y-offset: $hamburger-layer-spacing + $hamburger-layer-height;
transform: translate3d(0, $y-offset, 0) rotate(135deg);
transition-delay: 0.075s;
&::before {
transition-delay: 0s;
opacity: 0;
}
&::after {
transform: translate3d(0, $y-offset * -2, 0) rotate(-270deg);
transition-delay: 0.075s;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_emphatic-r.scss
================================================
@if index($hamburger-types, emphatic-r) {
/*
* Emphatic Reverse
*/
.hamburger--emphatic-r {
overflow: hidden;
.hamburger-inner {
transition: background-color 0.125s 0.175s ease-in;
&::before {
left: 0;
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335),
top 0.05s 0.125s linear,
left 0.125s 0.175s ease-in;
}
&::after {
top: ($hamburger-layer-height) + ($hamburger-layer-spacing);
right: 0;
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335),
top 0.05s 0.125s linear,
right 0.125s 0.175s ease-in;
}
}
&.is-active {
.hamburger-inner {
transition-delay: 0s;
transition-timing-function: ease-out;
background-color: transparent !important;
&::before {
left: $hamburger-layer-width * -2;
top: $hamburger-layer-width * 2;
transform: translate3d($hamburger-layer-width * 2, $hamburger-layer-width * -2, 0) rotate(-45deg);
transition: left 0.125s ease-out,
top 0.05s 0.125s linear,
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
}
&::after {
right: $hamburger-layer-width * -2;
top: $hamburger-layer-width * 2;
transform: translate3d($hamburger-layer-width * -2, $hamburger-layer-width * -2, 0) rotate(45deg);
transition: right 0.125s ease-out,
top 0.05s 0.125s linear,
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_emphatic.scss
================================================
@if index($hamburger-types, emphatic) {
/*
* Emphatic
*/
.hamburger--emphatic {
overflow: hidden;
.hamburger-inner {
transition: background-color 0.125s 0.175s ease-in;
&::before {
left: 0;
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335),
top 0.05s 0.125s linear,
left 0.125s 0.175s ease-in;
}
&::after {
top: ($hamburger-layer-height) + ($hamburger-layer-spacing);
right: 0;
transition: transform 0.125s cubic-bezier(0.6, 0.04, 0.98, 0.335),
top 0.05s 0.125s linear,
right 0.125s 0.175s ease-in;
}
}
&.is-active {
.hamburger-inner {
transition-delay: 0s;
transition-timing-function: ease-out;
background-color: transparent !important;
&::before {
left: $hamburger-layer-width * -2;
top: $hamburger-layer-width * -2;
transform: translate3d($hamburger-layer-width * 2, $hamburger-layer-width * 2, 0) rotate(45deg);
transition: left 0.125s ease-out,
top 0.05s 0.125s linear,
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
}
&::after {
right: $hamburger-layer-width * -2;
top: $hamburger-layer-width * -2;
transform: translate3d($hamburger-layer-width * -2, $hamburger-layer-width * 2, 0) rotate(-45deg);
transition: right 0.125s ease-out,
top 0.05s 0.125s linear,
transform 0.125s 0.175s cubic-bezier(0.075, 0.82, 0.165, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_minus.scss
================================================
@if index($hamburger-types, minus) {
/*
* Minus
*/
.hamburger--minus {
.hamburger-inner {
&::before,
&::after {
transition: bottom 0.08s 0s ease-out,
top 0.08s 0s ease-out,
opacity 0s linear;
}
}
&.is-active {
.hamburger-inner {
&::before,
&::after {
opacity: 0;
transition: bottom 0.08s ease-out,
top 0.08s ease-out,
opacity 0s 0.08s linear;
}
&::before {
top: 0;
}
&::after {
bottom: 0;
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_slider-r.scss
================================================
@if index($hamburger-types, slider-r) {
/*
* Slider Reverse
*/
.hamburger--slider-r {
.hamburger-inner {
top: $hamburger-layer-height / 2;
&::before {
top: $hamburger-layer-height + $hamburger-layer-spacing;
transition-property: transform, opacity;
transition-timing-function: ease;
transition-duration: 0.15s;
}
&::after {
top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2);
}
}
&.is-active {
.hamburger-inner {
$y-offset: $hamburger-layer-spacing + $hamburger-layer-height;
transform: translate3d(0, $y-offset, 0) rotate(-45deg);
&::before {
transform: rotate(45deg) translate3d($hamburger-layer-width / 7, $hamburger-layer-spacing * -1, 0);
opacity: 0;
}
&::after {
transform: translate3d(0, $y-offset * -2, 0) rotate(90deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_slider.scss
================================================
@if index($hamburger-types, slider) {
/*
* Slider
*/
.hamburger--slider {
.hamburger-inner {
top: $hamburger-layer-height / 2;
&::before {
top: $hamburger-layer-height + $hamburger-layer-spacing;
transition-property: transform, opacity;
transition-timing-function: ease;
transition-duration: 0.15s;
}
&::after {
top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2);
}
}
&.is-active {
.hamburger-inner {
$y-offset: $hamburger-layer-spacing + $hamburger-layer-height;
transform: translate3d(0, $y-offset, 0) rotate(45deg);
&::before {
transform: rotate(-45deg) translate3d($hamburger-layer-width / -7, $hamburger-layer-spacing * -1, 0);
opacity: 0;
}
&::after {
transform: translate3d(0, $y-offset * -2, 0) rotate(-90deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_spin-r.scss
================================================
@if index($hamburger-types, spin-r) {
/*
* Spin Reverse
*/
.hamburger--spin-r {
.hamburger-inner {
transition-duration: 0.22s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::before {
transition: top 0.1s 0.25s ease-in,
opacity 0.1s ease-in;
}
&::after {
transition: bottom 0.1s 0.25s ease-in,
transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: rotate(-225deg);
transition-delay: 0.12s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::before {
top: 0;
opacity: 0;
transition: top 0.1s ease-out,
opacity 0.1s 0.12s ease-out;
}
&::after {
bottom: 0;
transform: rotate(90deg);
transition: bottom 0.1s ease-out,
transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_spin.scss
================================================
@if index($hamburger-types, spin) {
/*
* Spin
*/
.hamburger--spin {
.hamburger-inner {
transition-duration: 0.22s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::before {
transition: top 0.1s 0.25s ease-in,
opacity 0.1s ease-in;
}
&::after {
transition: bottom 0.1s 0.25s ease-in,
transform 0.22s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: rotate(225deg);
transition-delay: 0.12s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::before {
top: 0;
opacity: 0;
transition: top 0.1s ease-out,
opacity 0.1s 0.12s ease-out;
}
&::after {
bottom: 0;
transform: rotate(-90deg);
transition: bottom 0.1s ease-out,
transform 0.22s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_spring-r.scss
================================================
@if index($hamburger-types, spring-r) {
/*
* Spring Reverse
*/
.hamburger--spring-r {
.hamburger-inner {
top: auto;
bottom: 0;
transition-duration: 0.13s;
transition-delay: 0s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::after {
top: ($hamburger-layer-spacing * 2 + $hamburger-layer-height * 2) * -1;
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
opacity 0s linear;
}
&::before {
transition: top 0.1s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: translate3d(0, ($hamburger-layer-spacing + $hamburger-layer-height) * -1, 0) rotate(-45deg);
transition-delay: 0.22s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::after {
top: 0;
opacity: 0;
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
opacity 0s 0.22s linear;
}
&::before {
top: 0;
transform: rotate(90deg);
transition: top 0.1s 0.15s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_spring.scss
================================================
@if index($hamburger-types, spring) {
/*
* Spring
*/
.hamburger--spring {
.hamburger-inner {
top: $hamburger-layer-height / 2;
transition: background-color 0s 0.13s linear;
&::before {
top: $hamburger-layer-height + $hamburger-layer-spacing;
transition: top 0.1s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
&::after {
top: ($hamburger-layer-height * 2) + ($hamburger-layer-spacing * 2);
transition: top 0.2s 0.2s cubic-bezier(0.33333, 0.66667, 0.66667, 1),
transform 0.13s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transition-delay: 0.22s;
background-color: transparent !important;
&::before {
top: 0;
transition: top 0.1s 0.15s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translate3d(0, $hamburger-layer-spacing + $hamburger-layer-height, 0) rotate(45deg);
}
&::after {
top: 0;
transition: top 0.2s cubic-bezier(0.33333, 0, 0.66667, 0.33333),
transform 0.13s 0.22s cubic-bezier(0.215, 0.61, 0.355, 1);
transform: translate3d(0, $hamburger-layer-spacing + $hamburger-layer-height, 0) rotate(-45deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_squeeze.scss
================================================
@if index($hamburger-types, squeeze) {
/*
* Squeeze
*/
.hamburger--squeeze {
.hamburger-inner {
transition-duration: 0.075s;
transition-timing-function: cubic-bezier(0.55, 0.055, 0.675, 0.19);
&::before {
transition: top 0.075s 0.12s ease,
opacity 0.075s ease;
}
&::after {
transition: bottom 0.075s 0.12s ease,
transform 0.075s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: rotate(45deg);
transition-delay: 0.12s;
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
&::before {
top: 0;
opacity: 0;
transition: top 0.075s ease,
opacity 0.075s 0.12s ease;
}
&::after {
bottom: 0;
transform: rotate(-90deg);
transition: bottom 0.075s ease,
transform 0.075s 0.12s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_stand-r.scss
================================================
@if index($hamburger-types, stand-r) {
/*
* Stand Reverse
*/
.hamburger--stand-r {
.hamburger-inner {
transition: transform 0.075s 0.15s cubic-bezier(0.55, 0.055, 0.675, 0.19),
background-color 0s 0.075s linear;
&::before {
transition: top 0.075s 0.075s ease-in,
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
&::after {
transition: bottom 0.075s 0.075s ease-in,
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: rotate(-90deg);
background-color: transparent !important;
transition: transform 0.075s 0s cubic-bezier(0.215, 0.61, 0.355, 1),
background-color 0s 0.15s linear;
&::before {
top: 0;
transform: rotate(-45deg);
transition: top 0.075s 0.1s ease-out,
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
}
&::after {
bottom: 0;
transform: rotate(45deg);
transition: bottom 0.075s 0.1s ease-out,
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_stand.scss
================================================
@if index($hamburger-types, stand) {
/*
* Stand
*/
.hamburger--stand {
.hamburger-inner {
transition: transform 0.075s 0.15s cubic-bezier(0.55, 0.055, 0.675, 0.19),
background-color 0s 0.075s linear;
&::before {
transition: top 0.075s 0.075s ease-in,
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
&::after {
transition: bottom 0.075s 0.075s ease-in,
transform 0.075s 0s cubic-bezier(0.55, 0.055, 0.675, 0.19);
}
}
&.is-active {
.hamburger-inner {
transform: rotate(90deg);
background-color: transparent !important;
transition: transform 0.075s 0s cubic-bezier(0.215, 0.61, 0.355, 1),
background-color 0s 0.15s linear;
&::before {
top: 0;
transform: rotate(-45deg);
transition: top 0.075s 0.1s ease-out,
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
}
&::after {
bottom: 0;
transform: rotate(45deg);
transition: bottom 0.075s 0.1s ease-out,
transform 0.075s 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_vortex-r.scss
================================================
@if index($hamburger-types, vortex-r) {
/*
* Vortex Reverse
*/
.hamburger--vortex-r {
.hamburger-inner {
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
&::before,
&::after {
transition-duration: 0s;
transition-delay: 0.1s;
transition-timing-function: linear;
}
&::before {
transition-property: top, opacity;
}
&::after {
transition-property: bottom, transform;
}
}
&.is-active {
.hamburger-inner {
transform: rotate(-765deg);
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
&::before,
&::after {
transition-delay: 0s;
}
&::before {
top: 0;
opacity: 0;
}
&::after {
bottom: 0;
transform: rotate(-90deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/hamburgers/types/_vortex.scss
================================================
@if index($hamburger-types, vortex) {
/*
* Vortex
*/
.hamburger--vortex {
.hamburger-inner {
transition-duration: 0.2s;
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
&::before,
&::after {
transition-duration: 0s;
transition-delay: 0.1s;
transition-timing-function: linear;
}
&::before {
transition-property: top, opacity;
}
&::after {
transition-property: bottom, transform;
}
}
&.is-active {
.hamburger-inner {
transform: rotate(765deg);
transition-timing-function: cubic-bezier(0.19, 1, 0.22, 1);
&::before,
&::after {
transition-delay: 0s;
}
&::before {
top: 0;
opacity: 0;
}
&::after {
bottom: 0;
transform: rotate(90deg);
}
}
}
}
}
================================================
FILE: docs/current-version/assets/scss/libraries/pygments/github.scss
================================================
.highlight { background: #f5f5f5; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #000000; font-weight: bold } /* Keyword */
.highlight .o { color: #000000; font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #000000; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d01040 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nl { color: #990000; font-weight: bold } /* Name.Label */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d01040 } /* Literal.String.Backtick */
.highlight .sc { color: #d01040 } /* Literal.String.Char */
.highlight .sd { color: #d01040 } /* Literal.String.Doc */
.highlight .s2 { color: #d01040 } /* Literal.String.Double */
.highlight .se { color: #d01040 } /* Literal.String.Escape */
.highlight .sh { color: #d01040 } /* Literal.String.Heredoc */
.highlight .si { color: #d01040 } /* Literal.String.Interpol */
.highlight .sx { color: #d01040 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d01040 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
================================================
FILE: docs/current-version/assets/scss/pages/_home.scss
================================================
.page-home {
text-align: center;
.title {
font-weight: lighter;
font-family: $font-family-base;
}
p {
margin: 0 auto;
font-size: 1.2rem;
font-weight: lighter;
margin-bottom: 40px;
@include media-breakpoint-up(md) {
width: 80%;
}
@include media-breakpoint-up(lg) {
width: 60%;
}
}
.terminal {
border-radius: 3px;
margin: 0 auto;
margin-top: -200px;
img {
width: 100%;
height: auto;
}
}
}
================================================
FILE: docs/current-version/assets/scss/style.scss
================================================
// Font
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700|Lora:400,700|Roboto+Mono:300,400');
// Bootstrap
@import 'bootstrap/functions';
@import 'bootstrap-variables';
@import 'bootstrap/variables';
@import 'bootstrap/mixins';
@import 'bootstrap/reboot';
@import 'bootstrap/utilities';
@import 'bootstrap/grid';
@import 'bootstrap/tables';
// Libraries
@import 'libraries/hamburgers/hamburgers';
@import 'libraries/pygments/github';
// Components
@import 'components/reset';
@import 'components/type';
@import 'components/page';
@import 'components/header';
@import 'components/footer';
@import 'components/sub-footer';
@import 'components/logo';
@import 'components/main-menu';
@import 'components/main-menu-mobile';
@import 'components/docs-menu';
@import 'components/hamburger';
@import 'components/buttons';
@import 'components/title';
@import 'components/content';
@import 'components/strip';
@import 'components/whitebox';
@import 'components/overview';
@import 'components/anchor';
// Pages
@import 'pages/home';
// Global
body {
font-family: $font-family-base;
font-size: 1rem;
font-weight: 400;
line-height: 1.4;
color: $black;
}
.container {
padding-left: $grid-gutter-width;
padding-right: $grid-gutter-width;
}
.sidebar ul li ul li {
list-style: none;
padding-left: 2em;
}
.sidebar .version {
font-size: 80%;
text-align: right;
padding: 2px;
}
// Display breakpoints for DEV
// body:after {
// color: #000000;
// font-size: 12px;
// padding: 5px;
// font-weight: bold;
// right: 10px;
// position: fixed;
// text-align: center;
// text-transform: uppercase;
// bottom: 10px;
// width: 200px;
// z-index: 9999;
// border: solid 1px #000000;
// @each $name, $value in $grid-breakpoints {
// @include media-breakpoint-up($name) {
// content: "#{$name} - min-width: #{$value}";
// }
// }
// }
================================================
FILE: docs/current-version/config.yaml
================================================
title: Octopilot
languageCode: en-us
pygmentsCodeFences: true
pygmentsCodeFencesGuessSyntax: true
pygmentsUseClasses: true
PygmentsStyle: monokailight
enableGitInfo: true
disableKinds:
- taxonomy
- term
- RSS
- sitemap
- robotsTXT
- "404"
outputs:
home:
- HTML
page:
- HTML
params:
octopilot:
version: v1.0.0
homepage_meta_tags:
meta_description: Automate your Gitops workflow, by automatically creating/merging GitHub Pull Requests
meta_og_title: Octopilot
meta_og_type: website
meta_og_url: https://dailymotion-oss.github.io/octopilot
meta_og_image:
meta_og_description: Automate your Gitops workflow, by automatically creating/merging GitHub Pull Requests
meta_twitter_card: summary
meta_twitter_site: "@dailymotionEng"
meta_twitter_creator: "@dailymotionEng"
menu:
shortcuts:
- name: Source Code
url: https://github.com/dailymotion-oss/octopilot
weight: 10
================================================
FILE: docs/current-version/content/advanced/_index.md
================================================
---
title: "Advanced"
anchor: "advanced"
weight: 60
---
Octopilot advanced features:
- [Templating](#templating)
================================================
FILE: docs/current-version/content/advanced/templating.md
================================================
---
title: "Templating"
anchor: "templating"
weight: 10
---
For some of the CLI flags - such as commit title/body or Pull Requests title/body - you can use our "templating" feature. This will allow you to write nice commits and Pull Requests.
Octopilot uses the [Go template](https://pkg.go.dev/text/template) syntax, and supports the following functions:
- all the [Go template functions](https://golang.org/pkg/text/template/#hdr-Functions)
- all the [sprig functions](http://masterminds.github.io/sprig/)
- Octopilot's own custom functions
## Octopilot's own custom functions
Octopilot comes with the following custom functions:
- `readFile` to read a file from the cloned git repository, and return its content
- `githubRelease` to retrieve the release notes for a specific GitHub release
- `expandGithubLinks` to transform GitHub short links - such as #123 - to absolute URLs
- `extractMarkdownURLs` to transform markdown links to plain URLs
- `md2txt` to strip all the markdown syntax from a string
### readFile
The `readFile` function will read a file from the cloned git repository, and return its content as a string. If the path of the file is relative, it will be relative to the root of the git repository.
Definition: `readFile(filePath string) string`.
Example: `{{readFile "README.md"}}` to print the content of the `README.md` file.
### githubRelease
The `githubRelease` function will retrieve the release notes for a specific GitHub release. The release is identified by the owner, repository and release version.
Definition: `githubRelease(releaseID string) string`.
Example: `{{ githubRelease "owner/repo/v1.2.3" }}` to print the release notes for the release `v1.2.3` of the `owner/repo` github repository.
### expandGithubLinks
The `expandGithubLinks` function will transform GitHub short links - such as #123 - to absolute URLs. It is most useful when combined with the `githubRelease` function, to ensure that the links in the release notes are always absolute.
Definition: `expandGithubLinks(fullRepositoryName string, markdownInput string) string`. The `fullRepositoryName` parameter is the full name of the repository, such as `owner/repo`. It is used to build the absolute URLs.
Example: `{{ githubRelease (print "owner/repo/" (env "VERSION")) | expandGithubLinks "owner/repo" }}`.
### extractMarkdownURLs
The `extractMarkdownURLs` function will transform markdown links to plain URLs. It is most useful when combined with the `githubRelease` function, to ensure that the links in the release notes are always plain URLs - when you want to print plain text, and not markdown, such as in a commit message.
Definition: `extractMarkdownURLs(markdownInput string) string`.
Example: `{{ githubRelease (print "owner/repo/" (env "VERSION")) | expandGithubLinks "owner/repo" | extractMarkdownURLs }}`.
### md2txt
The `md2txt` function will strip all the markdown syntax from a string. It is most useful when combined with the `githubRelease` function, to ensure that the release notes are always plain text, and not markdown. Use it for your commit messages.
Definition: `md2txt(markdownInput string) string`.
Example: `{{ githubRelease (print "owner/repo/" (env "VERSION")) | expandGithubLinks "owner/repo" | extractMarkdownURLs | md2txt }}`.
================================================
FILE: docs/current-version/content/github/_index.md
================================================
---
title: "GitHub Auth"
anchor: "github-auth"
weight: 50
---
Octopilot needs a way to authenticate against the GitHub API, to:
- clone the repositories
- push new changes
- and create/update/merge Pull Requests
It supports 2 ways to authenticate:
- using a personal access **token**, which is the default
- using a GitHub **app**
You can define which method to use, using the `--github-auth-method` CLI flag.
## Personal Access Token
By default, the `--github-auth-method` flag is set to `token`, so Octopilot will use a **Personal Access Token** - or `PAT`. This token can be defined either by the `GITHUB_TOKEN` environment variable, or by setting the `--github-token` CLI flag.
You can read GitHub's documentation on [creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token). You'll need at least the `repo` permissions.
## GitHub App
An alternative to the "simple" token is to use a [GitHub App](https://docs.github.com/en/developers/apps).
First, you'll need to set the `--github-auth-method` flag value to `app`, and then configure the following settings:
- `--github-app-id` (int): the GitHub App ID. Default to the value of the `GITHUB_APP_ID` environment variable.
- `--github-installation-id` (int): the GitHub App installation ID. Default to the value of the `GITHUB_INSTALLATION_ID` environment variable.
- `--github-privatekey` (string): the app's private key - used to sign access token requests - in PEM format. Default to the value of the `GITHUB_PRIVATEKEY` environment variable. You can either set this, or the `--github-privatekey-path`.
- `--github-privatekey-path` (string): the path to the app's private key - used to sign access token requests - in PEM format. Default to the value of the `GITHUB_PRIVATEKEY_PATH` environment variable. Will be used if the `--github-privatekey` flag is not set.
See GitHub's documentation for more details on:
- [Creating a GitHub App](https://docs.github.com/en/developers/apps/building-github-apps/creating-a-github-app)
- [Authenticating with GitHub Apps](https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps)
## Using octopilot with Enterprise GitHub
By default, octopilot will operate on repositories hosted on https://github.com. Octopilot can work on repositories hosted on an Enterprise Github servers by adding the `--github-url` flag.
This flag must be set to the URL of the Enterprise GitHub server (the URL used to browse to the GitHub server main page). Authentication is usually required using any of the authentication method described above.
Example of use:
```bash
$ octopilot \
--github-url https://mygitserver.acme.com \
--repo "${ORG_NAME}/test-repo" \
...
```
================================================
FILE: docs/current-version/content/intro/_index.md
================================================
---
title: "Introduction"
anchor: "intro"
weight: 10
---
**Octopilot** is a CLI tool designed to help you automate your Gitops workflow, by automatically creating and merging GitHub Pull Requests to update specific content in Git repositories.
If you are doing Gitops with GitHub-hosted repositories, **Octopilot** is your *swiss army knife* to propagate changes in your infrastructure.
**Octopilot** was initially developed at [Dailymotion](https://www.dailymotion.com/), and is a core component of our Gitops workflow - you can read our blog post [Introducing Octopilot: a CLI to automate the creation of GitHub pull requests in your gitops workflow](https://vbehar.medium.com/introducing-octopilot-a-cli-to-automate-the-creation-of-github-pull-request-in-your-gitops-e49b9eb0177a).
It works by:
- cloning one or more [repositories](#repos), defined either:
- [statically](#static)
- [dynamically](#dynamic), using environment variables or GitHub search queries
- running one or more [updaters](#updaters) on each cloned repository, using either:
- the [YAML updater](#yaml), to quickly update YAML files
- the [YQ updater](#yq), based on [mikefarah's yq](https://github.com/mikefarah/yq), to manipulate YAML or JSON files as you want
- the [Helm updater](#helm), to easily update the dependencies of an [Helm](https://helm.sh/) chart
- The [sops updater](#sops), to manipulate files encrypted with [mozilla's sops](https://github.com/mozilla/sops)
- The [regex updater](#regex), to update any kind of text file using a regular expression
- The [exec updater](#exec), to execute any command you want
- [commit/push](#commit) the changes
- create [Pull Requests](#pull-request) and optionally merge them
If you want to see what you can do with Octopilot for real, here is a set of real-world [use-cases](#use-cases) that we have at [Dailymotion](https://www.dailymotion.com/):
- [Promoting a new application release](#use-case-app-promotion) with a gitops workflow
- [Promoting a new library release](#use-case-lib-promotion) to a dynamic list of application repositories
- [Updating certificates](#use-case-update-certs) with a gitops workflow
- [Updating Go dependencies](#use-case-go-deps)
- [Previsualizing changes](#use-case-preview) done by octopilot, without pushing to the remote GitHub repository
================================================
FILE: docs/current-version/content/repos/_index.md
================================================
---
title: "Repositories"
anchor: "repos"
weight: 30
---
Octopilot operates on GitHub repositories. A single execution of Octopilot can update one or more repositories. There are 2 ways to define the repositories to update:
- using a [static list](#static)
- using a [dynamic list](#dynamic)
================================================
FILE: docs/current-version/content/repos/commit.md
================================================
---
title: "Commits"
anchor: "commit"
weight: 50
---
After running all the [updaters](#updaters), octopilot will commit the changes on each [repository](#repos). You can control which files will be committed, and how the commit will be created, using the Octopilot's CLI flags.
## Git clone
Flags related to the `git clone` operation:
- `--git-clone-dir` (string): optional path to a directory used to clone the git repositories. Default to a newly created directory in the system temporary directory (defined by the `TMPDIR` environment variable, defaulting to `/tmp`). Note that by default all files created inside this directory will be deleted at the end of the process, unless the `--keep-files` flag is set.
- `--git-recurse-submodules` (bool): recursively initialize all submodules. Disabled by default.
## Git index/stage
By default, all files changed by the [updaters](#updaters) will be added to the git "index" - so that they can be added to the git commit. This is configurable through the following flags:
- `--git-stage-all-changed` (boolean): if set to `true` (the default), then all changed files will be "staged" - or added to the git index. Set it to `false` to control which files should be staged.
- `--git-stage-pattern` (array of string): list of path patterns that will be "staged" - or added to the git index.
For example, to make sure you will only commit the changes to the `helmfile.yaml` file:
```bash
$ octopilot \
--git-stage-all-changed=false \
--git-stage-pattern=helmfile.yaml \
...
```
## Git commit
Although there are good default values, you can configure how Octopilot will create the git commit:
- `git-author-name` (string): the name of the author of the git commit. Default to the value of the `GIT_AUTHOR_NAME` environment variable, or if unset, the `user.name` git config value.
- `git-author-email` (string): the email of the author of the git commit. Default to the value of the `GIT_AUTHOR_EMAIL` environment variable, or if unset, the `user.email` git config value.
- `git-committer-name` (string): the name of the committer. Default to the value of the `GIT_COMMITTER_NAME` environment variable, or if unset, the `user.name` git config value.
- `git-committer-email` (string): the email of the committer. Default to the value of the `GIT_COMMITTER_EMAIL` environment variable, or if unset, the `user.email` git config value.
- `git-commit-title` (string): the title of the commit. Note that you can use the [templating](#templating) feature here.
- `git-commit-body` (string): the body of the commit. Note that you can use the [templating](#templating) feature here.
- `git-commit-footer` (string): the footer of the commit. Default to Octopilot's signature, to indicate that this commit was generated by a tool.
The commit message is composed of the commit title, body and optional footer:
```go-text-template
${git-commit-title}
${git-commit-body}
--
${git-commit-footer}
```
For example, to update the version of an application named `my-app`, and write a nice commit message:
```bash
$ octopilot \
--repo "my-org/my-gitops-repo" \
--update "yaml(file=my-app/config.yaml,path='version')=${VERSION}" \
--git-commit-title 'chore(deps): update my-app to {{ env "VERSION" }}' \
--git-commit-body '{{ githubRelease (print "my-org/my-app-repo/" (env "VERSION")) | md2txt }}' \
...
```
It's using the [templating](#templating) feature to retrieve the GitHub Release for your application's version, and convert it to raw text. So in your commit message, you'll see what changed in the new version.
## Git push
- `git-branch-prefix` (string): when pushing the changes to the "origin" git repository, a new branch with a random name will be created. You can control the prefix of this random name, which default to `octopilot-`.
Note that Octopilot requires permissions to push on the GitHub repositories to update. For the moment, it doesn't support forking the repository, and creating the Pull Request from the fork.
## Git signing
- `git-signing-key-path` (string): when provided, Octopilot will use the GPG private key file to sign commits or tags, which will allow GitHub to verify the committer's identity. See [Add a GPG key](https://docs.github.com/en/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account).
- `git-signing-key-passphrase` (string): Passphrase to decrypt the GPG private key used to sign commits. Leave empty if the private key is stored unencrypted.
================================================
FILE: docs/current-version/content/repos/dynamic.md
================================================
---
title: "Dynamic list"
anchor: "dynamic"
weight: 20
---
Octopilot can also be used with a "dynamic" list of repositories: repositories that are unknown when you write the command arguments.
It can retrieve the list of repositories to update from:
- one or more **environment variables**
- one or more [GitHub Repositories Search Query](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-for-repositories)
- one or more [GitHub Code Search Query](https://docs.github.com/en/search-github/searching-on-github/searching-code)
## Using environment variables
At runtime, Octopilot will read the list of repositories defined in one or more environment variables, such as:
```bash
$ export PROMOTE_TO_REPOSITORIES="my-github-org/my-first-repo my-github-org/my-second-repo(draft=true,merge=false)"
$ export ANOTHER_SET_OF_REPOSITORIES="some-org/some-repo;another-org/another-repo(draft=false)"
$ octopilot \
--repo "discover-from(env=PROMOTE_TO_REPOSITORIES)" \
--repo "discover-from(env=ANOTHER_SET_OF_REPOSITORIES,sep=;,draft=true)"
```
It supports the following parameters:
- `env` (string): the name of the environment variable to use, to retrieve the list of repositories.
- `sep` (string): the separator between each repository, default to `" "` (space).
- `merge` (boolean): if `true`, then the PRs created on the repositories from this env var will be automatically merged - see the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge` flag for the repositories defined in this env var.
- `mergeauto` (boolean): if `true`, then the PR will merged by Github's auto-merge PR feature. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto` flag for these specific repository.
- `mergeautowait` (boolean): if `true`, then wait until the PR is actually merged. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto-wait` flag for these specific repository.
- `draft` (boolean): if `true`, then the PRs will be created as [draft PRs](https://github.blog/2019-02-14-introducing-draft-pull-requests/) on GitHub. You will need to manually mark them as "ready for review" before being able to merge them. It overrides the value of the `--pr-draft` flag for the repositories defined in this env var.
- `branch` (string): the name of the base branch to use when cloning the repositories. Default to the `HEAD` branch - which means the default branch configured in GitHub: usually `main` or `master`.
Note that each repository listed in an environment variable supports all the parameters defined in the [static definition of a repository](#static).
## Using GitHub Search Query
A more powerful feature is the ability to load a list of repositories from a [GitHub Repositories Search Query](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-for-repositories) or a [GitHub Code Search Query](https://docs.github.com/en/search-github/searching-on-github/searching-code), such as:
```bash
$ octopilot \
--repo "discover-from(query=org:my-github-org topic:some-topic)" \
--repo "discover-from(query=org:my-github-org in:readme some-specific-content-in-the-readme,draft=true)" \
--repo "discover-from(query=org:my-github-org language:java is:private mirror:false archived:false,merge=true)" \
--repo "discover-from(searchtype=code,query=org:my-org filename:my-file path:dir-path in-file-text)" \
--repo "discover-from(searchtype=code,query=org:my-org filename:my-file path:dir-path fork:true)"
```
At runtime, Octopilot will use the GitHub API to retrieve the list of repositories matching a given query. This is useful when you have a common library used/imported by many repositories, and you want to create a PR to update the version when there is a new release of your lib. Instead of hardcoding the list of "dependant" repositories in your library repository, you can use a GitHub Search Query to find all repositories with a specific topic, or specific content in the description of the repo, or specific content in the README.md file of the repo, and so on. So "dependant" repositories can easily opt-in to get automatic PRs just by adding a topic for example.
It supports the following parameters:
- `searchtype` (string): represents the type of github search to be performed. Only `code` and `repositories` are availables. Default to `repositories`.
- `query` (string): Specifies search criteria for listing repositories, including filters for file contents, location, language, topic, and more.
- `merge` (boolean): if `true`, then the PRs created on the repositories from this query will be automatically merged - see the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge` flag for the repositories retrieved from this query.
- `mergeauto` (boolean): if `true`, then the PR will merged by Github's auto-merge PR feature. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto` flag for these specific repository.
- `mergeautowait` (boolean): if `true`, then wait until the PR is actually merged. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto-wait` flag for these specific repository.
- `draft` (boolean): if `true`, then the PRs will be created as [draft PRs](https://github.blog/2019-02-14-introducing-draft-pull-requests/) on GitHub. You will need to manually mark them as "ready for review" before being able to merge them. It overrides the value of the `--pr-draft` flag for the repositories retrieved from this query.
- `branch` (string): the name of the base branch to use when cloning the repositories. Default to the `HEAD` branch - which means the default branch configured in GitHub: usually `main` or `master`.
See the ["promoting a new library release" use-case](#use-case-lib-promotion) for a real-life example of what you can do with this feature.
================================================
FILE: docs/current-version/content/repos/pull-request.md
================================================
---
title: "Pull Requests"
anchor: "pull-request"
weight: 60
---
After running all the [updaters](#updaters) and creating a [git commit](#commit), octopilot will create a Pull Request for each [repository](#repos).
## Strategies
Octopilot has 3 strategies for creating a Pull Request:
- **reset** (the default): reset any existing Pull Request from the base branch
- **append**: append new commits to any existing Pull Request
- **recreate**: always create a new Pull Request
You can control which strategy to use using the `--strategy` CLI flag.
### Reset Strategy
This is the default strategy. With this strategy, Octopilot will reset any existing Pull Request from the base branch.
In detail, it will:
- clone the git repository
- find a "matching" Pull Request - based on the pre-configured labels. If there is a matching Pull Request, it will use the PR's branch. Otherwise, it will just create a new branch
- reset the branch to the base branch - usually `main` or `master`
- run the [updaters](#updaters)
- [commit](#commit) the changes and (force) push the commit
- update the existing Pull Request title/body/labels/comments/assignees or create a new one
Note that you can control how the existing Pull Request will be updated. For both the title and body, you can either:
- **ignore** the new changes. The existing PR won't be changed - except for the labels, comments, assignees, and of course the commit.
- **replace** the title and/or body with the new ones. This is the default for the **reset** strategy.
- **prepend** the title and/or body with the new ones. This is mostly useful for the body.
- **append** the title and/or body with the new ones. This is mostly useful for the body.
### Append Strategy
With this strategy, Octopilot will append new commits to any existing Pull Request.
In detail, it will:
- clone the git repository
- find a "matching" Pull Request - based on the pre-configured labels. If there is a matching Pull Request, it will switch to the PR's branch. Otherwise it will just create a new branch from the base branch, and switch to it.
- run the [updaters](#updaters)
- [commit](#commit) the changes and push the commit
- update the existing Pull Request title/body/labels/comments/asignees or create a new one
Note that you can control how the existing Pull Request will be updated. For both the title and body, you can either:
- **ignore** the new changes. The existing PR won't be changed - except for the labels, comments, assignees, and of course the commit. This is the default for the **append** strategy.
- **replace** the title and/or body with the new ones.
- **prepend** the title and/or body with the new ones. This is mostly useful for the body.
- **append** the title and/or body with the new ones. This is mostly useful for the body.
### Recreate Strategy
With this strategy, Octopilot will always create a new Pull Request.
In detail, it will:
- clone the git repository
- create a new branch from the base branch, and switch to it
- run the [updaters](#updaters)
- [commit](#commit) the changes and push the commit
- create a new Pull Request
## Creating / updating Pull Requests
You can control how the Pull Requests will be created or updated using the following CLI flags:
- `--strategy` (string): strategy to use when creating/updating the Pull Requests: either `reset` (reset any existing PR from the current base branch), `append` (append new commit to any existing PR) or `recreate` (always create a new PR). Default to `reset`.
- `--dry-run` (bool): if enabled, won't perform any operation on the remote git repository or on GitHub: all operations will be done in the local cloned repository. So no Pull Request will be created/updated. Default to `false`.
- `--pr-title` (string): the title of the Pull Request. Default to the commit title. Note that you can use the [templating](#templating) feature here.
- `--pr-title-update-operation` (string): the type of operation when updating a Pull Request's title: either `ignore` (keep old value), `replace`, `prepend` or `append`. Default is: `ignore` for "append" strategy, `replace` for "reset" strategy, and not applicable for "recreate" strategy.
- `--pr-body` (string): the body of the Pull Request. Default to the commit body and the commit footer. Note that you can use the [templating](#templating) feature here.
- `--pr-body-update-operation` (string): the type of operation when updating a Pull Request's body: either `ignore` (keep old value), `replace`, `prepend` or `append`. Default is: `ignore` for "append" strategy, `replace` for "reset" strategy, and not applicable for "recreate" strategy.
- `--pr-comment` (array of string): optional list of comments to add to the Pull Request.
- `--pr-assignees` (array of string): optional list of assignees (Github usernames) to add to the Pull Request.
- `--pr-reviewers` (array of string): optional list of reviewers (Github usernames) for the Pull Request.
- `--pr-team-reviewers` (array of string): optional list of team reviewers (Github team names) for the Pull Request.
- `--pr-labels` (array of string): optional list of labels to set on the pull requests, and used to find existing pull requests to update. Default to `["octopilot-update"]`.
- `--pr-base-branch` (string): name of the branch used as a base when creating pull requests. Default to `master`.
- `--pr-draft` (bool): if enabled, the Pull Request will be created as a draft - instead of regular ones. It means that the PRs can't be merged until marked as "ready for review". Default to `false`.
## Merging Pull Requests
Optionally, Octopilot can also automatically merge the Pull Requests it creates. Before merging a Pull Request, Octopilot will wait for the PR to be in a "mergable" state, and for all required status checks to pass.
- `--pr-merge` (bool): if enabled, the Pull Requests will be automatically merged. It will wait until the PRs are "mergeable" before merging them. Default to `false`.
All the following flags only apply if `--pr-merge` is enabled.
- `--pr-merge-auto` (bool): merge PRs using Github's [auto-merge PR feature](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request).
By default, this will not wait until the PR is merged.
Note, this must also be enabled at the [repository level](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-auto-merge-for-pull-requests-in-your-repository) for it to work. This is a one-time task and `ocotopilot` will *not* do this for you. One way of doing this in bulk is using the `gh` CLI: `gh search repos --json url --jq '.[].url' ... | xargs -L1 gh repo edit --enable-auto-merge`.
- `--pr-merge-auto-wait` (bool): when `--pr-merge-auto` is enabled, wait for the PR to be merged by Github.
- `--pr-merge-method` (string): the merge method to use. Either `merge`, `squash`, or `rebase`. Default to `merge`.
- `--pr-merge-commit-title` (string): optional title of the merge commit.
- `--pr-merge-commit-message` (string): optional body of the merge commit.
- `--pr-merge-sha` (string): optional SHA that pull request head must match to allow merge.
- `--pr-merge-poll-timeout` (string/duration): maximum duration to wait for a Pull Request to be mergeable/merged, using the [Golang syntax](https://golang.org/pkg/time/#ParseDuration). Default to `10m` (10 minutes).
- `--pr-merge-poll-interval` (string/duration): duration to wait for between each GitHub API call to check if a PR is mergeable/merged, using the [Golang syntax](https://golang.org/pkg/time/#ParseDuration). Default to `30s` (30 seconds).
- `--pr-merge-retry-count` (int): number of times to retry the merge operation in case of merge failure. Default to `3`.
- `--pr-merge-branch-protection` (string): One of `statusChecks`, `all`, `bypass`. Wait for the specified kind of branch protection rules to be satisfied before attempting to merge.
- `statusChecks` waits only for status checks to be passing. This is the default.
- `all` waits for every rule (approvals, commit signature, etc).
- `bypass` will bypass branch protection rules when possible (i.e. the authenticated user/app have permissions to do so).
================================================
FILE: docs/current-version/content/repos/static.md
================================================
---
title: "Static list"
anchor: "static"
weight: 10
---
It is the easiest: just specify the repositories on the CLI using the `--repo` flag, such as:
```bash
$ octopilot \
--repo "my-github-org/my-first-repo" \
--repo "my-github-org/my-second-repo(merge=true)" \
--repo "my-github-org/my-third-repo(draft=true,merge=false,branch=dev)"
```
You can add as much repositories as you want, each with different configuration.
It supports the following parameters:
- `merge` (boolean): if `true`, then the PR created on this repository will be automatically merged - see the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge` flag for this specific repository.
- `mergeauto` (boolean): if `true`, then the PR will merged by Github's auto-merge PR feature. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto` flag for this specific repository.
- `mergeautowait` (boolean): if `true`, then wait until the PR is actually merged. See the [Pull Requests](#pull-request) section for more details. It overrides the value of the `--pr-merge-auto-wait` flag for this specific repository.
- `draft` (boolean): if `true`, then the PR will be created as a [draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) on GitHub. You will need to manually mark it as "ready for review" before being able to merge it. It overrides the value of the `--pr-draft` flag for this specific repository.
- `branch` (string): the name of the base branch to use when cloning the repository. Default to the `HEAD` branch - which means the default branch configured in GitHub: usually `main` or `master`.
================================================
FILE: docs/current-version/content/updaters/_index.md
================================================
---
title: "Updaters"
anchor: "updaters"
weight: 40
---
The core feature of Octopilot is to update git repositories, and to do it you can use one or more of the available "updaters":
- the [YAML updater](#yaml), to quickly update YAML files
- the [YQ updater](#yq), based on [mikefarah's yq](https://github.com/mikefarah/yq), to manipulate YAML or JSON files as you want
- the [Helm updater](#helm), to easily update the dependencies of an [Helm](https://helm.sh/) chart
- The [sops updater](#sops), to manipulate files encrypted with [mozilla's sops](https://github.com/mozilla/sops)
- The [regex updater](#regex), to update any kind of text file using a regular expression
- The [exec updater](#exec), to execute any command you want
Each updater can be used once or more, such as:
```bash
$ octopilot \
--update "yaml(file=config.yaml,path='version')=file(path=VERSION)" \
--update "regex(file=some-file.txt,pattern='version: \"(.*)\"')=${VERSION}" \
--update "yaml(file=another-config.yaml,path='path.to.version')=$(cat VERSION)" \
...
```
================================================
FILE: docs/current-version/content/updaters/exec.md
================================================
---
title: "Exec"
anchor: "exec"
weight: 60
---
The **exec** updater can execute any command you want, so you can change files in the cloned git repository with any tool you have available.
For example to update all your Go dependencies to the latest version:
```bash
$ octopilot \
--update "exec(cmd=go,args=get -d -t -u)" \
--update "exec(cmd=go,args=mod tidy)" \
--update "exec(cmd=go,args=mod vendor)" \
--git-stage-pattern "vendor" \
...
```
This will execute 3 commands, that will update the `go.mod` & `go.sum` files, and the `vendor` dir. Octopilot will then add/commit all the changes, including the new files in the `vendor` directory.
The syntax is: `exec(params)`.
It supports the following parameters:
- `cmd` (string): mandatory command to execute.
- `path` (string): optional path to execute the command in.
- `args` (string): optional arguments for the command. The arguments are space-separated. If you have a space in an argument, you can quote it, such as: `-c 'some arg' -x another`.
- `stdout` (string): optional path to a file where the std output of the command will be written. If it's a relative path, it will be relative to the root of the cloned git repository.
- `stderr` (string): optional path to a file where the std error output of the command will be written. If it's a relative path, it will be relative to the root of the cloned git repository.
- `timeout` (string/duration): optional maximum duration to wait for the command to finish, using the [Golang syntax](https://golang.org/pkg/time/#ParseDuration).
A few things you can do with the regex updater:
- use a bash command to enable shell expansion (disabled by default when invoking commands through Octopilot)
```bash
$ octopilot \
--update "exec(cmd=sh,args=-c 'cat files/*.txt',stdout=output.txt)"
```
- use the an external tool (here kustomize) and change the current working directory before executing the command
```bash
$ octopilot \
--update "exec(cmd=kustomize, path=k8s/overlays/dev, args=edit set image containername=registry.tld/repo/image:newtag)"
```
See the ["updating go dependencies" use-case](#use-case-go-deps) for a real-life example of what you can do with this updater.
================================================
FILE: docs/current-version/content/updaters/helm.md
================================================
---
title: "Helm"
anchor: "helm"
weight: 30
---
The Helm updater is made to easily update the dependencies of one or more [Helm](https://helm.sh/) charts. It supports both:
- Helm v3, with the dependencies declared in the `Chart.yaml` file
- Helm v2, with the dependencies declared in the `requirements.yaml` file
If you run the following command:
```bash
$ octopilot \
--update "helm(dependency=chart-name)=1.2.3" \
...
```
Octopilot will discover all charts stored in the cloned repository, and for each, try to change the version of the `chart-name` dependency to `1.2.3`.
The syntax is: `helm(params)=value` - you can read more about the value in the ["value" section](#value).
It supports the following parameters:
- `dependency` (string): mandatory name of the dependency to update. Must exist in the dependencies list - it won't be added.
- `indent` (int): optional number of spaces used for indentation when writing the YAML file(s) after update. Default to `2`.
Note that Octopilot will keep the comments in the YAML files - because we're using the great [go-yaml v3 lib](https://github.com/go-yaml/yaml/tree/v3). [Just that it might rewrite a bit your indentation](https://mikefarah.gitbook.io/yq/usage/output-format#indent).
See the ["promoting a new library release" use-case](#use-case-lib-promotion) for a real-life example of what you can do with this updater.
================================================
FILE: docs/current-version/content/updaters/regex.md
================================================
---
title: "Regex"
anchor: "regex"
weight: 50
---
The **regex** updater can be used to update any kind of text file using a regular expression - with the [Golang syntax](https://golang.org/pkg/regexp/syntax/), such as:
```bash
$ octopilot \
--update "regex(file=some-file.txt,pattern='version: \"(.*)\"')=${VERSION}" \
...
```
Given the following `some-file.txt` file:
```
version: "1.0.0"
...
```
Octopilot will replace the first line with `version: "1.2.3"` if the `$VERSION` env var is set to `1.2.3` for example.
The syntax is: `regex(params)=value` - you can read more about the value in the ["value" section](#value).
It supports the following parameters:
- `file` (string): mandatory path to the file to update. Can be a file pattern - such as `files/*.txt` to match files in the same directory, or `files/**/*.txt` using double asterisks (**) to match files in subdirectories. If it's a relative path, it will be relative to the root of the cloned git repository. For more information on using file patterns, you can refer to the [go-zglob documentation](https://github.com/mattn/go-zglob).
- `pattern` (string): mandatory regex pattern to find and replace something in the file(s). The pattern must be in the [Golang syntax](https://golang.org/pkg/regexp/syntax/). If this pattern includes a capturing group, then it will be replaced by the provided value.
A few things you can do with the regex updater:
- replace the whole content of a file
```bash
$ octopilot \
--update "regex(file=my-file,pattern='(?ms)(.*)')=new content"
```
================================================
FILE: docs/current-version/content/updaters/sops.md
================================================
---
title: "Sops"
anchor: "sops"
weight: 40
---
The **sops** updater can manipulate files encrypted with [mozilla's sops](https://github.com/mozilla/sops) natively, without the need to install [sops](https://github.com/mozilla/sops). This is great if you want to store sensitive data in your git repositories: you can encrypt them with `sops`, and use Octopilot to update them automatically.
For example if you want to store your TLS certificate as a base64 encoded string in a sops-encrypted file:
```bash
$ octopilot \
--update `sops(file=secrets.yaml,key=app.tls.base64encodedCertificateKey)=$(kubectl -n cert-manager get secrets tls-myapp -o template='{{index .data "tls.key"}}')` \
...
```
Given the following (decrypted) `secrets.yaml` file:
```yaml
app:
tls:
base64encodedCertificateKey: LS0tLS1CRUdJTiBSU0EgU...
```
Octopilot will decrypt the `secrets.yaml` file, set the value of the `app.tls.base64encodedCertificateKey` key to the given value, and re-encrypt the `secrets.yaml` file before writing it to disk.
The syntax is: `sops(params)=value` - you can read more about the value in the ["value" section](#value).
It supports the following parameters:
- `file` (string): mandatory path to the file to update. Can be a file pattern - such as `config/secrets.*` to match files in the same directory, or `config/**/secrets.*` using double asterisks (**) to match files in subdirectories. If it's a relative path, it will be relative to the root of the cloned git repository. For more information on using file patterns, you can refer to the [go-zglob documentation](https://github.com/mattn/go-zglob).
- `key` (string): mandatory key to update in the file(s).
Note that depending on the sops backend you use (KMS, age, vault, ...) you might need to set some environment variables, such as:
- for GCP KMS, the `GOOGLE_APPLICATION_CREDENTIALS` env var
- for [age](https://age-encryption.org/), the `SOPS_AGE_KEY_FILE` env var
- ...
See the ["updating certificates" use-case](#use-case-update-certs) for a real-life example of what you can do with this updater.
================================================
FILE: docs/current-version/content/updaters/value.md
================================================
---
title: "Value"
anchor: "value"
weight: 100
---
Some updaters accept a **value** in their syntax, such as `updater(params)=value`.
This value can be either:
- a raw value
- the content of a file
## Raw value
This is the easiest way to set a value: just use a raw value, such as:
```bash
$ octopilot \
--update "yaml(file=config.yaml,path='version')=v1.2.3" \
...
```
Note that you can also use an environment variable:
```bash
$ export VERSION=v1.2.3
$ octopilot \
--update "yaml(file=config.yaml,path='version')=${VERSION}" \
...
```
or any command you want:
```bash
$ echo v1.2.3 > /tmp/VERSION
$ octopilot \
--update "yaml(file=config.yaml,path='version')=$(cat /tmp/VERSION)" \
...
```
## File content
If you want to use the content of a file, you can use the **file** valuer:
```bash
$ octopilot \
--update "yaml(file=config.yaml,path='version')=file(path=VERSION)" \
...
```
It will read the `VERSION` file located at the root of the cloned git repository, and use its content as the value.
The syntax is: `file(params)`.
It supports the following parameters:
- `path` (string): mandatory path to the file to read. If it's a relative path, it will be relative to the root of the cloned git repository.
================================================
FILE: docs/current-version/content/updaters/yaml.md
================================================
---
title: "YAML"
anchor: "yaml"
weight: 10
---
The YAML updater is great when you want to quickly set a value for a specific path in one or more files. Such as if you want to update a version used in a YAML file:
```bash
$ octopilot \
--update "yaml(file=config.yaml,path='app.version')=file(path=VERSION)" \
...
```
Given the following `config.yaml` file:
```yaml
app:
name: foo
version: 1.0.0
```
Octopilot will set the value of the `app.version` key to the content of the `VERSION` file.
The syntax is: `yaml(params)=value` - you can read more about the value in the ["value" section](#value).
It supports the following parameters:
- `file` (string): mandatory path to the file to update. Can be a file pattern - such as `config/*.yaml` to match files in the same directory, or `config/**/*.yaml` using double asterisks (**) to match files in subdirectories. If it's a relative path, it will be relative to the root of the cloned git repository. For more information on using file patterns, you can refer to the [go-zglob documentation](https://github.com/mattn/go-zglob).
- `path` (string): mandatory path to the key to update in the YAML file(s). We support [yq v3 path expressions](https://mikefarah.gitbook.io/yq/v/v3.x/usage/path-expressions) or [yq v4 syntax](https://mikefarah.gitbook.io/yq/operators/traverse-read).
- `indent` (int): optional number of spaces used for indentation when writing the YAML file(s) after update. Default to `2`.
- `trim` (boolean): if `true`, the content will be "trimmed" before being written to disk - to avoid extra line break at the end of the file for example.
- `create` (boolean): if `true`, then the `path` will always be set to the given value, even if no such key existed before. The default behaviour (`false`) is to NOT create any new path/key.
- `style` (string): an optional style to apply to the new value: `double` (add double quotes), `single` (add single quotes), `literal`, `folded` or `flow` - see [yq style reference](https://mikefarah.gitbook.io/yq/operators/style).
Note that Octopilot will keep the comments in the YAML files - because we're using the great [go-yaml v3 lib](https://github.com/go-yaml/yaml/tree/v3). [Just that it might rewrite a bit your indentation](https://mikefarah.gitbook.io/yq/usage/output-format#indent).
See the ["updating certificates" use-case](#use-case-update-certs) for a real-life example of what you can do with this updater.
================================================
FILE: docs/current-version/content/updaters/yq.md
================================================
---
title: "YQ"
anchor: "yq"
weight: 20
---
The YQ updater is based on the excellent [yq](https://github.com/mikefarah/yq) application - and Go lib. It is much more powerful than the basic [YAML updater](#yaml) - because it supports all the [yq operators](https://mikefarah.gitbook.io/yq/operators), and because you are not limited to setting a value for a specific key. You can do very powerful things, such as manipulating YAML comments, use variables, output to json (note that it can also read JSON input), ...
The syntax is: `yq(params)`, such as:
```bash
$ octopilot \
--update "yq(file=config.yaml,expression='.path.to.version = strenv(VERSION)')" \
...
```
It supports the following parameters:
- `file` (string): mandatory path to the file to update. Can be a file pattern - such as `config/*.yaml` to match files in the same directory, or `config/**/*.yaml` using double asterisks (**) to match files in subdirectories. If it's a relative path, it will be relative to the root of the cloned git repository. For more information on using file patterns, you can refer to the [go-zglob documentation](https://github.com/mattn/go-zglob).
- `expression` (string): mandatory [yq v4 expression](https://mikefarah.gitbook.io/yq/commands/evaluate) that will be evaluated against each file.
- `output` (string): optional output of the result. By default the result is written to the source file - in-place editing. But you can send the result to `stdout`, `stderr` or a specific file.
- `json` (boolean): if `true`, then the output will be written in JSON format instead of YAML format.
- `indent` (int): optional number of spaces used for indentation when writing the YAML file(s) after update. See [yq doc on indent](https://mikefarah.gitbook.io/yq/usage/output-format#indent). Default to `2`.
- `trim` (boolean): if `true`, the content will be "trimmed" before being written to disk - to avoid extra line break at the end of the file for example.
- `unwrapscalar` (boolean): if `true` (the default), only the value will be printed - not the comments. See [yq doc on unwrap scalars](https://mikefarah.gitbook.io/yq/usage/output-format#unwrap-scalars).
Note that Octopilot will keep the comments in the YAML files - because we're using the great [go-yaml v3 lib](https://github.com/go-yaml/yaml/tree/v3). [Just that it might rewrite a bit your indentation](https://mikefarah.gitbook.io/yq/usage/output-format#indent).
See the ["promoting a new application release" use-case](#use-case-app-promotion) for a real-life example of what you can do with this updater.
================================================
FILE: docs/current-version/content/usage/_index.md
================================================
---
title: "Usage"
anchor: "usage"
weight: 20
---
You can download the binary or see the `docker pull` commands from the [release page on GitHub](https://github.com/dailymotion-oss/octopilot/releases/latest).
There are no dependencies - not even on `git`.
There are no configuration files - we use CLI flags for everything. You can run `octopilot -h` to see all the flags. Some of them can be used multiple times, such as the `--repo` or `--update` flags.
You will need a GitHub token or app to authenticate with GitHub. See the [GitHub Auth](#github-auth) section for more details.
Here is an example of using Octopilot to update multiple repositories, using multiple updaters:
```bash
$ octopilot \
--github-token "my-github-token" \
--repo "my-org/some-repo" \
--repo "my-org/another-repo(merge=true)" \
--repo "discover-from(env=PROMOTE_TO_REPOSITORIES)" \
--repo "discover-from(query=org:my-org topic:my-topic)" \
--repo "discover-from(searchtype=code,query=org:my-org filename:my-file path:dir-path in-file-text)" \
--repo "discover-from(searchtype=code,query=org:my-org filename:my-file path:dir-path fork:true)" \
--update "yaml(file=config.yaml,path='version')=file(path=VERSION)" \
--update "yq(file=helmfile.yaml,expression='(.releases[] | select(.chart == \"repo/my-chart\") | .version ) = strenv(VERSION)')" \
--update "sops(file=secrets.yaml,key=path.to.base64encodedCertificateKey)=$(kubectl -n cert-manager get secrets tls-myapp -o template='{{index .data \"tls.key\"}}')" \
--pr-title "Updating some files" \
...
```
## Continuous Delivery Pipelines
Octopilot has been designed to be used in a Continuous Delivery pipeline: no dependencies, no configuration file, only 1 command to update multiple repositories...
You can use it with [Jenkins](https://www.jenkins.io/), [Jenkins X](https://jenkins-x.io/), [Tekton](https://tekton.dev/), [GitHub Actions](https://github.com/features/actions), ...
At Dailymotion, we're using it through [Jenkins X](https://jenkins-x.io/)/[Tekton](https://tekton.dev/) pipelines, and also a few [Jenkins](https://www.jenkins.io/) pipelines.
================================================
FILE: docs/current-version/content/use-cases/_index.md
================================================
---
title: "Use cases"
anchor: "use-cases"
weight: 80
---
If you want to see what you can do with Octopilot for real, here is a set of real-world use-cases that we have at [Dailymotion](https://www.dailymotion.com/):
- [Promoting a new application release](#use-case-app-promotion) with a gitops workflow
- [Promoting a new library release](#use-case-lib-promotion) to a dynamic list of application repositories
- [Updating certificates](#use-case-update-certs) with a gitops workflow
- [Updating Go dependencies](#use-case-go-deps)
- [Previsualizing changes](#use-case-preview) done by octopilot, without pushing to the remote GitHub repository
================================================
FILE: docs/current-version/content/use-cases/app-promotion.md
================================================
---
title: "Promoting a new application release"
anchor: "use-case-app-promotion"
weight: 10
---
If you're doing gitops, you'll most likely have:
- at least one "application" git repository, for your(s) application(s).
- at least one "environment" git repository, for your(s) environment(s).
When you release a new version of your application, you'll need to "promote" it to (at least) one of your environments. In the gitops world, we're doing that by creating a new Pull Request against the target environment git repository, to update the version of the application in a configuration file.
And this is where Octopilot shines. You can use it in your application's Continuous Delivery pipeline to create the Pull Request against your environment's git repository.
Let's see an example, where we want to:
- automatically deploy new releases in the staging environment
- manually deploy new releases in the production environment
To do that, we'll:
- create a Pull Request on the `staging-env` git repository, and ask Octopilot to automatically merge it - and thus deploying it
- create a Pull Request on the `prod-env` git repository, but not merge it. We'll even create the Pull Request as a "draft", making it explicit that the release is not ready yet.
Oh, and we'd like to get nice commit messages and Pull Request title/description, so that people can understand what really is changing with this Pull Request. If all you have is "Update my-app to version 1.2.3", and a diff that shows a version change in a config file, it won't help you understand if this release is just fixing a typo in a README, fixing a critical bug, or introducing a new feature. We're already generating release notes with a changelog - if not, you should, using [git-chglog](https://github.com/git-chglog/git-chglog) for example - so let's re-use it and include it in our commit messages and Pull Request.
Here is an example of an Octopilot invocation you can use to achieve our goal - we'll go over it in details later:
```bash
$ export GITHUB_TOKEN=
$ export ORG_NAME=my-org
$ export APP_NAME=my-app
$ export VERSION=1.2.3
$ octopilot \
--repo "${ORG_NAME}/staging-env(merge=true)" \
--repo "${ORG_NAME}/prod-env(draft=true)" \
--update "yq(file=helmfile.yaml,expression='.releases[] | select(.name == strenv(APP_NAME)) | .version',output=.git/previous-version.txt)" \
--update "yq(file=helmfile.yaml,expression='(.releases[] | select(.name == strenv(APP_NAME)) | .version) = strenv(VERSION)')" \
--git-commit-title 'chore(deps): update {{ env "APP_NAME" }} from {{ readFile ".git/previous-version.txt" | trim }} to {{ env "VERSION" }}' \
--git-commit-body '{{ githubRelease (printf "%s/%s/v%s" (env "ORG_NAME") (env "APP_NAME") (env "VERSION")) | expandGithubLinks (printf "%s/%s" (env "ORG_NAME") (env "APP_NAME")) | extractMarkdownURLs | md2txt }}' \
--git-branch-prefix "octopilot-update-${APP_NAME}-" \
--pr-labels "update-${APP_NAME}" \
--pr-title "Update ${APP_NAME} to ${VERSION}" \
--pr-title-update-operation "replace" \
--pr-body '{{ githubRelease (printf "%s/%s/v%s" (env "ORG_NAME") (env "APP_NAME") (env "VERSION")) | expandGithubLinks (printf "%s/%s" (env "ORG_NAME") (env "APP_NAME")) }}' \
--pr-body-update-operation "prepend" \
--strategy "append"
```
As you can see, we're making the same set of changes to 2 different repositories, with different configurations:
- the PR on the `staging-env` repository will be automatically merged - and thus our release deployed
- the PR on the `prod-env` repository will be created as "draft", and won't be automatically merged - thus requiring a human intervention to merge it
We're running the [YQ updater](#yq) twice, on the same `helmfile.yaml` file, which would look like the following:
```yaml
releases:
- name: my-app
version: 1.0.0
- name: another-app
version: 1.5.0
```
This is a very simplified configuration file for [helmfile](https://github.com/roboll/helmfile), an application used to describe [Helm](http://helm.sh/) releases. You can use whatever you want, it's just to base our example on a real-life use-case.
So we're running the [YQ updater](#yq) twice:
- the first time, with the `.releases[] | select(.name == strenv(APP_NAME)) | .version` expression, to extract the current version for our application named `my-app`. And we're sending the output to the `.git/previous-version.txt` file - which will contain just `1.0.0`. We're doing that to store the "previous" version before changing it without new version. You'll notice that the output file is located in the `.git` directory, this is to avoid committing it by default.
- the second time, we're replacing the version with the new one - stored in the `VERSION` environment variable - with the following expression: `(.releases[] | select(.name == strenv(APP_NAME)) | .version) = strenv(VERSION)`.
Now, we have:
- a locally modified `helmfile.yaml`
- a new `.git/previous-version.txt` file
So it's time to commit!
- in the commit title, we want to include both the previous version and the new version. We'll use the [templating feature](#templating) to include both the content of a file and an environment variable: `chore(deps): update {{ env "APP_NAME" }} from {{ readFile ".git/previous-version.txt" | trim }} to {{ env "VERSION" }}`
- in the commit body, we want to include the release notes for the new version. We'll use the [templating feature](#templating) to retrieve the release notes, convert all the GitHub short links to absolute URLs, and transform the markdown into raw text: `{{ githubRelease (printf "%s/%s/v%s" (env "ORG_NAME") (env "APP_NAME") (env "VERSION")) | expandGithubLinks (printf "%s/%s" (env "ORG_NAME") (env "APP_NAME")) | extractMarkdownURLs | md2txt }}`
We'll also use a custom prefix for the branch name, to make it easier to find which branch belongs to which app, if you have multiple promotion PRs for different applications opened at the same time.
Next, the Pull Request. We'll use the `append` strategy, which means that if we need to promote a release in prod, and the previous one hasn't been merged/deployed yet, we'll just append a new commit on the existing branch/PR. So that your production PR for your application will stay the same, accumulating releases until it is merged. We're using a specific label for our Pull Request: `update-${APP_NAME}` - to make sure we'll find any existing PR for our application, and that each application will get its own PR.
Same as for the commit, we'll use the [templating feature](#templating) to write a nice title and description for our Pull Request - just that this time we won't need to convert from markdown to raw text. And we'll use specific "update operations":
- we'll always replace the PR title, because we want a short title, with only the app name and the latest release's version - using the `--pr-title-update-operation "replace"` flag
- we'll "prepend" the new PR body, before the existing one, using the `--pr-body-update-operation "prepend"` flag. So that the release notes for the latest release will be first - just as when you read a changelog. And of course we don't want to remove the previous release notes.
## Result
### Staging environment
This is a screenshot of a Pull Request on the staging environment git repository, which has been automatically merged. You can see the release notes, and you'll notice the "signature" at the bottom: we're making it easy for people to know:
- that this PR has been generated by an application - and not created manually by a human
- which version of Octopilot has been used
- from where it has been executed. This will most likely be the application's GitHub repository, because it is where you (should) define your application's Continuous Delivery pipeline, which contains a step to execute Octopilot.

### Production environment
This is a screenshot of a Pull Request on the production environment git repository:
- the PR has been created to promote `v3.14.1` of the application
- later, `v3.15.0` has been released - and promoted. Thus adding a new commit to the PR
- and then, `some-user` merged the Pull Request, to deploy in prod
You'll notice that we have 2 release notes in the PR: 1 for each release. So you can see the full changelog for every release that will be deployed when you'll merge this PR.

In this screenshot you can see the 2 commits:

### Feedback
The benefit of adding the application's release notes in the promotion pull request body, is that not only will you know exactly what you'll deploy, but you'll also get links between the application pull request and the promotion pull requests. So that if you go back to the application's PR, you'll see something like:

You can see at the bottom the links to our 2 promotion pull requests, with their statuses - both have been merged already in this case.
## Going further
As you can see, it's easy to adapt this example for your own use-case. For example, you might want:
- to create PRs on a different set of [repositories](#repos): QA, staging and production
- to update different kinds of files, using different [updaters](#updaters)
- to customize the [commit](#commit) or the [Pull Request](#pull-request)
================================================
FILE: docs/current-version/content/use-cases/certificates.md
================================================
---
title: "Updating certificates"
anchor: "use-case-update-certs"
weight: 20
---
One of the questions you will have to answer when doing gitops is: "where do I stop?". What do you store in your environment git repository? For example, should you store your certificates there too, or do you consider them "outside" of the gitops-scope, and so managed by something else, such as [cert-manager](https://cert-manager.io/)?
Let's say we want to manage them with our gitops process. It means that we'll need to:
- store them in a git repository. It's not a problem for the certificate itself, but we'll need to ensure that the private key won't be stored in cleartext.
- update the git repository every time a new certificate is issued - ideally by automatically creating a Pull Request.
In a Kubernetes environment where you have multiple clusters - for example in different regions of the world, different environments, etc - we can setup and use [cert-manager](https://cert-manager.io/) to manage the certificates from a "central" cluster. No need to setup cert-manager in all your clusters. And we'll use Octopilot to "propagate" the certificates to all the clusters, through a gitops workflow, by storing and updating the certificates in one or more git repositories.
You can setup a nightly CronJob, a scheduled pipeline, or anything else you prefer to regularly call Octopilot, to make sure that all the certificates stored in the git repositories are up-to-date - or to create Pull Requests to update them.
In fact, we won't call Octopilot directly, we'll call a script that will perform a few operations before executing Octopilot:
- first, we'll need to retrieve all the certificates from the Kubernetes API - using something like `kubectl -n cert-manager get certificates.cert-manager.io`
- then, for each certificate, we'll need to retrieve its associated Kubernetes Secret, which contains the actual certificate and its private key - both base64-encoded - using something like `kubectl -n cert-manager get secret $secretName -o go-template='{{index .data "tls.crt"}}' > tls.crt.base64`
- optionally, we can extract some data from the certificates, such as the DNS names, validity dates, and so on - to generate nice commit messages and Pull requests. Use the `openssl` tool to extract the `startdate` and `enddate` fields for example.
- and then we can execute Octopilot with something like the following:
```bash
$ octopilot \
--repo "owner/prod-env" \
--update "yaml(file=${APP_NAME}-values.yaml,path=tls.certificate)=file(path=tls.crt.base64)" \
--update "sops(file=${APP_NAME}-secrets.yaml,key=tls.certificateKey)=file(path=tls.key.base64)" \
--git-commit-title "Update ${APP_NAME} certificate" \
--git-commit-body "..." \
--git-branch-prefix "octopilot-cert-${APP_NAME}-" \
--pr-labels "update-cert-${APP_NAME}"
```
Here, we are running 2 [updaters](#updaters):
- the [YAML updater](#yaml), to update the Helm values file of our application, and set the `tls.certificate` value to the content of a `tls.cert.base64` file
- the [SOPS updater](#sops), to update the Helm secrets file of our application - which is in fact a [sops](https://github.com/mozilla/sops)-encrypted YAML file - and set the `tls.certificateKey` value to the content of a `tls.key.base64` file
We're using the default `reset` strategy, which means that if we don't merge the PR right away, and your CronJob runs a second time, it will find the existing PR and just reset it from the base branch, and then force push the commit. So you'll always only see 1 commit, rebased every day, with the latest certificate. We're using a specific label for our Pull Request: `octopilot-cert-${APP_NAME}` - to make sure we'll find any existing PR for our application/certificate, and that each application/certificate will get its own PR.
## Result
This is a screenshot of a Pull Request on an environment git repository, which updates a specific certificate.

You can see that we extracted a few information, to make it easy for reviewers - because the diff is just a base64 blob replaced by another one:
- the creation date of the new certificate - in fact this is the creation timestamp of the latest cert-manager order, which means the latest time the certificate has been renewed
- the new validity dates, extracted using `openssl x509 -in tls.crt -noout -startdate` for example
- the validity dates of the currently deployed certificate, retrieved using `openssl s_client -servername $domain -connect $domain:443 > previous.crt` for example, and then extracted using `openssl` once again
- the list of domains - or DNS names - for which this certificate is valid, extracted using `kubectl -n cert-manager get $cert -o go-template={{.spec.dnsNames}}` for example
Merging this Pull Request would result in a re-deployment of our application, with an updated certificate. So with this approach we can control when we want to deploy new certificates.
================================================
FILE: docs/current-version/content/use-cases/detecting-errors-in-scripts.md
================================================
---
title: "Detecting errors in scripts"
anchor: "detecting-errors-in-scripts"
weight: 50
---
By default Octopilot does not exit with error even when updates fail. Add the `--fail-on-error` flag so that Octopilot exits with error when updates fail.
================================================
FILE: docs/current-version/content/use-cases/go-deps.md
================================================
---
title: "Updating Go dependencies"
anchor: "use-case-go-deps"
weight: 30
---
One of the downside of using a micro-services architecture is that it requires a lot of maintenance on the different git repositories. Even more when you have more repositories than teams or developers. For example, you'll need to ensure that:
- the dependencies are up to date
- the "config files" for your Continuous Delivery pipeline(s) are up to date
- and so on...
Automating the creation of Pull Requests to keep your git repositories "in sync" is a good way to reduce the maintenance effort. [Dependabot](https://dependabot.com/) is one way to do it, Octopilot is another. The benefits of using Octopilot are:
- you control where it is executed - in your own infrastructure
- you control exactly what it does - including running your own custom scripts/binaries
One use-case we have is to update the [Go](https://golang.org/) dependencies, by running the following commands:
- `go get -d -t -u`
- `go mod tidy`
- `go mod vendor`
- `go mod verify`
For example you can do it on octopilot's own repository, by running:
```bash
$ export GITHUB_TOKEN=
$ octopilot \
--repo "dailymotion-oss/octopilot" \
--update "exec(cmd=go,args=get -d -t -u)" \
--update "exec(cmd=go,args=mod tidy)" \
--update "exec(cmd=go,args=mod vendor)" \
--update "exec(cmd=go,args=mod verify)" \
--git-stage-pattern "vendor" \
--git-commit-title "chore(deps): update Go dependencies"
```
You can then run it on a regular basis, such as every week, to update all your dependencies at once. And you can use the [dynamic repositories](#dynamic) feature to do it on all your repositories with a specific GitHub topic.
## Result
This is a screenshot of a Pull Request on a git repository, which updates all the Go modules.

Using the [exec updater](#exec) we can run any command we want, capture its stdout and/or stderr, and use it in the commit message and/or Pull Request description.
================================================
FILE: docs/current-version/content/use-cases/handle-maximum-number-of-repositories-in-parallel.md
================================================
---
title: "Handle maximum number of repositories in parallel"
anchor: "handle-maximum-number-of-repositories-in-parallel"
weight: 50
---
By default Octopilot handles all repositories in parallel - creating as many goroutines as there are repositories.
Add the `--max-concurrent-repos` flag so that Octopilot handles them in a batch way to avoid issues such as github rate limiting, or high load on your CI platform.
================================================
FILE: docs/current-version/content/use-cases/lib-promotion.md
================================================
---
title: "Promoting a new library release"
anchor: "use-case-lib-promotion"
weight: 15
---
Promoting a new release of a library is similar to [promoting a new release of an application](#use-case-app-promotion), except that instead of promoting to a small number of git repositories - representing the different environments - you will promote to a much larger number of git repositories: one for each application using the library.
The main change is that instead of using a [static list](#static) of repositories, you can use a [dynamic list](#dynamic) of repositories - based on a [GitHub Repositories Search Query](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-for-repositories) or a [GitHub Code Search Query](https://docs.github.com/en/search-github/searching-on-github/searching-code) for example.
## GitHub Repositories Search Query
Here is an example of an Octopilot invocation using a dynamic list of repos and GitHub Repositories Search Query - we'll go over it in details later:
```bash
$ export GITHUB_TOKEN=
$ export VERSION=1.0.15
$ octopilot \
--repo "discover-from(query=org:my-org topic:octopilot-my-base-chart)" \
--update "helm(dependency=my-base-chart)=${VERSION}" \
--git-commit-title 'chore(deps): update my-base-chart to {{ env "VERSION" }}' \
--git-commit-body '{{ githubRelease (printf "my-org/my-base-chart/v%s" (env "VERSION")) | expandGithubLinks "my-org/my-base-chart" | extractMarkdownURLs | md2txt }}' \
--git-branch-prefix "octopilot-update-my-base-chart-" \
--pr-labels "update-my-base-chart" \
--pr-title "Update Helm Base Chart to ${VERSION}" \
--pr-title-update-operation "replace" \
--pr-body '{{ githubRelease (printf "my-org/my-base-chart/v%s" (env "VERSION")) | expandGithubLinks "my-org/my-base-chart" }}' \
--pr-body-update-operation "prepend" \
--strategy "append"
```
We're using the following GitHub Repositories search query to discover the repositories that are using the `my-base-chart` Helm chart:
```
query=org:my-org topic:octopilot-my-base-chart
```
Which means that developers just need to add the `octopilot-my-base-chart` topic to their repositories - in the GitHub UI - to enable automatic update of the Helm base chart. It's easy to add, and easy to turn off if you don't want it. Note that you are not limited to searching by topic - you can also search for specific content in the repository's name, description, `README.md` file, and so on.
We're using the [Helm updater](#helm) to update all the [Helm](https://helm.sh/) charts, and set the version of their dependency on `my-base-chart` to the new release version.
Everything else is similar to the [promotion of a new application release](#use-case-app-promotion).
## GitHub Code Search Query
This search type is useful in case you experience some limitations with the default `Repositories` one
- 50 characters max
- 20 topics max per repository
Here is an example of an Octopilot invocation using a dynamic list of repos and GitHub Code Search Query - we'll go over it in details later:
```bash
$ export GITHUB_TOKEN=
$ export VERSION=1.0.15
$ octopilot \
--repo "discover-from(searchtype=code,query=org:my-org filename:Chart.yaml path:charts my-base-chart)" \
--update "yaml(file=charts/*/Chart.yaml,path=dependencies.(name==my-base-chart).version,style=folded)=${VERSION}" \
--git-commit-title 'chore(deps): update my-base-chart to {{ env "VERSION" }}' \
--git-commit-body '{{ githubRelease (printf "my-org/my-base-chart/v%s" (env "VERSION")) | expandGithubLinks "my-org/my-base-chart" | extractMarkdownURLs | md2txt }}' \
--git-branch-prefix "octopilot-update-my-base-chart-" \
--pr-labels "update-my-base-chart" \
--pr-title "Update Helm Base Chart to ${VERSION}" \
--pr-title-update-operation "replace" \
--pr-body '{{ githubRelease (printf "my-org/my-base-chart/v%s" (env "VERSION")) | expandGithubLinks "my-org/my-base-chart" }}' \
--pr-body-update-operation "prepend" \
--strategy "append"
```
We can use the following GitHub Code search type and query to discover the repositories that are using the `my-base-chart` Helm chart:
```
searchtype=code,query=org:my-org filename:Chart.yaml path:charts my-base-chart
```
By default `searchtype` is equal to `repositories`, because here we need to use the Github Code Search query, we have to put it to code.
With Github Code Search query, developers don't need to do anything to enable automatic update of their Helm base chart.
We're using the [Helm updater](#helm) to update all the [Helm](https://helm.sh/) charts, and set the version of their dependency on `my-base-chart` to the new release version.
Everything else is similar to the [promotion of a new application release](#use-case-app-promotion).
## Result
This is the screenshot of the bottom of the library PR which is at the origin of the promotion - and which is referenced in the library's release notes.

You can see that multiple promotion pull requests have been created, one per repository matching the GitHub search query. This is an easy way to see which application repositories have upgraded to the new version of the library.
================================================
FILE: docs/current-version/content/use-cases/preview.md
================================================
---
title: "Previsualizing changes"
anchor: "use-case-preview"
weight: 40
---
If you're working on your workflow with Octopilot, at some point you might want to "preview" the changes Octopilot will do, without actually creating the Pull Request(s).
There is an easy way to do that. You'll need to:
- use the `--dry-run` CLI flag, to ensure that no operation will be performed on the remote git repository: not pushing branches/commits, not creating/updating Pull Requests, ...
- use the `--keep-files` CLI flag, to ensure that the changes to the local cloned git repositories won't be lost at the end of the process - because by default Octopilot removes all temporary files
- use a verbose log level - such as `debug` or `trace` - with the `--log-level` CLI flag, to retrieve the path of the temporary files created by Octopilot
For example, if you run:
```bash
$ export GITHUB_TOKEN=
$ octopilot \
--repo "dailymotion-oss/octopilot" \
--update "yq(file=.goreleaser.yml,expression='(.dockers[] | select(.dockerfile == \"Dockerfile.goreleaser\") | .dockerfile) = \"a.new.Dockerfile\"')" \
--update "yaml(file=.golangci.yml,path=run.timeout)=42m" \
--update "regex(file=README.md,pattern='(?ms)(.*)')=replacing the content of the README.md file with this new content" \
--dry-run --keep-files --log-level=debug
```
Then you should see something like:
```log
DEBU[0000] Updaters ready updaters="[YQ[file=.goreleaser.yml,expression=(.dockers[] | select(.dockerfile == \"Dockerfile.goreleaser\") | .dockerfile) = \"a.new.Dockerfile\",output=,indent=2] YAML[path=run.timeout,file=.golangci.yml,style=,create=false,trim=false,indent=2] Regex[pattern=(?ms)(.*),file=README.md]]"
DEBU[0000] Repositories ready repositories="[{dailymotion-oss octopilot map[]}]"
DEBU[0000] Using 'reset' strategy repository=dailymotion-oss/octopilot
DEBU[0003] Git repository cloned git-reference=HEAD git-url="https://github.com/dailymotion-oss/octopilot.git" local-path=/var/folders/v0/fx5l3skn17785d8f4l883m6w0000gp/T/octopilot092369223/dailymotion-oss/octopilot
DEBU[0003] No existing Pull Request found labels="[octopilot-update]" repository=dailymotion-oss/octopilot
DEBU[0004] Switched Git branch branch=octopilot-c3qif432dnc2961tuuh0 repository-name=octopilot
DEBU[0004] Updater finished changes=true repository=dailymotion-oss/octopilot updater="YQ[file=.goreleaser.yml,expression=(.dockers[] | select(.dockerfile == \"Dockerfile.goreleaser\") | .dockerfile) = \"a.new.Dockerfile\",output=,indent=2]"
DEBU[0004] Updater finished changes=true repository=dailymotion-oss/octopilot updater="YAML[path=run.timeout,file=.golangci.yml,style=,create=false,trim=false,indent=2]"
DEBU[0004] Updater finished changes=true repository=dailymotion-oss/octopilot updater="Regex[pattern=(?ms)(.*),file=README.md]"
DEBU[0004] All updaters finished repository=dailymotion-oss/octopilot
DEBU[0005] Git status repository-name=octopilot status=" M README.md\n M .golangci.yml\n M .goreleaser.yml\n"
DEBU[0006] Git commit commit=d263de874faf26a6ccc8bb2325bc4eb47e0a7029 repository-name=octopilot
WARN[0006] Running in dry-run mode, not pushing changes repository=dailymotion-oss/octopilot
WARN[0006] Repository update has no changes repository=dailymotion-oss/octopilot
INFO[0006] Updates finished repositories-count=1
```
The 2 interesting lines are:
- `Git repository cloned local-path=/var/folders/v0/fx5l3skn17785d8f4l883m6w0000gp/T/octopilot092369223/dailymotion-oss/octopilot`
- `Git commit commit=d263de874faf26a6ccc8bb2325bc4eb47e0a7029`
If you go to the directory identified by the `local-path` value, you can inspect the git repository - for example:
```bash
$ cd /var/folders/v0/fx5l3skn17785d8f4l883m6w0000gp/T/octopilot092369223/dailymotion-oss/octopilot
$ git show d263de874faf26a6ccc8bb2325bc4eb47e0a7029
```
and you should see:
```diff
commit d263de874faf26a6ccc8bb2325bc4eb47e0a7029 (HEAD -> octopilot-c3qif432dnc2961tuuh0)
Author: author
Date: Mon Jul 19 09:19:46 2021 +0200
Octopilot update
Updates:
### YQ[file=.goreleaser.yml,expression=(.dockers[] | select(.dockerfile == "Dockerfile.goreleaser") | .dockerfile) = "a.new.Dockerfile",output=,indent=2]
Update .goreleaser.yml
Updating file(s) `.goreleaser.yml` using yq expression `(.dockers[] | select(.dockerfile == "Dockerfile.goreleaser") | .dockerfile) = "a.new.Dockerfile"`
### YAML[path=run.timeout,file=.golangci.yml,style=,create=false,trim=false,indent=2]
Update .golangci.yml
Updating path `run.timeout` in file(s) `.golangci.yml`
### Regex[pattern=(?ms)(.*),file=README.md]
Update README.md
Updating file(s) `README.md` using pattern `(?ms)(.*)`
--
Generated by [Octopilot](https://github.com/dailymotion-oss/octopilot) [v0.2.16](https://github.com/dailymotion-oss/octopilot/releases/tag/v0.2.16) from https://github.com/dailymotion-oss/octopilot
diff --git a/.golangci.yml b/.golangci.yml
index 9a84d2c..b8a04d9 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,4 +1,4 @@
# See https://golangci-lint.run/usage/configuration/#config-file
run:
- timeout: 3m
+ timeout: 42m
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 3d8734f..1b96958 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -12,12 +12,10 @@ builds:
- -X main.buildDate={{.Date}}
env:
- CGO_ENABLED=0
-
archives:
- format: binary
-
dockers:
- - dockerfile: Dockerfile.goreleaser
+ - dockerfile: a.new.Dockerfile
image_templates:
- "ghcr.io/dailymotion-oss/{{.ProjectName}}:{{ .Version }}"
- "ghcr.io/dailymotion-oss/{{.ProjectName}}:{{ .Tag }}"
@@ -31,6 +29,5 @@ dockers:
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
- "--label=org.opencontainers.image.version={{.Version}}"
- "--label=org.opencontainers.image.source={{.GitURL}}"
-
changelog:
sort: asc
diff --git a/README.md b/README.md
index a1dbefa..b247a46 100644
--- a/README.md
+++ b/README.md
@@ -1,115 +1 @@
-# Octo Pilot
-...
+replacing the content of the README.md file with this new content
```
This is a good way to ensure that you have the right syntax for your [updater(s)](#updaters), and/or that your git commit is what you want.
================================================
FILE: docs/current-version/layouts/_default/baseof.html
================================================
{{ block "title" . }}{{ .Title }} - {{ .Site.Title }}{{ end }}
{{ block "meta_tags" . }}{{end}}
{{ if .Site.IsServer }}
{{ $style := resources.Get "scss/style.scss" | toCSS (dict "targetPath" "css/style.css" "enableSourceMap" true) }}
{{ else }}
{{ $style := resources.Get "scss/style.scss" | toCSS (dict "targetPath" "css/style.css" "outputStyle" "compressed" "enableSourceMap" false) }}
{{ end }}
{{ block "header_css" . }}{{ end }}
{{ partial "header.html" . }}
{{ block "main" . }}
{{ end }}
{{ partial "sub-footer.html" . }}
{{ $scripts := resources.Get "js/scripts.js" }}
{{ block "footer_js" . }}
{{ end }}
{{ if .Site.IsServer }}
{{ else }}
{{ end }}
================================================
FILE: docs/current-version/layouts/_default/list.html
================================================
================================================
FILE: docs/current-version/layouts/_default/single.html
================================================
================================================
FILE: docs/current-version/layouts/index.html
================================================
{{ define "header_css" }}{{ end }}
{{ define "body_classes" }}page-default-single{{ end }}
{{ define "header_classes" }}{{ end }}
{{ define "main" }}
{{ $release := getJSON (print "https://api.github.com/repos/dailymotion-oss/octopilot/releases/tags/" .Site.Params.Octopilot.Version) }}
Documentation for Octopilot {{ $release.name }}
Released on {{ dateFormat "Jan 2, 2006" $release.published_at }}
{{ partial "changelog.html" . }}
{{ with .Sections }}
{{ range .ByWeight }}
{{ partial "section_list.html" . }}
{{ end }}
{{ end }}
{{ end }}
================================================
FILE: docs/current-version/layouts/partials/changelog.html
================================================
{{ $release := getJSON (print "https://api.github.com/repos/dailymotion-oss/octopilot/releases/tags/" .Site.Params.Octopilot.Version) }}
================================================
FILE: docs/current-version/layouts/partials/header.html
================================================
================================================
FILE: docs/current-version/layouts/partials/menu.html
================================================
{{ with .Sections }}
{{ range .ByWeight }}
{{ partial "menu_page_list.html" . }}
{{ end }}
{{ end }}
================================================
FILE: docs/current-version/layouts/partials/menu_page_list.html
================================================
{{ if .Pages }}
{{ .Title }}
{{ if .Sections }}
{{ range .Sections.ByWeight }}
{{ partial "menu_page_list.html" . }}
{{ end }}
{{ else }}
{{ range .Pages.ByWeight }}
{{ .Title }}
{{ end }}
{{ end }}
{{ else }}
{{ .Title }}
{{ end }}
================================================
FILE: docs/current-version/layouts/partials/section.html
================================================
================================================
FILE: docs/current-version/layouts/partials/section_list.html
================================================
{{ if .Pages }}
{{ partial "section.html" . }}
{{ if .Sections }}
{{ range .Sections.ByWeight }}
{{ partial "section_list.html" . }}
{{ end }}
{{ else }}
{{ range .Pages.ByWeight }}
{{ partial "section.html" . }}
{{ end }}
{{ end }}
{{ else }}
{{ partial "section.html" . }}
{{ end }}
================================================
FILE: docs/current-version/layouts/partials/sidebar.html
================================================
================================================
FILE: docs/current-version/layouts/partials/sub-footer.html
================================================
================================================
FILE: docs/current-version/layouts/shortcodes/anchor.html
================================================
{{ $page_path := .Get 0 -}}
{{ with .Site.GetPage $page_path }}
#{{ .Params.anchor }}
{{ end -}}
================================================
FILE: docs/current-version/layouts/shortcodes/block.html
================================================
{{ .Inner }}
================================================
FILE: docs/package-docs.sh
================================================
#!/bin/bash
# detect this script location (also resolve links since $0 may be a softlink)
PRG="$0"
while [[ -h $PRG ]]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
DOCS_DIR=$(dirname "$PRG")
ROOT_DIR=${DOCS_DIR}/..
mkdir -p ${ROOT_DIR}/dist
mv ${DOCS_DIR}/root/public ${ROOT_DIR}/dist/docs
mv ${DOCS_DIR}/current-version/public ${ROOT_DIR}/dist/docs/${VERSION}
================================================
FILE: docs/root/.gitignore
================================================
/public
/resources
================================================
FILE: docs/root/README.md
================================================
# Octopilot root documentation
This is the "root" documentation project for octopilot, it contains:
- a high-level overview of what is octopilot
- links to the detailed per-version documentation
It's a static website build with [Hugo](https://gohugo.io/).
- the content is written in markdown format, in the [content](./content/) directory
- to render the website:
- install [Hugo](https://gohugo.io/) - see the [.github/workflows/release.yml](../../.github/workflows/release.yml) file for the version of Hugo to use
- run `hugo server` in this directory, and open
================================================
FILE: docs/root/config.yaml
================================================
title: Octopilot
theme: OneDly-Theme
languageCode: en-us
pygmentsCodeFences: true
pygmentsCodeFencesGuessSyntax: true
PygmentsStyle: monokailight
enableGitInfo: true
outputs:
home:
- HTML
page:
- HTML
params:
description: Automate your Gitops workflow, by automatically creating/merging GitHub PRs.
author_url: https://github.com/dailymotion-oss
author_name: Dailymotion
project_url: https://github.com/dailymotion-oss/octopilot
mainSections:
- intro
socialShare: false
socialShareTwitter: false
socialShareGoogleplus: false
socialShareFacebook: false
socialShareReddit: false
socialShareLinkedin: false
socialShareStumbleupon: false
socialSharePinterest: false
socialShareEmail: false
# theme's color scheme
first_color: "#f8f8f8"
first_border_color: "#e7e7e7"
first_text_color: "#333"
second_color: "white"
second_text_color: "#333"
header_color: "#f8f8f8"
header_text_color: "rgb(51, 51, 51)"
header_link_color: "#777"
header_link_hover_color: "rgb(51, 51, 51)"
social:
github: dailymotion-oss/octopilot
medium: dailymotion
twitter: dailymotionEng
================================================
FILE: docs/root/content/intro/about.md
================================================
---
title: "About"
anchor: "about"
weight: 10
---
**Octopilot** is a CLI tool designed to help you automate your Gitops workflow, by automatically creating and merging GitHub Pull Requests to update specific content in Git repositories.
If you are doing Gitops with GitHub-hosted repositories, **Octopilot** is your *swiss army knife* to propagate changes in your infrastructure.
**Octopilot** was initially developed at [Dailymotion](https://www.dailymotion.com/), and is a core component of our Gitops workflow - you can read our blog post [Introducing Octopilot: a CLI to automate the creation of GitHub pull requests in your gitops workflow](https://vbehar.medium.com/introducing-octopilot-a-cli-to-automate-the-creation-of-github-pull-request-in-your-gitops-e49b9eb0177a).
### Features
- written in Go, and has **0 dependencies** - not even `git`
- native support for manipulating **YAML or JSON files** - which are commonly used in the Gitops world to describe resources
- native support for manipulating **files encrypted with [sops](https://github.com/mozilla/sops)** - because who wants to store non-encrypted sensitive data in git?
- supports **regex-based updates to any kind of files** - for these times when you need raw power
- supports **executing any command/tool** - because you don't want to be limited by what we support
- supports **multiple strategies to create/update the PRs**
- supports **automatic merge of the PRs** - once the pre-configured CI checks are green
- can update **one or more GitHub repositories** from a single execution - including dynamically defined repositories, using a **GitHub search query**
- can execute **one or more update rules** in a single execution
### Example
Updating multiple repositories, and executing multiple update rules at once:
```bash
$ octopilot \
--github-token "my-github-token" \
--repo "my-org/some-repo" \
--repo "my-org/another-repo(merge=true)" \
--repo "discover-from(env=PROMOTE_TO_REPOSITORIES)" \
--repo "discover-from(query=org:my-org topic:my-topic)" \
--update "yaml(file=config.yaml,path='version')=file(path=VERSION)" \
--update "yq(file=helmfile.yaml,expression='(.releases[] | select(.chart == \"repo/my-chart\") | .version ) = strenv(VERSION)')" \
--update "sops(file=secrets.yaml,key=path.to.base64encodedCertificateKey)=$(kubectl -n cert-manager get secrets tls-myapp -o template='{{index .data \"tls.key\"}}')" \
--pr-title "Updating some files" \
...
```
### Screenshots
#### Pull Request to promote a new release of an application
Including the release notes in the Pull Request description

#### Pull Request to update the certificates

================================================
FILE: docs/root/layouts/_default/_markup/render-image.html
================================================
================================================
FILE: docs/root/layouts/index.html
================================================
{{ partial "head.html" . }}
{{ partial "nav.html" . }}
{{ partial "header.html" . }}
{{ partial "main.html" . }}
{{ partial "versions.html" . }}
{{ partial "social_sharing.html" . }}
{{ partial "footer.html" . }}
================================================
FILE: docs/root/layouts/partials/social.html
================================================
{{ with .Site.Social.github }}
{{ end }}
{{ with .Site.Social.gitlab }}
{{ end }}
{{ with .Site.Social.stackoverflow }}
{{ end }}
{{ with .Site.Social.bitbucket }}
{{ end }}
{{ with .Site.Social.jsfiddle }}
{{ end }}
{{ with .Site.Social.codepen }}
{{ end }}
{{ with .Site.Social.deviantart }}
{{ end }}
{{ with .Site.Social.flickr }}
{{ end }}
{{ with .Site.Social.behance }}
{{ end }}
{{ with .Site.Social.dribbble }}
{{ end }}
{{ with .Site.Social.wordpress }}
{{ end }}
{{ with .Site.Social.medium}}
{{ end }}
{{ with .Site.Social.linkedin }}
{{ end }}
{{ with .Site.Social.linkedin_company }}
{{ end }}
{{ with .Site.Social.foursquare }}
{{ end }}
{{ with .Site.Social.xing }}
{{ end }}
{{ with .Site.Social.slideshare }}
{{ end }}
{{ with .Site.Social.facebook }}
{{ end }}
{{ with .Site.Social.googleplus }}
{{ end }}
{{ with .Site.Social.reddit }}
{{ end }}
{{ with .Site.Social.quora }}
{{ end }}
{{ with .Site.Social.youtube }}
{{ end }}
{{ with .Site.Social.vimeo }}
{{ end }}
{{ with .Site.Social.whatsapp }}
{{ end }}
{{ with .Site.Social.wechat }}
{{ end }}
{{ with .Site.Social.qq }}
{{ end }}
{{ with .Site.Social.instagram }}
{{ end }}
{{ with .Site.Social.tumblr }}
{{ end }}
{{ with .Site.Social.twitter }}
{{ end }}
{{ with .Site.Social.skype }}
{{ end }}
{{ with .Site.Social.snapchat }}
{{ end }}
{{ with .Site.Social.pinterest }}
{{ end }}
{{ with .Site.Social.telegram }}
{{ end }}
{{ with .Site.Social.vine }}
{{ end }}
{{ with .Site.Social.googlescholar }}
{{ end }}
{{ with .Site.Social.orcid }}
{{ end }}
{{ with .Site.Social.researchgate }}
{{ end }}
{{ with .Site.Social.email }}
{{ end }}
================================================
FILE: docs/root/layouts/partials/versions.html
================================================
Documentation
The full documentation for Octopilot is versionned - please select the version you want to use:
{{ range (getJSON "https://api.github.com/repos/dailymotion-oss/octopilot/releases?per_page=10") }}
{{ .name }}
released on {{ dateFormat "Jan 2, 2006" .published_at }}
{{ end }}
================================================
FILE: docs/set-next-version.sh
================================================
#!/bin/bash
echo Next Version: ${VERSION}
# detect this script location (also resolve links since $0 may be a softlink)
PRG="$0"
while [[ -h $PRG ]]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`/"$link"
fi
done
DOCS_DIR=$(dirname "$PRG")
# set the next version
yq --inplace eval '.params.octopilot.version = env(VERSION)' $DOCS_DIR/current-version/config.yaml
================================================
FILE: flake.nix
================================================
{
description = "Automate your Gitops workflow, by automatically creating/merging GitHub Pull Requests.";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};
outputs = inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
perSystem = { config, self', inputs', pkgs, system, ... }: {
packages.default = pkgs.buildGoModule rec {
pname = "octopilot";
version = with inputs; "${self.shortRev or self.dirtyShortRev or "dirty"}";
src = inputs.self;
subPackages = [ "." ];
ldflags = with inputs; [
"-s" "-w"
"-X main.buildVersion=flake-${version}"
"-X main.buildCommit=${self.rev or self.dirtyRev or "dirty"}"
"-X main.buildDate=${inputs.self.lastModifiedDate}"
];
vendorHash = null;
meta = {
homepage = "https://github.com/dailymotion-oss/octopilot";
};
};
};
};
}
================================================
FILE: go.mod
================================================
module github.com/dailymotion-oss/octopilot
go 1.21
require (
github.com/Masterminds/sprig/v3 v3.3.0
github.com/ProtonMail/go-crypto v1.1.5
github.com/bradleyfalzon/ghinstallation v1.1.1
github.com/cosiner/argv v0.1.1-0.20200416041250-86e3c689263e
github.com/go-git/go-git/v5 v5.13.2
github.com/google/go-github/v57 v57.0.0
github.com/imdario/mergo v0.3.16
github.com/mattn/go-zglob v0.0.6
github.com/mholt/archiver v3.1.1+incompatible
github.com/mikefarah/yq/v4 v4.28.2
github.com/mitchellh/go-homedir v1.1.0
github.com/otiai10/copy v1.14.1
github.com/rs/xid v1.6.0
github.com/shurcooL/githubv4 v0.0.0-20231126234147-1cffa1f02456
github.com/sirupsen/logrus v1.9.3
github.com/spf13/pflag v1.0.6
github.com/stretchr/testify v1.10.0
github.com/writeas/go-strip-markdown v2.0.1+incompatible
github.com/ybbus/httpretry v1.0.2
github.com/zoumo/goset v0.2.0
go.mozilla.org/sops/v3 v3.7.3
golang.org/x/oauth2 v0.26.0
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
gopkg.in/yaml.v3 v3.0.1
)
require (
cloud.google.com/go/compute/metadata v0.3.0 // indirect
dario.cat/mergo v1.0.1 // indirect
filippo.io/age v1.2.1 // indirect
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.26 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.23 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.3.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/a8m/envsubst v1.3.0 // indirect
github.com/alecthomas/participle/v2 v2.0.0-beta.5 // indirect
github.com/armon/go-metrics v0.3.10 // indirect
github.com/armon/go-radix v1.0.0 // indirect
github.com/aws/aws-sdk-go v1.43.43 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/elliotchance/orderedmap v1.5.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/goccy/go-yaml v1.9.5 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-github/v29 v29.0.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.11.0 // indirect
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-plugin v1.4.3 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 // indirect
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3 // indirect
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
github.com/hashicorp/go-uuid v1.0.2 // indirect
github.com/hashicorp/go-version v1.4.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/hashicorp/vault/api v1.5.0 // indirect
github.com/hashicorp/vault/sdk v0.4.1 // indirect
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 // indirect
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef // indirect
github.com/huandu/xstrings v1.5.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/lib/pq v1.10.5 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/nwaples/rardecode v1.0.0 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/otiai10/mint v1.6.3 // indirect
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
github.com/pjbgf/sha1cd v0.3.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect
github.com/skeema/knownhosts v1.3.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/ulikunitz/xz v0.5.8 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a // indirect
go.opencensus.io v0.24.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/sync v0.10.0 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/term v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/grpc v1.57.1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/urfave/cli.v1 v1.20.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
)
================================================
FILE: go.sum
================================================
c2sp.org/CCTV/age v0.0.0-20240306222714-3ec4d716e805 h1:u2qwJeEvnypw+OCPUHmoZE3IqwfuN5kgDfo5MLzpNM0=
c2sp.org/CCTV/age v0.0.0-20240306222714-3ec4d716e805/go.mod h1:FomMrUJ2Lxt5jCLmZkG3FHa72zUprnhd3v/Z18Snm4w=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
filippo.io/age v1.2.1 h1:X0TZjehAZylOIj4DubWYU1vWQxv9bJpo+Uu2/LGhi1o=
filippo.io/age v1.2.1/go.mod h1:JL9ew2lTN+Pyft4RiNGguFfOpewKwSHm5ayKD/A4004=
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible h1:INepVujzUrmArRZjDLHbtER+FkvCoEwyRCXGqOlmDII=
github.com/Azure/azure-sdk-for-go v63.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs=
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc=
github.com/Azure/go-autorest/autorest v0.11.26 h1:W/MzvoAiFfL5h4nq81wm7axvITgbnOoifXXGkFrgF1g=
github.com/Azure/go-autorest/autorest v0.11.26/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8=
github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA=
github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4=
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk=
github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE=
github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac=
github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4=
github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE=
github.com/a8m/envsubst v1.3.0 h1:GmXKmVssap0YtlU3E230W98RWtWCyIZzjtf1apWWyAg=
github.com/a8m/envsubst v1.3.0/go.mod h1:MVUTQNGQ3tsjOOtKCNd+fl8RzhsXcDvvAEzkhGtlsbY=
github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg=
github.com/alecthomas/assert/v2 v2.0.3/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA=
github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35a3WghArZ/Hbebrjo=
github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM=
github.com/alecthomas/repr v0.1.1 h1:87P60cSmareLAxMc4Hro0r2RBY4ROm0dYwkJNpS4pPs=
github.com/alecthomas/repr v0.1.1/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go v1.43.43 h1:1L06qzQvl4aC3Skfh5rV7xVhGHjIZoHcqy16NoyQ1o4=
github.com/aws/aws-sdk-go v1.43.43/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/bradleyfalzon/ghinstallation v1.1.1 h1:pmBXkxgM1WeF8QYvDLT5kuQiHMcmf+X015GI0KM/E3I=
github.com/bradleyfalzon/ghinstallation v1.1.1/go.mod h1:vyCmHTciHx/uuyN82Zc3rXN3X2KTK8nUTCrTMwAhcug=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA=
github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk=
github.com/cosiner/argv v0.1.1-0.20200416041250-86e3c689263e h1:1m6Zv6jGsCUFFFSHiAt9yHzKFjdEZNQepMAaxYPAxSM=
github.com/cosiner/argv v0.1.1-0.20200416041250-86e3c689263e/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM=
github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U=
github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
github.com/elliotchance/orderedmap v1.5.0 h1:1IsExUsjv5XNBD3ZdC7jkAAqLWOOKdbPTmkHx63OsBg=
github.com/elliotchance/orderedmap v1.5.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0=
github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-yaml v1.9.5 h1:Eh/+3uk9kLxG4koCX6lRMAPS1OaMSAi+FJcya0INdB0=
github.com/goccy/go-yaml v1.9.5/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
github.com/google/go-github/v29 v29.0.3 h1:IktKCTwU//aFHnpA+2SLIi7Oo9uhAzgsdZNbcAqhgdc=
github.com/google/go-github/v29 v29.0.3/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.11.0 h1:9V9PWXEsWnPpQhu/PeQIkS4eGzMlTLGgt80cUUI8Ki4=
github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI=
github.com/goware/prefixer v0.0.0-20160118172347-395022866408 h1:Y9iQJfEqnN3/Nce9cOegemcy/9Ai5k3huT6E80F3zaw=
github.com/goware/prefixer v0.0.0-20160118172347-395022866408/go.mod h1:PE1ycukgRPJ7bJ9a1fdfQ9j8i/cEcRAoLZzbxYpNB/s=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2 h1:p4AKXPPS24tO8Wc8i1gLvSKdmkiSY5xuju57czJ/IJQ=
github.com/hashicorp/go-secure-stdlib/mlock v0.1.2/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3 h1:geBw3SBrxQq+buvbf4K+Qltv1gjaXJxy8asD4CjGYow=
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.3/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/vault/api v1.5.0 h1:Bp6yc2bn7CWkOrVIzFT/Qurzx528bdavF3nz590eu28=
github.com/hashicorp/vault/api v1.5.0/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM=
github.com/hashicorp/vault/sdk v0.4.1 h1:3SaHOJY687jY1fnB61PtL0cOkKItphrbLmux7T92HBo=
github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J+x6AzmKuVM/JWCQwkWm6GW/MUR6I=
github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef h1:A9HsByNhogrvm9cWb28sjiS3i7tcKCkflWFEkHfuAgM=
github.com/howeyc/gopass v0.0.0-20210920133722-c8aef6fb66ef/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI=
github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-zglob v0.0.6 h1:mP8RnmCgho4oaUYDIDn6GNxYk+qJGUs8fJLn+twYj2A=
github.com/mattn/go-zglob v0.0.6/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
github.com/mikefarah/yq/v4 v4.28.2 h1:IfDSee7jPvI54Y2NPmH+N+qMDpj/hIejTOFHJPGifYs=
github.com/mikefarah/yq/v4 v4.28.2/go.mod h1:uGbXrTtjrzH6oNE30tkVBowl7p6LOx3f2hUOqJe98Yk=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nwaples/rardecode v1.0.0 h1:r7vGuS5akxOnR4JQSkko62RJ1ReCMXxQRPtxsiFMBOs=
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8=
github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc=
github.com/ory/dockertest v3.3.5+incompatible h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4=
github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
github.com/shurcooL/githubv4 v0.0.0-20231126234147-1cffa1f02456 h1:6dExqsYngGEiixqa1vmtlUd+zbyISilg0Cf3GWVdeYM=
github.com/shurcooL/githubv4 v0.0.0-20231126234147-1cffa1f02456/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8=
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY=
github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M=
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/writeas/go-strip-markdown v2.0.1+incompatible h1:IIqxTM5Jr7RzhigcL6FkrCNfXkvbR+Nbu1ls48pXYcw=
github.com/writeas/go-strip-markdown v2.0.1+incompatible/go.mod h1:Rsyu10ZhbEK9pXdk8V6MVnZmTzRG0alMNLMwa0J01fE=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/ybbus/httpretry v1.0.2 h1:QIU8dfSF+kZx5xO1bUcLKyxYNEUsLX/hsN6gN6Up1So=
github.com/ybbus/httpretry v1.0.2/go.mod h1:fwOEa1URVFYikEqgQLCBtLyExFt5danZrxF5xF2qZh8=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zoumo/goset v0.2.0 h1:mflvfwZfKiayxR8/7fFBhvWHzhXU+aVP2nOzTEKVTfU=
github.com/zoumo/goset v0.2.0/go.mod h1:9N4gYaiVAbD/SytgmvFUlacbp1lSItmws1xNdzVslH4=
go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a h1:N7VD+PwpJME2ZfQT8+ejxwA4Ow10IkGbU0MGf94ll8k=
go.mozilla.org/gopgagent v0.0.0-20170926210634-4d7ea76ff71a/go.mod h1:YDKUvO0b//78PaaEro6CAPH6NqohCmL2Cwju5XI2HoE=
go.mozilla.org/sops/v3 v3.7.3 h1:CYx02LnWTATWv6NqWJIt4JCKVKSnGV+MsRiDpvwWQhg=
go.mozilla.org/sops/v3 v3.7.3/go.mod h1:AutdccISG5Nt/faUigaKPU9aGmhyZuCyUiSx5YCa1O8=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.126.0 h1:q4GJq+cAdMAC7XP7njvQ4tvohGLiSlytuL4BQxbIZ+o=
google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q=
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5 h1:eSaPbMR4T7WfH9FvABk36NBMacoTUKdWCvV0dx+KfOg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230803162519-f966b187b2e5/go.mod h1:zBEcrKX2ZOcEkHWxBPAIvYUWOKKMIhYcmNiUIu2ji3I=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.57.1 h1:upNTNqv0ES+2ZOOqACwVtS3Il8M12/+Hz41RCPzAjQg=
google.golang.org/grpc v1.57.1/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4=
gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473/go.mod h1:N1eN2tsCx0Ydtgjl4cqmbRCsY4/+z4cYDeqwZTk6zog=
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
================================================
FILE: internal/git/config.go
================================================
package git
import (
"fmt"
"os"
"path/filepath"
"strings"
configformat "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/mitchellh/go-homedir"
)
// ConfigValue returns the "best" value for the given configuration key.
// It respects the "git config" algorithm to search for a value:
// - first, the local git repository based on the working directory
// - then the global git config, either in $HOME/.gitconfig or $XDG_CONFIG_HOME/git/config or $HOME/.config/git/config
// - and finally the system git config, from /etc/gitconfig
// If not found, it will return an empty string.
// The key syntax is the same as used in the "git config" cmdline: a dot-separated path of elements.
// For example: `user.name` or `remote.origin.url`.
func ConfigValue(key string) string {
// local $PWD/.git/config
// or any .git directory in the upper hierarchy
gitDir, err := findGitDirectory()
if err == nil {
if value := getConfigValue(filepath.Join(gitDir, "config"), key); len(value) > 0 {
return value
}
}
// global $HOME/.gitconfig
homeDir, err := homedir.Dir()
if err == nil {
if value := getConfigValue(filepath.Join(homeDir, ".gitconfig"), key); len(value) > 0 {
return value
}
}
// global $XDG_CONFIG_HOME/git/config
if value := getConfigValue(filepath.Join(os.Getenv("XDG_CONFIG_HOME"), "git", "config"), key); len(value) > 0 {
return value
}
// global $HOME/.config/git/config
if len(homeDir) > 0 {
if value := getConfigValue(filepath.Join(homeDir, ".config", "git", "config"), key); len(value) > 0 {
return value
}
}
// system /etc/gitconfig
if value := getConfigValue("/etc/gitconfig", key); len(value) > 0 {
return value
}
return ""
}
// CurrentRepositoryURL returns the URL of the current git repository, based on the "origin" remote URL.
// If no repository could be found (from the current working directory), or if there is no "origin" remote
// configured, it will return an empty string.
func CurrentRepositoryURL() string {
gitDir, err := findGitDirectory()
if err != nil {
return ""
}
repoURL := getConfigValue(filepath.Join(gitDir, "config"), "remote.origin.url")
return normaliseRepositeURL(repoURL)
}
func normaliseRepositeURL(url string) string {
if strings.HasPrefix(url, "git@") {
url = strings.Replace(url, ":", "/", 1)
url = strings.Replace(url, "git@", "https://", 1)
}
url = strings.TrimSuffix(url, ".git")
return url
}
// getConfigValue returns the value associated with the given key in the given git config file path.
// The key syntax is the same as used in the "git config" cmdline: a dot-separated path of elements.
// For example: `user.name` or `remote.origin.url`.
// In case of error or if no value could be found, it will just return an empty string.
func getConfigValue(configFilePath string, key string) string {
file, err := os.Open(configFilePath)
if err != nil {
return ""
}
defer file.Close()
cfg := configformat.New()
if err = configformat.NewDecoder(file).Decode(cfg); err != nil {
return ""
}
keyElems := strings.Split(key, ".")
if len(keyElems) < 2 {
return ""
}
section := cfg.Section(keyElems[0])
if section == nil {
return ""
}
switch len(keyElems) {
case 2:
return section.Option(keyElems[1])
case 3:
subSection := section.Subsection(keyElems[1])
if subSection == nil {
return ""
}
return subSection.Option(keyElems[2])
default:
return ""
}
}
// findGitDirectory returns the path of the local ".git" directory, based on the working directory.
// It starts at the working directory, and walks up the filesystem hierarchy until it finds a valid ".git" directory.
// If it can't retrieve the working directory, and can't find a ".git" directory it will return an error.
func findGitDirectory() (string, error) {
wd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("failed to get current working directory: %w", err)
}
dir := wd
for {
fi, _ := os.Stat(filepath.Join(dir, ".git", "config"))
if fi != nil && !fi.IsDir() {
return filepath.Join(dir, ".git"), nil
}
if len(dir) == 0 || (len(dir) == 1 && os.IsPathSeparator(dir[0])) {
return "", fmt.Errorf("failed to find a .git directory starting from %s", wd)
}
dir = strings.TrimSuffix(dir, string(os.PathSeparator))
dir = filepath.Dir(dir)
}
}
================================================
FILE: internal/git/config_test.go
================================================
package git
import (
"os"
"path/filepath"
"testing"
"github.com/otiai10/copy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// note that this test can't be run in parallel, because it needs to change the working directory
func TestFindGitDirectory(t *testing.T) {
baseDir, err := os.Getwd()
require.NoError(t, err, "failed to get the current working directory")
defer os.Chdir(baseDir) //nolint: errcheck // don't care in the tests...
// copy the "git" dir to ".git", because otherwise it's a pain to commit a .git dir ;-)
err = copy.Copy(
filepath.Join(baseDir, "testdata", "dir-with-git-config", "git"),
filepath.Join(baseDir, "testdata", "dir-with-git-config", ".git"),
)
require.NoError(t, err, "failed to copy the .git directory")
// create the empty directory
emptyDirectoryPath := filepath.Join(baseDir, "testdata", "empty-dir")
err = os.MkdirAll(emptyDirectoryPath, 0755)
require.NoErrorf(t, err, "failed to create an empty directory at %s", emptyDirectoryPath)
tests := []struct {
name string
workingDir string
gitDir string
}{
{
name: "dir with git config",
workingDir: filepath.Join(baseDir, "testdata", "dir-with-git-config"),
gitDir: filepath.Join(baseDir, "testdata", "dir-with-git-config", ".git"),
},
{
name: "empty dir walks up to project's git directory",
workingDir: emptyDirectoryPath,
gitDir: filepath.Join(baseDir, "..", "..", ".git"),
},
}
for _, test := range tests {
err = os.Chdir(test.workingDir)
require.NoErrorf(t, err, "failed to switch current directory to %s", test.workingDir)
t.Run(test.name, func(t *testing.T) {
gitDir, err := findGitDirectory()
require.NoError(t, err)
assert.Equal(t, test.gitDir, gitDir)
})
}
}
func TestNormaliseRepositeURL(t *testing.T) {
t.Parallel()
tests := []struct {
name string
input string
expected string
}{
{
name: "ssh url",
input: "git@github.com:dailymotion-oss/octopilot.git",
expected: "https://github.com/dailymotion-oss/octopilot",
},
{
name: "https url",
input: "https://github.com/dailymotion-oss/octopilot",
expected: "https://github.com/dailymotion-oss/octopilot",
},
{
name: "ghe ssh url",
input: "git@github.example.com:dailymotion-oss/octopilot.git",
expected: "https://github.example.com/dailymotion-oss/octopilot",
},
{
name: "ghe https url",
input: "https://github.example.com/dailymotion-oss/octopilot",
expected: "https://github.example.com/dailymotion-oss/octopilot",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
actual := normaliseRepositeURL(test.input)
assert.Equal(t, test.expected, actual)
})
}
}
// note that this test can't be run in parallel, because it needs to change the working directory
func TestCurrentRepositoryURL(t *testing.T) {
baseDir, err := os.Getwd()
require.NoError(t, err, "failed to get the current working directory")
defer os.Chdir(baseDir) //nolint: errcheck // don't care in the tests...
gitDir := filepath.Join(baseDir, "testdata", "dir-with-git-config")
err = os.Chdir(gitDir)
require.NoErrorf(t, err, "failed to switch current directory to %s", gitDir)
repoURL := CurrentRepositoryURL()
assert.Equal(t, "https://github.com/dailymotion-oss/octopilot", repoURL)
}
================================================
FILE: internal/git/doc.go
================================================
// Package git provides helper functions to work with Git repository - and mainly its configuration.
package git
================================================
FILE: internal/git/testdata/dir-with-git-config/git/config
================================================
[remote "origin"]
url = git@github.com:dailymotion-oss/octopilot.git
fetch = +refs/heads/*:refs/remotes/origin/*
================================================
FILE: internal/glob/glob.go
================================================
package glob
import (
"errors"
"os"
"path/filepath"
"github.com/mattn/go-zglob"
)
// ExpandGlobPattern expands a glob pattern in the specified repository path.
// It reproduces similar error characteristics as filepath.Glob().
// Supports recursive glob patterns using **
func ExpandGlobPattern(repoPath, filePathPattern string) ([]string, error) {
filePaths, err := zglob.Glob(filepath.Join(repoPath, filePathPattern))
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return []string{}, nil
}
return nil, err
}
return filePaths, nil
}
================================================
FILE: internal/glob/glob_test.go
================================================
package glob
import (
"path/filepath"
"testing"
)
func generateTestCases(testdataDir string) map[string]map[string]bool {
return map[string]map[string]bool{
"**/data.txt": {
filepath.Join(testdataDir, "data.txt"): true,
filepath.Join(testdataDir, "subdirectory1/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/test/data.txt"): true,
},
"**/*/data.txt": {
filepath.Join(testdataDir, "subdirectory1/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/test/data.txt"): true,
},
"*/**/data.txt": {
filepath.Join(testdataDir, "subdirectory1/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/data.txt"): true,
filepath.Join(testdataDir, "subdirectory2/test/data.txt"): true,
},
"*/data.txt": {
filepath.Join(testdataDir, "subdirectory2/data.txt"): true,
filepath.Join(testdataDir, "subdirectory1/data.txt"): true,
},
"subdirectory1/data.txt": {
filepath.Join(testdataDir, "subdirectory1/data.txt"): true,
},
"*.txt": {
filepath.Join(testdataDir, "data.txt"): true,
},
"non_existent_directory/data.txt": {},
"non_existent_file.txt": {},
}
}
func TestExpandGlobPatternWithPatterns(t *testing.T) {
testdataDir := "testdata"
testCases := generateTestCases(testdataDir)
for pattern, expectedPaths := range testCases {
filePaths, err := ExpandGlobPattern(testdataDir, pattern)
if err != nil {
t.Errorf("Error expanding glob pattern %s: %v", pattern, err)
continue
}
actualPathsMap := make(map[string]bool)
for _, path := range filePaths {
if !expectedPaths[path] {
t.Errorf("Expected path %s not to exist for pattern %s, but it does", path, pattern)
}
actualPathsMap[path] = true
}
for expectedPath := range expectedPaths {
if !actualPathsMap[expectedPath] {
t.Errorf("Expected path %s to exist for pattern %s, but it does not", expectedPath, pattern)
}
}
}
}
================================================
FILE: internal/glob/testdata/data.txt
================================================
some content
================================================
FILE: internal/glob/testdata/subdirectory1/data.txt
================================================
some content
================================================
FILE: internal/glob/testdata/subdirectory2/data.txt
================================================
some content
================================================
FILE: internal/glob/testdata/subdirectory2/test/data.txt
================================================
some content
================================================
FILE: internal/parameters/doc.go
================================================
// Package parameters provides functions to work with "parameters": key-value maps.
package parameters
================================================
FILE: internal/parameters/parameters.go
================================================
package parameters
import (
"strings"
)
// Parse parses a string representation of parameters, and return a key-value map.
// The string representation is a comma-separated list of key=value elements.
// For example: "key1=value1,key2=value2"
func Parse(paramsStr string) map[string]string {
params := make(map[string]string)
for _, param := range strings.Split(paramsStr, ",") {
kv := strings.SplitN(param, "=", 2)
if len(kv) == 2 {
key := kv[0]
value := kv[1]
if strings.HasPrefix(value, `'`) && strings.HasSuffix(value, `'`) {
value = value[1 : len(value)-1]
}
if strings.HasPrefix(value, `"`) && strings.HasSuffix(value, `"`) {
value = value[1 : len(value)-1]
}
params[key] = value
}
}
return params
}
================================================
FILE: internal/parameters/parameters_test.go
================================================
package parameters
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParse(t *testing.T) {
t.Parallel()
tests := []struct {
name string
paramsStr string
expected map[string]string
}{
{
name: "empty input",
paramsStr: "",
expected: map[string]string{},
},
{
name: "invalid input",
paramsStr: "whatever",
expected: map[string]string{},
},
{
name: "single simple param",
paramsStr: "key=value",
expected: map[string]string{
"key": "value",
},
},
{
name: "multiple simple params",
paramsStr: "key=value,other-key=some-value,another-key=whatever value",
expected: map[string]string{
"key": "value",
"other-key": "some-value",
"another-key": "whatever value",
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual := Parse(test.paramsStr)
assert.Equal(t, test.expected, actual)
})
}
}
================================================
FILE: internal/yaml/yaml.go
================================================
// Package yaml provides functions to work with YAML content
package yaml
import (
"bufio"
"errors"
"io"
"regexp"
"strings"
)
// ExtractLeadingContentForYQ extracts the leading content (comment, frontmatter, ...) of a YAML file, for the YQ lib
// It is copied from the `processReadStream` func in the yq lib (because it's not public)
// It is a workaround for go-yaml to persist header content
func ExtractLeadingContentForYQ(input io.Reader) (io.Reader, string, error) {
var (
commentLineRegEx = regexp.MustCompile(`^\s*#`)
reader = bufio.NewReader(input)
sb strings.Builder
)
for {
peekBytes, err := reader.Peek(3)
if errors.Is(err, io.EOF) {
// EOF are handled else where..
return reader, sb.String(), nil
} else if err != nil {
return reader, sb.String(), err
} else if string(peekBytes) == "---" {
_, err := reader.ReadString('\n')
sb.WriteString("$yqDocSeperator$\n")
if errors.Is(err, io.EOF) {
return reader, sb.String(), nil
} else if err != nil {
return reader, sb.String(), err
}
} else if commentLineRegEx.MatchString(string(peekBytes)) {
line, err := reader.ReadString('\n')
sb.WriteString(line)
if errors.Is(err, io.EOF) {
return reader, sb.String(), nil
} else if err != nil {
return reader, sb.String(), err
}
} else {
return reader, sb.String(), nil
}
}
}
================================================
FILE: internal/yaml/yaml_test.go
================================================
package yaml
import (
"io"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestExtractLeadingContentForYQ(t *testing.T) {
t.Parallel()
const (
yqDocSeparatorPrefix = "$yqDocSeperator$\n"
)
tests := []struct {
name string
input string
expected string
expectedLeadingContent string
expectedErrorMsg string
}{
{
name: "empty input",
input: "",
},
{
name: "no leading content",
input: "key: value",
expected: "key: value",
},
{
name: "top level comments",
input: `# top level comment
# on multiple lines
key: value
object:
key: value`,
expected: `
key: value
object:
key: value`,
expectedLeadingContent: `# top level comment
# on multiple lines
`,
},
{
name: "doc separator and top level comments",
input: `---
# top level comment
# on multiple lines
key: value`,
expected: `
key: value`,
expectedLeadingContent: yqDocSeparatorPrefix + `# top level comment
# on multiple lines
`,
},
{
name: "doc separator",
input: `---
key: value`,
expected: `key: value`,
expectedLeadingContent: yqDocSeparatorPrefix,
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, actualLeadingContent, err := ExtractLeadingContentForYQ(strings.NewReader(test.input))
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
} else {
require.NoError(t, err)
assert.Equal(t, test.expectedLeadingContent, actualLeadingContent)
actualBytes, err := io.ReadAll(actual)
require.NoError(t, err)
assert.Equal(t, test.expected, string(actualBytes))
}
})
}
}
================================================
FILE: main.go
================================================
package main
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"github.com/dailymotion-oss/octopilot/internal/git"
"github.com/dailymotion-oss/octopilot/repository"
"github.com/dailymotion-oss/octopilot/update"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
)
// the following build-related variables are set at release-time by goreleaser
// using ldflags
var (
buildVersion = "dev"
buildCommit = "none"
buildDate = "unknown"
)
var options struct {
updates []string
repos []string
repository.UpdateOptions
logLevel string
failOnError bool
maxConcurrentRepos int
outputResults string
}
func init() {
// defaults
options.GitHub.PullRequest.Merge.BranchProtection = repository.BranchProtectionKindStatusChecks
// required flags
pflag.StringArrayVarP(&options.updates, "update", "u", nil, `An update operation, such as "yaml(file=config.yaml,path='version')=file(path=VERSION)" - see the online documentation for all available updaters.`)
assert(pflag.CommandLine.SetAnnotation("update", "mandatory", []string{"true"}))
pflag.StringArrayVarP(&options.repos, "repo", "r", nil, `A repository to update, defined either statically in the form "org/repo", or dynamically with the "discover-from" prefix - see the online documentation for more details.`)
assert(pflag.CommandLine.SetAnnotation("repo", "mandatory", []string{"true"}))
pflag.StringVar(&options.GitHub.AuthMethod, "github-auth-method", "token", `Mandatory GitHub authentication method: either "token" or "app" - see the online documentation for more details.`)
assert(pflag.CommandLine.SetAnnotation("github-auth-method", "mandatory", []string{"true"}))
// GitHub auth flags
pflag.StringVar(&options.GitHub.Token, "github-token", os.Getenv("GITHUB_TOKEN"), `This is the GitHub token - required when the GitHub auth method is "token". Default to the GITHUB_TOKEN env var.`)
pflag.Int64Var(&options.GitHub.AppID, "github-app-id", int64(getenvInt("GITHUB_APP_ID")), `This is the GitHub AppID - required when the GitHub auth method is "app". Default to the GITHUB_APP_ID env var.`)
pflag.Int64Var(&options.GitHub.InstallationID, "github-installation-id", int64(getenvInt("GITHUB_INSTALLATION_ID")), "For the `app` GitHub auth method, contains the GitHubApp Installation ID. Default to the GITHUB_INSTALLATION_ID env var.")
pflag.StringVar(&options.GitHub.PrivateKey, "github-privatekey", os.Getenv("GITHUB_PRIVATEKEY"), "For the `app` GitHub auth method, contains the GitHubApp Private key file in PEM format. Default to the GITHUB_PRIVATEKEY env var.")
pflag.StringVar(&options.GitHub.PrivateKeyPath, "github-privatekey-path", os.Getenv("GITHUB_PRIVATEKEY_PATH"), "For the `app` GitHub auth method, contains the GitHubApp Private key file path `/some/key.pem` (used if the github-privatekey is empty). Default to the GITHUB_PRIVATEKEY_PATH env var.")
pflag.StringVar(&options.GitHub.URL, "github-url", repository.PublicGithubURL, `GitHub server URL`)
// pull-request flags
pflag.StringVar(&options.GitHub.PullRequest.Title, "pr-title", "", "The title of the Pull Request to create. Default to the commit title.")
pflag.StringVar(&options.GitHub.PullRequest.TitleUpdateOperation, "pr-title-update-operation", "", `The type of operation when updating the PR's title: "ignore" (keep old value), "replace", "prepend" or "append". Default is: "ignore" for "append" strategy, "replace" for "reset" strategy, and not applicable for "recreate" strategy.`)
pflag.StringVar(&options.GitHub.PullRequest.Body, "pr-body", "", "The body of the Pull Request to create. Default to the commit body and the commit footer.")
pflag.StringVar(&options.GitHub.PullRequest.BodyUpdateOperation, "pr-body-update-operation", "", `The type of operation when updating the PR's body: "ignore" (keep old value), "replace", "prepend" or "append". Default is: "ignore" for "append" strategy, "replace" for "reset" strategy, and not applicable for "recreate" strategy.`)
pflag.StringArrayVar(&options.GitHub.PullRequest.Comments, "pr-comment", []string{}, "List of comments to add to the Pull Request.")
pflag.StringSliceVar(&options.GitHub.PullRequest.Assignees, "pr-assignees", []string{}, "List of users to assign PR to.")
pflag.StringSliceVar(&options.GitHub.PullRequest.Reviewers, "pr-reviewers", []string{}, "List of users to request a review from.")
pflag.StringSliceVar(&options.GitHub.PullRequest.TeamReviewers, "pr-team-reviewers", []string{}, "List of teams to request a review from.")
pflag.StringSliceVar(&options.GitHub.PullRequest.Labels, "pr-labels", []string{"octopilot-update"}, "List of labels set on the pull requests, and used to find existing pull requests to update.")
pflag.StringVar(&options.GitHub.PullRequest.BaseBranch, "pr-base-branch", "", "Name of the branch used as a base when creating pull requests. If empty, the branch used will be the one referenced by the HEAD of each cloned repository.")
pflag.BoolVar(&options.GitHub.PullRequest.Draft, "pr-draft", false, `Create "draft" Pull Requests, instead of regular ones. It means that the PRs can't be merged until marked as "ready for review".`)
pflag.BoolVar(&options.GitHub.PullRequest.Merge.Enabled, "pr-merge", false, `Merge the Pull Requests created. It will wait until the PRs are "mergeable" before merging them.`)
pflag.BoolVar(&options.GitHub.PullRequest.Merge.Auto, "pr-merge-auto", false, "If pr-merge is enabled, then merge the PR using Github's auto-merge feature. Note, this must also be enabled in the repository settings manually for it to work.")
pflag.BoolVar(&options.GitHub.PullRequest.Merge.AutoWait, "pr-merge-auto-wait", false, "If pr-merge & pr-merge-auto is enabled, then wait until the PR is actually merged by Github. By default, it will happen asynchronously in the background.")
pflag.StringVar(&options.GitHub.PullRequest.Merge.Method, "pr-merge-method", "merge", `If pr-merge is enabled, the PRs will be merged with this method. Can be either "merge", "squash", or "rebase".`)
pflag.StringVar(&options.GitHub.PullRequest.Merge.CommitTitle, "pr-merge-commit-title", "", "If pr-merge is enabled, this is the optional title of the merge commit.")
pflag.StringVar(&options.GitHub.PullRequest.Merge.CommitMessage, "pr-merge-commit-message", "", "If pr-merge is enabled, this is the optional body of the merge commit.")
pflag.StringVar(&options.GitHub.PullRequest.Merge.SHA, "pr-merge-sha", "", "If pr-merge is enabled, this is the optional SHA that pull request head must match to allow merge.")
pflag.DurationVar(&options.GitHub.PullRequest.Merge.PollTimeout, "pr-merge-poll-timeout", 10*time.Minute, "If pr-merge is enabled, this is the maximum duration to wait for a Pull Request to be mergeable/merged.")
pflag.DurationVar(&options.GitHub.PullRequest.Merge.PollInterval, "pr-merge-poll-interval", 30*time.Second, "If pr-merge is enabled, this is the duration to wait for between each GitHub API call to check if a PR is mergeable/merged.")
pflag.IntVar(&options.GitHub.PullRequest.Merge.RetryCount, "pr-merge-retry-count", 3, "If pr-merge is enabled, this is the number of times to retry the merge operation in case of merge failure.")
pflag.Var(&options.GitHub.PullRequest.Merge.BranchProtection, "pr-merge-branch-protection", `If pr-merge is enabled, then wait for the specified kind of branch protection rules to be satisfied before attempting to merge. "statusChecks" waits only for status checks to be passing. "all" waits for every rule (approvals, commit signature, etc). "bypass" will bypass branch protection rules when possible.`)
// git-related flags
pflag.StringVar(&options.UpdateOptions.Git.CloneDir, "git-clone-dir", temporaryDirectory(), "Directory used to clone the repositories.")
pflag.StringArrayVar(&options.UpdateOptions.Git.StagePatterns, "git-stage-pattern", nil, "List of path patterns that will be added to the git index and committed.")
pflag.BoolVar(&options.UpdateOptions.Git.StageAllChanged, "git-stage-all-changed", true, "Commit all files changed.")
pflag.BoolVar(&options.UpdateOptions.Git.RecurseSubmodules, "git-recurse-submodules", false, "Recursively initialize all submodules.")
pflag.StringVar(&options.UpdateOptions.Git.AuthorName, "git-author-name", firstNonEmpyValue(os.Getenv("GIT_AUTHOR_NAME"), git.ConfigValue("user.name")), `Name of the author of the git commit. Default to the GIT_AUTHOR_NAME env var, or the "user.name" git config value.`)
pflag.StringVar(&options.UpdateOptions.Git.AuthorEmail, "git-author-email", firstNonEmpyValue(os.Getenv("GIT_AUTHOR_EMAIL"), git.ConfigValue("user.email")), `Email of the author of the git commit. Default to the GIT_AUTHOR_EMAIL env var, or the "user.email" git config value.`)
pflag.StringVar(&options.UpdateOptions.Git.CommitterName, "git-committer-name", firstNonEmpyValue(os.Getenv("GIT_COMMITTER_NAME"), git.ConfigValue("user.name")), `Name of the committer. Default to the GIT_COMMITTER_NAME env var, or the "user.name" git config value.`)
pflag.StringVar(&options.UpdateOptions.Git.CommitterEmail, "git-committer-email", firstNonEmpyValue(os.Getenv("GIT_COMMITTER_EMAIL"), git.ConfigValue("user.email")), `Email of the committer. Default to the GIT_COMMITTER_EMAIL env var, or the "user.email" git config value.`)
pflag.StringVar(&options.UpdateOptions.Git.CommitTitle, "git-commit-title", "", "Title of the git commit.")
pflag.StringVar(&options.UpdateOptions.Git.CommitBody, "git-commit-body", "", "Body of the git commit.")
pflag.StringVar(&options.UpdateOptions.Git.CommitFooter, "git-commit-footer", defaultCommitFooter(), "Footer of the git commit.")
pflag.StringVar(&options.UpdateOptions.Git.BranchPrefix, "git-branch-prefix", "octopilot-", "Prefix of the new branch to create.")
pflag.StringVar(&options.UpdateOptions.Git.SigningKeyPath, "git-signing-key-path", os.Getenv("GIT_SIGNING_KEY_PATH"), "Path to the private key file to sign commits or tags (e.g. `/some/key.pgp`). Default to the GIT_SIGNING_KEY_PATH env var.")
pflag.StringVar(&options.UpdateOptions.Git.SigningKeyPassphrase, "git-signing-key-passphrase", os.Getenv("GIT_SIGNING_KEY_PASSPHRASE"), "Passphrase to decrypt the signing key. Default to the GIT_SIGNING_KEY_PASSPHRASE env var.")
pflag.StringVar(&options.Strategy, "strategy", "reset", `Strategy to use when creating/updating the Pull Requests: either "reset" (reset any existing PR from the current base branch), "append" (append new commit to any existing PR) or "recreate" (always create a new PR).`)
pflag.BoolVar(&options.KeepFiles, "keep-files", false, "Keep the cloned repositories on disk. If false, the files will be deleted at the end of the process.")
pflag.BoolVarP(&options.DryRun, "dry-run", "n", false, `Don't perform any operation on the remote git repository: all operations will be done in the local cloned repository. You should also set the "--keep-files" flag to keep the files and inspect the changes in the local repository.`)
pflag.StringVar(&options.logLevel, "log-level", "info", "Log level. Supported values: trace, debug, info, warning, error, fatal, panic.")
pflag.BoolVar(&options.failOnError, "fail-on-error", false, "Exit with error code 1 if any repository update fails.")
pflag.IntVar(&options.maxConcurrentRepos, "max-concurrent-repos", 0, "Maximum number of repositories to handle in parallel. Default to unlimited")
pflag.StringVar(&options.outputResults, "output-results", "", "Optional file to write JSON encoded execution results to. This may be useful to other tools for further processing.")
pflag.BoolP("help", "h", false, "Display this help message.")
pflag.Bool("version", false, "Display the version and exit.")
// usage
pflag.Usage = func() {
fmt.Fprintf(os.Stderr, "Octopilot v%s - Documentation at https://dailymotion-oss.github.io/octopilot/v%s/\n", buildVersion, buildVersion)
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0])
pflag.PrintDefaults()
}
}
func main() {
ctx := context.Background()
pflag.Parse()
printHelpOrVersion()
setLogLevel()
checkMandatoryFlags()
logrus.WithField("updates", options.updates).Trace("Parsing updates")
updaters, err := update.Parse(options.updates)
if err != nil {
logrus.
WithError(err).
WithField("updates", options.updates).
Fatal("Failed to parse updates")
}
logrus.WithField("updaters", updaters).Debug("Updaters ready")
logrus.WithField("repos", options.repos).Trace("Parsing repositories")
repositories, err := repository.Parse(ctx, options.repos, options.GitHub)
if err != nil {
logrus.
WithError(err).
WithField("repos", options.repos).
Fatal("Failed to parse repos")
}
logrus.WithField("repositories", repositories).Debug("Repositories ready")
logrus.WithField("repositories-count", len(repositories)).Trace("Starting updates")
var wg sync.WaitGroup
results := make(chan repository.RepoUpdateResult, len(repositories))
var workers chan struct{}
if options.maxConcurrentRepos > 0 {
workers = make(chan struct{}, options.maxConcurrentRepos)
}
for _, repo := range repositories {
wg.Add(1)
if workers != nil {
workers <- struct{}{}
}
go func(repo repository.Repository) {
defer func() {
if workers != nil {
<-workers
}
wg.Done()
}()
logrus.WithField("repository", repo.FullName()).Trace("Starting repository update")
updated, pr, err := repo.Update(ctx, updaters, options.UpdateOptions)
result := repository.RepoUpdateResult{
Owner: repo.Owner,
Repo: repo.Name,
IsUpdated: updated,
}
if err != nil {
errMsg := err.Error()
result.Error = &errMsg
}
if pr != nil {
result.PullRequest = &repository.PullRequestResult{
Number: pr.GetNumber(),
NodeID: pr.GetNodeID(),
URL: pr.GetHTMLURL(),
}
}
results <- result
if err != nil {
logrus.
WithError(err).
WithField("repository", repo.FullName()).
Error("Repository update failed")
return
}
if !updated {
logrus.WithField("repository", repo.FullName()).Warn("Repository update has no changes")
return
}
logrus.WithField("repository", repo.FullName()).Info("Repository update finished")
}(repo)
}
wg.Wait()
close(results)
logrus.WithField("repositories-count", len(repositories)).Info("Updates finished")
updatedPRURLs, notUpdatedPRURLs, resultFile, hadError := processResults(results)
logUpdatesSummary(updatedPRURLs, notUpdatedPRURLs)
if options.outputResults != "" {
err := writeResults(&resultFile, options.outputResults)
if err != nil {
logrus.Fatalf("Failed to write results: %s", err)
}
}
if options.failOnError && hadError {
logrus.Fatal("Some repository updates failed")
}
}
func processResults(results chan repository.RepoUpdateResult) (updatedPRURLs []string, notUpdatedPRURLs []string, resultFile repository.ResultFile, hadError bool) {
for r := range results {
if r.PullRequest != nil && r.PullRequest.URL != "" {
if r.IsUpdated {
updatedPRURLs = append(updatedPRURLs, r.PullRequest.URL)
} else {
notUpdatedPRURLs = append(notUpdatedPRURLs, r.PullRequest.URL)
}
}
resultFile.Repos = append(resultFile.Repos, r)
if r.Error != nil {
hadError = true
}
}
return updatedPRURLs, notUpdatedPRURLs, resultFile, hadError
}
func logUpdatesSummary(updatedPRURLs, notUpdatedPRURLs []string) {
if len(notUpdatedPRURLs) > 0 {
logrus.WithField("unrevised-repository-count", len(notUpdatedPRURLs)).Info("Update summary (Unrevised)")
for _, url := range notUpdatedPRURLs {
logrus.WithField("unrevised-repository-pr-url", url).Info("Update summary (Unrevised)")
}
}
if len(updatedPRURLs) > 0 {
logrus.WithField("updated-repository-count", len(updatedPRURLs)).Info("Update summary (Updated)")
for _, url := range updatedPRURLs {
logrus.WithField("updated-repository-pr-url", url).Info("Update summary (Updated)")
}
}
}
func writeResults(results *repository.ResultFile, file string) error {
jsonBytes, err := json.MarshalIndent(results, "", " ")
if err != nil {
return fmt.Errorf("failed to marshall results: %w", err)
}
return os.WriteFile(file, jsonBytes, 0644)
}
func checkMandatoryFlags() {
var missingFlags []string
pflag.CommandLine.VisitAll(func(flag *pflag.Flag) {
if mandatory, found := flag.Annotations["mandatory"]; found {
for _, v := range mandatory {
if isMandatory, _ := strconv.ParseBool(v); isMandatory {
switch flag.Value.Type() {
case "string":
if len(flag.Value.String()) == 0 {
missingFlags = append(missingFlags, flag.Name)
}
case "stringSlice":
if flag.Value.String() == "[]" {
missingFlags = append(missingFlags, flag.Name)
}
}
}
}
}
})
if len(missingFlags) == 0 {
return
}
logrus.WithField("missing-flags", missingFlags).Fatal("Mandatory fields not defined")
}
func setLogLevel() {
level, err := logrus.ParseLevel(options.logLevel)
if err != nil {
logrus.
WithError(err).
WithField("log-level", options.logLevel).
Fatal("Invalid log level")
}
logrus.SetLevel(level)
}
func printHelpOrVersion() {
if printHelp, _ := pflag.CommandLine.GetBool("help"); printHelp {
fmt.Printf("Octopilot version %v, commit %v, built at %v\n", buildVersion, buildCommit, buildDate)
pflag.Usage()
os.Exit(0)
}
if printVersion, _ := pflag.CommandLine.GetBool("version"); printVersion {
fmt.Printf("version %v, commit %v, built at %v", buildVersion, buildCommit, buildDate)
os.Exit(0)
}
}
func temporaryDirectory() string {
dir, err := os.MkdirTemp("", "octopilot")
if err != nil {
dir = filepath.Join(os.TempDir(), "octopilot")
}
return dir
}
func defaultCommitFooter() string {
footer := new(strings.Builder)
footer.WriteString("Generated by [Octopilot](https://github.com/dailymotion-oss/octopilot)")
if buildVersion == "dev" {
footer.WriteString(" (dev version)")
} else {
footer.WriteString(fmt.Sprintf(" [v%[1]s](https://github.com/dailymotion-oss/octopilot/releases/tag/v%[1]s)", buildVersion))
}
if repoURL := git.CurrentRepositoryURL(); len(repoURL) > 0 {
footer.WriteString(fmt.Sprintf(" from %s", repoURL))
} else if currentDir, err := os.Getwd(); err == nil {
dirName := filepath.Base(currentDir)
footer.WriteString(fmt.Sprintf(" from %s", dirName))
}
return footer.String()
}
func firstNonEmpyValue(values ...string) string {
for _, value := range values {
if len(value) > 0 {
return value
}
}
return ""
}
func assert(err error) {
if err != nil {
panic(err)
}
}
func getenvInt(key string) int {
s := os.Getenv(key)
if s != "" {
v, err := strconv.Atoi(s)
assert(err)
return v
}
return 0
}
================================================
FILE: repository/commit.go
================================================
package repository
import (
"strings"
)
type CommitMessage struct {
Headline string
Body string
}
func (c CommitMessage) String() string {
commitMsg := new(strings.Builder)
commitMsg.WriteString(c.Headline)
if len(c.Body) > 0 {
commitMsg.WriteString("\n\n")
commitMsg.WriteString(c.Body)
}
return commitMsg.String()
}
func NewCommitMessage(title, body, footer string) CommitMessage {
bodyWithFooter := new(strings.Builder)
if len(body) > 0 {
bodyWithFooter.WriteString(body)
}
if len(footer) > 0 {
if bodyWithFooter.Len() > 0 {
bodyWithFooter.WriteString("\n\n")
}
bodyWithFooter.WriteString("-- \n")
bodyWithFooter.WriteString(footer)
}
return CommitMessage{
Headline: title,
Body: bodyWithFooter.String(),
}
}
type CommitFileChanges struct {
Upserted []string
Deleted []string
}
================================================
FILE: repository/commit_test.go
================================================
package repository
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestString(t *testing.T) {
t.Parallel()
tests := []struct {
name string
title string
body string
footer string
expected string
}{
{
name: "No content",
expected: "",
},
{
name: "Only title",
title: "title",
expected: "title",
},
{
name: "Title and body",
title: "title",
body: "body\nbody",
expected: "title\n\nbody\nbody",
},
{
name: "Title and footer",
title: "title",
footer: "footer\nfooter",
expected: "title\n\n-- \nfooter\nfooter",
},
{
name: "Title body and footer",
title: "title",
body: "body\nbody",
footer: "footer\nfooter",
expected: "title\n\nbody\nbody\n\n-- \nfooter\nfooter",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
commitMessage := NewCommitMessage(test.title, test.body, test.footer)
actual := commitMessage.String()
assert.Equal(t, test.expected, actual)
})
}
}
================================================
FILE: repository/discover_from_env.go
================================================
package repository
import (
"context"
"fmt"
"os"
"strings"
"github.com/imdario/mergo"
)
func discoverRepositoriesFromEnvironment(ctx context.Context, envVar string, params map[string]string, githubOpts GitHubOptions) ([]Repository, error) {
separator := params["sep"]
if len(separator) == 0 {
separator = " "
}
delete(params, "sep")
envValue := os.Getenv(envVar)
repoNames := strings.Split(envValue, separator)
if len(repoNames) == 0 {
return nil, nil
}
if len(repoNames) == 1 && len(repoNames[0]) == 0 {
return nil, nil
}
repos, err := Parse(ctx, repoNames, githubOpts)
if err != nil {
return nil, fmt.Errorf("failed to parse %v: %w", repoNames, err)
}
for i := range repos {
err = mergo.Merge(&repos[i].Params, params)
if err != nil {
return nil, fmt.Errorf("failed to merge params for repo %v: %w", repos[i], err)
}
}
return repos, nil
}
================================================
FILE: repository/discover_from_env_test.go
================================================
package repository
import (
"context"
"fmt"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestDiscoverRepositoriesFromEnvironment(t *testing.T) {
t.Parallel()
tests := []struct {
name string
envVarValue string
params map[string]string
expected []Repository
expectedErrorMsg string
}{
{
name: "empty input",
},
{
name: "invalid input",
envVarValue: "whatever",
expectedErrorMsg: "failed to parse [whatever]: invalid syntax for whatever: found 0 matches instead of 4: []",
},
{
name: "single repository without parameters",
envVarValue: "dailymotion-oss/octopilot",
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{},
},
},
},
{
name: "multiple repositories without parameters",
envVarValue: "dailymotion-oss/octopilot some-owner/MyGreatRepo",
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{},
},
},
},
{
name: "multiple repositories with custom separator",
envVarValue: "dailymotion-oss/octopilot|some-owner/MyGreatRepo",
params: map[string]string{
"sep": "|",
},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{},
},
},
},
{
name: "single repository with a single parameter",
envVarValue: "dailymotion-oss/octopilot(draft=true)",
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"draft": "true",
},
},
},
},
{
name: "multiple repositories with multiple parameters",
envVarValue: "dailymotion-oss/octopilot(draft=true,merge=true) some-owner/MyGreatRepo(merge=false)",
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"draft": "true",
"merge": "true",
},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{
"merge": "false",
},
},
},
},
{
name: "multiple repositories with multiple parameters with overrides",
envVarValue: "dailymotion-oss/octopilot(draft=true,merge=false) some-owner/MyGreatRepo(draft=true)",
params: map[string]string{
"merge": "true",
},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"draft": "true",
"merge": "false",
},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{
"draft": "true",
"merge": "true",
},
},
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
envVar := fmt.Sprintf("DISCOVER_FROM_ENV_%v", i)
os.Setenv(envVar, test.envVarValue)
defer os.Unsetenv(envVar)
actual, err := discoverRepositoriesFromEnvironment(context.Background(), envVar, test.params, GitHubOptions{})
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Empty(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
================================================
FILE: repository/discover_from_query.go
================================================
package repository
import (
"context"
"fmt"
"github.com/google/go-github/v57/github"
)
func discoverRepositoriesFromQuery(ctx context.Context, searchType SearchType, query string, params map[string]string, githubOpts GitHubOptions) ([]Repository, error) {
var pageRepos []Repository
var repos []Repository
var resp *github.Response
ghClient, _, err := githubClient(ctx, githubOpts)
if err != nil {
return nil, fmt.Errorf("failed to create github client: %w", err)
}
page := 1
for {
opts := &github.SearchOptions{
ListOptions: github.ListOptions{
Page: page,
PerPage: 100,
},
}
if searchType == Code {
pageRepos, resp, err = searchCodeRepositories(ctx, ghClient, query, opts, params)
} else {
pageRepos, resp, err = searchRepositories(ctx, ghClient, query, opts, params)
}
if err != nil {
return nil, fmt.Errorf("failed to list all repositories matching query %s on GitHub (page %d): %w", query, page, err)
}
repos = append(repos, pageRepos...)
page = resp.NextPage
if resp.NextPage == 0 {
break
}
}
return repos, nil
}
================================================
FILE: repository/git.go
================================================
package repository
import (
"bytes"
"context"
"errors"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/google/go-github/v57/github"
"github.com/shurcooL/githubv4"
"github.com/sirupsen/logrus"
)
func cloneGitRepository(ctx context.Context, repo Repository, localPath string, options UpdateOptions) (*git.Repository, error) {
gitURL, err := url.JoinPath(options.GitHub.URL, repo.GitFullName())
if err != nil {
// likely the Url passed is malformed
return nil, fmt.Errorf("invalid github url format: %w", err)
}
branch := "HEAD"
if b, ok := repo.Params["branch"]; ok && strings.TrimSpace(b) != "" {
branch = fmt.Sprintf("refs/heads/%s", b)
}
referenceName := plumbing.ReferenceName(branch)
logrus.WithFields(logrus.Fields{
"git-url": gitURL,
"git-reference": referenceName.String(),
"local-path": localPath,
}).Trace("Cloning git repository")
_, token, err := githubClient(ctx, options.GitHub)
if err != nil {
return nil, fmt.Errorf("failed to create github client: %w", err)
}
gitRepo, err := git.PlainCloneContext(ctx, localPath, false, &git.CloneOptions{
ReferenceName: referenceName,
URL: gitURL,
Auth: &http.BasicAuth{
Username: "x-access-token", // For GitHub Apps, the username must be `x-access-token`. For Personal Tokens, it doesn't matter.
Password: token,
},
})
if err != nil {
return nil, fmt.Errorf("failed to clone git repository from %s to %s: %w", gitURL, localPath, err)
}
recurseSubmodules := git.NoRecurseSubmodules
if options.Git.RecurseSubmodules {
recurseSubmodules = git.DefaultSubmoduleRecursionDepth
}
githubURL, err := url.Parse(options.GitHub.URL)
if err != nil {
return nil, fmt.Errorf("failed to parse Github URL: %w", err)
}
err = initSubmodules(ctx, gitRepo, token, recurseSubmodules, githubURL)
if err != nil {
return nil, fmt.Errorf("failed to initialize submodules for git repository %s: %w", gitURL, err)
}
logrus.WithFields(logrus.Fields{
"git-url": gitURL,
"git-reference": referenceName.String(),
"local-path": localPath,
}).Debug("Git repository cloned")
return gitRepo, nil
}
func initSubmodules(ctx context.Context, repo *git.Repository, token string, recurseSubmodules git.SubmoduleRescursivity, githubURL *url.URL) error {
if recurseSubmodules == git.NoRecurseSubmodules {
return nil
}
recurseSubmodules--
wt, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to get worktree: %w", err)
}
subModules, err := wt.Submodules()
if err != nil {
return fmt.Errorf("failed to get submodules: %w", err)
}
for _, s := range subModules {
// Hack: rewrite Github hosted submodule SSH URLs to use HTTPS because token auth only works with that
// go-git does not expose a way of doing insteadOf type rewrites for submodules, so this will have to do for now
s.Config().URL = strings.Replace(s.Config().URL, fmt.Sprintf("git@%s:", githubURL.Hostname()), fmt.Sprintf("%s://%s/", githubURL.Scheme, githubURL.Hostname()), 1)
// Only use basic auth for Github. This lets us use any public Git repo not hosted on Github.
var auth transport.AuthMethod
if strings.HasPrefix(s.Config().URL, githubURL.String()) {
auth = &http.BasicAuth{
Username: "x-access-token",
Password: token,
}
} else {
auth = nil
}
logrus.WithFields(logrus.Fields{
"submodule-name": s.Config().Name,
"submodule-url": s.Config().URL,
"submodule-branch": s.Config().Branch,
"submodule-path": s.Config().Path,
}).Trace("Initializing submodule")
err = s.UpdateContext(ctx, &git.SubmoduleUpdateOptions{
Init: true,
Auth: auth,
})
if err != nil {
return fmt.Errorf("failed to initialize submodule: %w", err)
}
sRepo, err := s.Repository()
if err != nil {
return fmt.Errorf("failed to get submodule repo: %w", err)
}
err = initSubmodules(ctx, sRepo, token, recurseSubmodules, githubURL)
if err != nil {
return err
}
}
return nil
}
type createBranchOptions struct {
GitHubOpts GitHubOptions
Repository Repository
BranchName string
CommitSHA string
}
func createBranchWithAPI(ctx context.Context, opts createBranchOptions) error {
client, _, err := githubClient(ctx, opts.GitHubOpts)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
repository, _, err := client.Repositories.Get(ctx, opts.Repository.Owner, opts.Repository.Name)
if err != nil {
return fmt.Errorf("failed to fetch repository: %w", err)
}
gqlClient, err := githubGraphqlClient(ctx, opts.GitHubOpts)
if err != nil {
return fmt.Errorf("failed to create github GraphQL client: %w", err)
}
inputs := githubv4.CreateRefInput{
RepositoryID: githubv4.ID(repository.NodeID),
Name: githubv4.String(fmt.Sprintf("refs/heads/%s", opts.BranchName)),
Oid: githubv4.GitObjectID(opts.CommitSHA),
}
var mutation struct {
CreateRefInput struct {
ClientMutationID string
} `graphql:"createRef(input: $input)"`
}
err = gqlClient.Mutate(ctx, &mutation, inputs, nil)
if err != nil {
return fmt.Errorf("failed to create branch: %w", err)
}
return nil
}
type switchBranchOptions struct {
Repository Repository
BranchName string
CreateBranch bool
}
func switchBranch(_ context.Context, gitRepo *git.Repository, opts switchBranchOptions) error {
branchRefName := plumbing.NewBranchReferenceName(opts.BranchName)
if !opts.CreateBranch {
// for an existing branch, we need to create a local reference to the remote branch
remoteBranchRefName := plumbing.NewRemoteReferenceName("origin", opts.BranchName)
remoteBranchRef, err := gitRepo.Reference(remoteBranchRefName, true)
if err != nil {
return fmt.Errorf("failed to get the reference for %s: %w", remoteBranchRef, err)
}
branchRef := plumbing.NewHashReference(branchRefName, remoteBranchRef.Hash())
err = gitRepo.Storer.SetReference(branchRef)
if err != nil {
return fmt.Errorf("failed to store the reference for branch %s: %w", opts.BranchName, err)
}
}
workTree, err := gitRepo.Worktree()
if err != nil {
return fmt.Errorf("failed to open worktree: %w", err)
}
if err := workTree.Checkout(&git.CheckoutOptions{
Branch: branchRefName,
Create: opts.CreateBranch,
}); err != nil {
return fmt.Errorf("failed to checkout the branch %s: %w", opts.BranchName, err)
}
logrus.WithFields(logrus.Fields{
"repository": opts.Repository.FullName(),
"branch": opts.BranchName,
}).Debug("Switched Git branch")
return nil
}
func stageSubmodules(ctx context.Context, repo *git.Repository, opts *GitOptions) error {
workTree, err := repo.Worktree()
if err != nil {
return fmt.Errorf("failed to open worktree: %w", err)
}
index, err := repo.Storer.Index()
if err != nil {
return fmt.Errorf("failed to get the repo index: %w", err)
}
submodules, err := workTree.Submodules()
if err != nil {
return fmt.Errorf("failed to parse submodules: %w", err)
}
for _, s := range submodules {
status, err := s.Status()
if err != nil {
return fmt.Errorf("failed to get submodule %s status: %w", s.Config().Name, err)
}
if status.Current.IsZero() || status.IsClean() {
continue
}
path := s.Config().Path
shouldStage := opts.StageAllChanged
if !shouldStage {
for _, p := range opts.StagePatterns {
shouldStage, err = filepath.Match(p, path)
if err != nil {
return fmt.Errorf("failed to compare stage pattern %s to path %s: %w", p, path, err)
}
if shouldStage {
break
}
}
}
if !shouldStage {
continue
}
entry, err := index.Entry(path)
if err != nil {
return fmt.Errorf("failed to get submodule %s index entry: %w", s.Config().Name, err)
}
entry.Hash = status.Current
}
err = repo.Storer.SetIndex(index)
if err != nil {
return fmt.Errorf("failed to update index: %w", err)
}
// Reset submodules in the working tree to avoid them being considered by AddGlob or similar later on.
for _, s := range submodules {
status, err := s.Status()
if err != nil {
return fmt.Errorf("failed to get submodule %s status: %w", s.Config().Name, err)
}
if status.Current.IsZero() {
continue
}
err = s.UpdateContext(ctx, &git.SubmoduleUpdateOptions{Init: false, NoFetch: true, RecurseSubmodules: git.NoRecurseSubmodules})
if err != nil {
return fmt.Errorf("failed to update submodule %s: %w", s.Config().Name, err)
}
}
return nil
}
type commitOptions struct {
Repository Repository
CommitMessage CommitMessage
GitOpts GitOptions
}
func commitChanges(ctx context.Context, gitRepo *git.Repository, opts commitOptions) (bool, error) {
workTree, err := gitRepo.Worktree()
if err != nil {
return false, fmt.Errorf("failed to open worktree: %w", err)
}
status, err := workTree.Status()
if err != nil {
return false, fmt.Errorf("failed to get the worktree status: %w", err)
}
if status.IsClean() {
return false, nil
}
logrus.WithFields(logrus.Fields{
"repository": opts.Repository.FullName(),
"status": status.String(),
}).Debug("Git status")
err = stageSubmodules(ctx, gitRepo, &opts.GitOpts)
if err != nil {
return false, fmt.Errorf("failed to stage submodules: %w", err)
}
for _, pattern := range opts.GitOpts.StagePatterns {
err = workTree.AddGlob(pattern)
if err != nil {
return false, fmt.Errorf("failed to stage files using pattern %s: %w", pattern, err)
}
}
signingKey, err := parseSigningKey(opts.GitOpts.SigningKeyPath, opts.GitOpts.SigningKeyPassphrase)
if err != nil {
return false, err
}
now := time.Now()
commit, err := workTree.Commit(opts.CommitMessage.String(),
&git.CommitOptions{
All: opts.GitOpts.StageAllChanged,
Author: &object.Signature{
Name: opts.GitOpts.AuthorName,
Email: opts.GitOpts.AuthorEmail,
When: now,
},
Committer: &object.Signature{
Name: opts.GitOpts.CommitterName,
Email: opts.GitOpts.CommitterEmail,
When: now,
},
SignKey: signingKey,
},
)
if err != nil {
return false, fmt.Errorf("failed to commit: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": opts.Repository.FullName(),
"commit": commit.String(),
}).Debug("Git commit")
return true, nil
}
func parseSigningKey(signingKeyPath, signingKeyPassphrase string) (*openpgp.Entity, error) {
if signingKeyPath == "" {
return nil, nil
}
b, err := os.ReadFile(signingKeyPath)
if err != nil {
return nil, fmt.Errorf("failed to read signing key file %q: %w", signingKeyPath, err)
}
el, err := openpgp.ReadArmoredKeyRing(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to read signing key file content: %w", err)
}
signingKey := el[0]
if signingKeyPassphrase != "" {
if err := signingKey.PrivateKey.Decrypt([]byte(signingKeyPassphrase)); err != nil {
return nil, fmt.Errorf("failed to decrypt signing key: %w", err)
}
} else if signingKey.PrivateKey.Encrypted {
return nil, errors.New("signing key is encrypted, please provide a passphrase")
}
return signingKey, nil
}
func getLatestCommit(_ context.Context, gitRepo *git.Repository) (*object.Commit, error) {
headCommitRef, err := gitRepo.Head()
if err != nil {
return nil, fmt.Errorf("failed to fetch head: %w", err)
}
latestCommit, err := gitRepo.CommitObject(headCommitRef.Hash())
if err != nil {
return nil, fmt.Errorf("failed to fetch commit: %w", err)
}
return latestCommit, nil
}
func buildDiffTreeEntries(ctx context.Context, base, head *object.Commit) ([]*github.TreeEntry, error) {
parentTree, err := base.Tree()
if err != nil {
return nil, fmt.Errorf("failed to get base commit tree: %w", err)
}
commitTree, err := head.Tree()
if err != nil {
return nil, fmt.Errorf("failed to get head commit tree: %w", err)
}
treeDiff, err := parentTree.DiffContext(ctx, commitTree)
if err != nil {
return nil, fmt.Errorf("failed to compare commit trees: %w", err)
}
treeEntries := []*github.TreeEntry{}
for _, c := range treeDiff {
var path, mode, treeType, sha, content *string
var entry object.ChangeEntry
switch c.To.TreeEntry.Mode {
case filemode.Empty:
entry = c.From
case filemode.Dir, filemode.Submodule:
entry = c.To
sha = ptr(entry.TreeEntry.Hash.String())
default:
entry = c.To
file, err := c.To.Tree.TreeEntryFile(&entry.TreeEntry)
if err != nil {
return nil, fmt.Errorf("failed to get tree entry file: %w", err)
}
s, err := file.Contents()
if err != nil {
return nil, fmt.Errorf("failed to read tree entry contents: %w", err)
}
content = ptr(s)
}
path = ptr(entry.Name)
treeType = ptr(treeEntryModeToTreeType(entry.TreeEntry.Mode))
mode = ptr(fmt.Sprintf("%06o", uint32(entry.TreeEntry.Mode)))
treeEntries = append(treeEntries, &github.TreeEntry{
Path: path,
Type: treeType,
Mode: mode,
SHA: sha,
Content: content,
})
}
return treeEntries, nil
}
func ptr[T any](v T) *T {
return &v
}
func treeEntryModeToTreeType(m filemode.FileMode) string {
switch m {
case filemode.Dir:
return "tree"
case filemode.Submodule:
return "commit"
default:
return "blob"
}
}
func pushChangesWithAPI(ctx context.Context, gitRepo *git.Repository, opts pushOptions) error {
commit, err := getLatestCommit(ctx, gitRepo)
if err != nil {
return fmt.Errorf("failed to fetch latest commit: %w", err)
}
parentCommit, err := commit.Parent(0)
if err != nil {
return fmt.Errorf("failed to fetch parent of latest commit: %w", err)
}
parentCommitSHA := parentCommit.Hash.String()
if opts.CreateBranch {
err = createBranchWithAPI(ctx, createBranchOptions{
GitHubOpts: opts.GitHubOpts,
Repository: opts.Repository,
BranchName: opts.BranchName,
CommitSHA: parentCommitSHA,
})
if err != nil {
return fmt.Errorf("failed to create branch: %w", err)
}
}
treeEntries, err := buildDiffTreeEntries(ctx, parentCommit, commit)
if err != nil {
return fmt.Errorf("failed to build a diff of tree entries: %w", err)
}
client, _, err := githubClient(ctx, opts.GitHubOpts)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
var treeSHA string
if len(treeEntries) > 0 {
tree, _, err := client.Git.CreateTree(ctx, opts.Repository.Owner, opts.Repository.Name, parentCommitSHA, treeEntries)
if err != nil {
return fmt.Errorf("failed to create tree: %w", err)
}
treeSHA = tree.GetSHA()
} else {
treeSHA = parentCommit.TreeHash.String()
}
newCommit, _, err := client.Git.CreateCommit(
ctx,
opts.Repository.Owner,
opts.Repository.Name,
&github.Commit{
Message: ptr(opts.CommitMessage.String()),
Tree: &github.Tree{SHA: ptr(treeSHA)},
Parents: []*github.Commit{&github.Commit{SHA: &parentCommitSHA}},
},
&github.CreateCommitOptions{},
)
if err != nil {
return fmt.Errorf("failed to create commit: %w", err)
}
_, _, err = client.Git.UpdateRef(
ctx,
opts.Repository.Owner,
opts.Repository.Name,
&github.Reference{
Ref: ptr(fmt.Sprintf("refs/heads/%s", opts.BranchName)),
Object: &github.GitObject{
SHA: newCommit.SHA,
},
},
opts.ResetFromBase,
)
if err != nil {
return fmt.Errorf("failed to update branch ref: %w", err)
}
return nil
}
func pushChangesWithGit(ctx context.Context, gitRepo *git.Repository, opts pushOptions) error {
refSpec := fmt.Sprintf("refs/heads/%[1]s:refs/heads/%[1]s", opts.BranchName)
if opts.ResetFromBase {
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
// The + tells Git to update the reference even if it isn’t a fast-forward.
refSpec = fmt.Sprintf("+%s", refSpec)
}
_, token, err := githubClient(ctx, opts.GitHubOpts)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": opts.Repository.FullName(),
"branch": opts.BranchName,
"force": opts.ResetFromBase,
}).Trace("Pushing git changes")
err = gitRepo.PushContext(ctx, &git.PushOptions{
RefSpecs: []config.RefSpec{
config.RefSpec(refSpec),
},
Auth: &http.BasicAuth{
Username: "x-access-token", // For GitHub Apps, the username must be `x-access-token`. For Personal Tokens, it doesn't matter.
Password: token,
},
})
if err != nil {
return fmt.Errorf("failed to push branch %s to %s: %w", opts.BranchName, opts.Repository.FullName(), err)
}
logrus.WithFields(logrus.Fields{
"repository": opts.Repository.FullName(),
"branch": opts.BranchName,
}).Debug("Git changes pushed")
return nil
}
type pushOptions struct {
GitHubOpts GitHubOptions
GitCloneDir string
Repository Repository
BranchName string
CreateBranch bool
ResetFromBase bool
CommitMessage CommitMessage
}
func pushChanges(ctx context.Context, gitRepo *git.Repository, opts pushOptions) error {
switch opts.GitHubOpts.AuthMethod {
case "token":
return pushChangesWithGit(ctx, gitRepo, opts)
case "app":
return pushChangesWithAPI(ctx, gitRepo, opts)
default:
return fmt.Errorf("GitHub auth method unrecognized (allowed values: app, token): %s", opts.GitHubOpts.AuthMethod)
}
}
================================================
FILE: repository/git_test.go
================================================
package repository
import (
"context"
"io"
"os"
"path/filepath"
"testing"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5"
"github.com/mholt/archiver"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestSwitchBranch(t *testing.T) {
t.Parallel()
tests := []struct {
name string
options switchBranchOptions
validateFunc func(*testing.T, *git.Repository)
}{
{
name: "create-new-branch",
options: switchBranchOptions{
BranchName: "new-branch",
CreateBranch: true,
},
validateFunc: func(t *testing.T, repo *git.Repository) {
t.Helper()
head, err := repo.Head()
require.NoError(t, err)
assert.Equal(t, "refs/heads/new-branch", head.Name().String())
workTree, err := repo.Worktree()
require.NoError(t, err)
f, err := workTree.Filesystem.Open("master-branch.txt")
require.NoError(t, err)
data, err := io.ReadAll(f)
require.NoError(t, err)
assert.Equal(t, "this is a file from the master branch\n", string(data))
},
},
{
name: "existing-branch",
options: switchBranchOptions{
BranchName: "update",
},
validateFunc: func(t *testing.T, repo *git.Repository) {
t.Helper()
head, err := repo.Head()
require.NoError(t, err)
assert.Equal(t, "refs/heads/update", head.Name().String())
workTree, err := repo.Worktree()
require.NoError(t, err)
f, err := workTree.Filesystem.Open("update-branch.txt")
require.NoError(t, err)
data, err := io.ReadAll(f)
require.NoError(t, err)
assert.Equal(t, "this is a file from the update branch\n", string(data))
},
},
}
// the git repo is stored as a tar.gz archive to make it easy to commit
gitRepoPath := filepath.Join("testdata", "switch-branch", "git-repo")
err := os.RemoveAll(gitRepoPath)
require.NoErrorf(t, err, "failed to delete %s", gitRepoPath)
err = archiver.Unarchive(filepath.Join("testdata", "switch-branch", "git-repo.tar.gz"), gitRepoPath)
require.NoErrorf(t, err, "failed to decompress git repository at %s", gitRepoPath)
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
// remove any previous testing data
err := os.RemoveAll(filepath.Join("testdata", "switch-branch", test.name))
require.NoError(t, err)
repo, err := git.PlainClone(filepath.Join("testdata", "switch-branch", test.name), false, &git.CloneOptions{
URL: gitRepoPath,
})
require.NoError(t, err)
head, err := repo.Head()
require.NoError(t, err)
assert.Equal(t, "refs/heads/master", head.Name().String())
err = switchBranch(context.Background(), repo, test.options)
require.NoError(t, err)
test.validateFunc(t, repo)
})
}
}
func TestParseSigningKey(t *testing.T) {
t.Parallel()
tests := []struct {
name string
signingKeyPath string
signingKeyPassphrase string
validateFunc func(*testing.T, *openpgp.Entity, error)
}{
{
name: "no-signing-key-path",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.Nil(t, signingKey)
assert.NoError(t, err)
},
},
{
name: "invalid-signing-key-path",
signingKeyPath: "testdata/parse-signing-key/unknown-dir/private-key.pgp",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.Nil(t, signingKey)
assert.Error(t, err)
},
},
{
name: "invalid-signing-key-format",
signingKeyPath: "testdata/parse-signing-key/invalid-format/private-key.pgp",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.Nil(t, signingKey)
assert.Error(t, err)
},
},
{
name: "valid-unencrypted",
signingKeyPath: "testdata/parse-signing-key/valid-unencrypted/private-key.pgp",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.NotNil(t, signingKey)
assert.NoError(t, err)
},
},
{
name: "valid-encrypted-without-passphrase",
signingKeyPath: "testdata/parse-signing-key/valid-encrypted/private-key.pgp",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.Nil(t, signingKey)
assert.Error(t, err)
},
},
{
name: "valid-encrypted-with-passphrase",
signingKeyPath: "testdata/parse-signing-key/valid-encrypted/private-key.pgp",
signingKeyPassphrase: "fake-passphrase",
validateFunc: func(t *testing.T, signingKey *openpgp.Entity, err error) {
t.Helper()
assert.NotNil(t, signingKey)
assert.NoError(t, err)
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
signingKey, err := parseSigningKey(test.signingKeyPath, test.signingKeyPassphrase)
test.validateFunc(t, signingKey, err)
})
}
}
================================================
FILE: repository/github_client.go
================================================
package repository
import (
"context"
"fmt"
"net/http"
"net/url"
"github.com/bradleyfalzon/ghinstallation"
"github.com/google/go-github/v57/github"
"github.com/shurcooL/githubv4"
"github.com/sirupsen/logrus"
"github.com/ybbus/httpretry"
"golang.org/x/oauth2"
)
func githubAuthenticatedHTTPClient(ctx context.Context, ghOptions GitHubOptions) (*http.Client, string, error) {
var (
httpClient *http.Client
token string
err error
)
logrus.Tracef("Creating github client using auth method %q", ghOptions.AuthMethod)
switch ghOptions.AuthMethod {
case "token":
httpClient, token, err = githubTokenClient(ctx, ghOptions.Token)
case "app":
httpClient, token, err = githubAppClient(ctx, ghOptions)
default:
return nil, "", fmt.Errorf("GitHub auth method unrecognized (allowed values: app, token): %s", ghOptions.AuthMethod)
}
if err != nil {
return nil, "", err
}
httpClient = httpretry.NewCustomClient(httpClient)
return httpClient, token, nil
}
func githubClient(ctx context.Context, ghOptions GitHubOptions) (*github.Client, string, error) {
httpClient, token, err := githubAuthenticatedHTTPClient(ctx, ghOptions)
if err != nil {
return nil, "", err
}
var ghc *github.Client
if ghOptions.isEnterprise() {
var err error
ghc, err = github.NewClient(httpClient).WithEnterpriseURLs(ghOptions.URL, ghOptions.URL)
if err != nil {
return nil, "", fmt.Errorf("failed to create an enterprise client: %w", err)
}
} else {
ghc = github.NewClient(httpClient)
}
return ghc, token, nil
}
type graphqlTransport struct {
base http.RoundTripper
}
func (t *graphqlTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// Enable PullRequest.mergeStateStatus
req.Header.Add("accept", "application/vnd.github.merge-info-preview+json")
return t.base.RoundTrip(req)
}
func githubGraphqlClient(ctx context.Context, ghOptions GitHubOptions) (*githubv4.Client, error) {
httpClient, _, err := githubAuthenticatedHTTPClient(ctx, ghOptions)
httpClient.Transport = &graphqlTransport{base: httpClient.Transport}
if err != nil {
return nil, err
}
if ghOptions.isEnterprise() {
apiURL, err := url.JoinPath(ghOptions.URL, "/api/graphql")
if err != nil {
return nil, fmt.Errorf("failed to build GraphQL API URL: %w", err)
}
return githubv4.NewEnterpriseClient(apiURL, httpClient), nil
}
return githubv4.NewClient(httpClient), nil
}
func githubTokenClient(ctx context.Context, token string) (*http.Client, string, error) { //nolint: unparam // the returned error is not used, but we need it for the method signature
tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token})
return oauth2.NewClient(ctx, tokenSource), token, nil
}
func githubAppClient(ctx context.Context, ghOptions GitHubOptions) (*http.Client, string, error) {
var (
tr = http.DefaultTransport
itr *ghinstallation.Transport
err error
)
if len(ghOptions.PrivateKey) > 0 {
itr, err = ghinstallation.New(tr, ghOptions.AppID, ghOptions.InstallationID, []byte(ghOptions.PrivateKey))
} else {
itr, err = ghinstallation.NewKeyFromFile(tr, ghOptions.AppID, ghOptions.InstallationID, ghOptions.PrivateKeyPath)
}
if err != nil {
return nil, "", err
}
if ghOptions.isEnterprise() {
itr.BaseURL = ghOptions.URL + "/api/v3"
}
token, err := itr.Token(ctx)
if err != nil {
return nil, "", err
}
return &http.Client{Transport: itr}, token, err
}
================================================
FILE: repository/options.go
================================================
package repository
import (
"errors"
"fmt"
"strings"
"time"
"github.com/dailymotion-oss/octopilot/update"
"github.com/go-git/go-git/v5"
)
// definition of the different kind of Pull Request update operations
const (
IgnoreUpdateOperation = "ignore"
ReplaceUpdateOperation = "replace"
PrependUpdateOperation = "prepend"
AppendUpdateOperation = "append"
PublicGithubURL = "https://github.com"
)
// UpdateOptions is the options entrypoint for a git repo update
type UpdateOptions struct {
DryRun bool
KeepFiles bool
Git GitOptions
GitHub GitHubOptions
Strategy string
}
// GitOptions holds all the options required to perform git operations: clone, commit, ...
type GitOptions struct {
CloneDir string
StagePatterns []string
StageAllChanged bool
AuthorName string
AuthorEmail string
CommitterName string
CommitterEmail string
CommitTitle string
CommitBody string
CommitFooter string
BranchPrefix string
SigningKeyPath string
SigningKeyPassphrase string
RecurseSubmodules bool
}
// GitHubOptions holds all the options required to perform github operations: auth, PRs, ...
type GitHubOptions struct {
URL string
AuthMethod string
Token string
AppID int64
InstallationID int64
PrivateKey string
PrivateKeyPath string
PullRequest PullRequestOptions
}
func (o *GitHubOptions) isEnterprise() bool {
return o.URL != PublicGithubURL
}
// PullRequestOptions holds all the options required to perform github PR operations: title/body, merge, ...
type PullRequestOptions struct {
Labels []string
BaseBranch string
Title string
TitleUpdateOperation string
Body string
BodyUpdateOperation string
Comments []string
Assignees []string
Reviewers []string
TeamReviewers []string
Draft bool
Merge PullRequestMergeOptions
}
// BranchProtectionKind enumerates possible branch protections to wait for before attempting a PR merge.
type BranchProtectionKind string
const (
// BranchProtectionKindStatusChecks waits for all required statues & checksuite runs to be passing ("success", "neutral", "skipped")
BranchProtectionKindStatusChecks BranchProtectionKind = "statusChecks"
// BranchProtectionKindAll wait for all protection rules
BranchProtectionKindAll BranchProtectionKind = "all"
// BranchProtectionKindBypass waits until the user can bypass branch protection rules
BranchProtectionKindBypass BranchProtectionKind = "bypass"
)
func (b *BranchProtectionKind) String() string {
return string(*b)
}
func (b *BranchProtectionKind) Set(s string) error {
switch s {
case string(BranchProtectionKindStatusChecks), string(BranchProtectionKindAll), string(BranchProtectionKindBypass):
*b = BranchProtectionKind(s)
return nil
default:
return errors.New("invalid value")
}
}
func (b *BranchProtectionKind) Type() string {
return strings.Join(
[]string{
string(BranchProtectionKindStatusChecks),
string(BranchProtectionKindAll),
string(BranchProtectionKindBypass),
},
"|",
)
}
// PullRequestMergeOptions holds all the options required to merge github PRs
type PullRequestMergeOptions struct {
Enabled bool
Auto bool
AutoWait bool
Method string
CommitTitle string
CommitMessage string
SHA string
PollInterval time.Duration
PollTimeout time.Duration
RetryCount int
BranchProtection BranchProtectionKind
}
func (o *GitOptions) setDefaultValues(updaters []update.Updater, tplExecutorFunc templateExecutor) error {
if len(updaters) == 1 {
title, body := updaters[0].Message()
if len(o.CommitTitle) == 0 {
o.CommitTitle = title
}
if len(o.CommitBody) == 0 {
o.CommitBody = body
}
}
if len(o.CommitTitle) == 0 {
o.CommitTitle = "Octopilot update"
}
if len(o.CommitBody) == 0 {
body := new(strings.Builder)
body.WriteString("Updates:")
for _, updater := range updaters {
updaterTitle, updaterBody := updater.Message()
body.WriteString("\n\n### ")
body.WriteString(updater.String())
body.WriteString("\n")
body.WriteString(updaterTitle)
body.WriteString("\n")
body.WriteString(updaterBody)
}
o.CommitBody = body.String()
}
commitTitle, err := tplExecutorFunc(o.CommitTitle)
if err != nil {
return fmt.Errorf("failed to run template for git commit title %s: %w", o.CommitTitle, err)
}
o.CommitTitle = commitTitle
commitBody, err := tplExecutorFunc(o.CommitBody)
if err != nil {
return fmt.Errorf("failed to run template for git commit body %s: %w", o.CommitBody, err)
}
o.CommitBody = commitBody
return nil
}
func (o *GitHubOptions) setDefaultValues(git GitOptions, tplExecutorFunc templateExecutor) error {
if len(o.PullRequest.Title) == 0 {
o.PullRequest.Title = git.CommitTitle
}
if len(o.PullRequest.Body) == 0 {
o.PullRequest.Body = git.CommitBody
}
if len(git.CommitFooter) > 0 {
o.PullRequest.Body += fmt.Sprintf("\n\n-- \n%s", git.CommitFooter)
}
prTitle, err := tplExecutorFunc(o.PullRequest.Title)
if err != nil {
return fmt.Errorf("failed to run template for pull reequest title %s: %w", o.PullRequest.Title, err)
}
o.PullRequest.Title = prTitle
prBody, err := tplExecutorFunc(o.PullRequest.Body)
if err != nil {
return fmt.Errorf("failed to run template for pull request body %s: %w", o.PullRequest.Body, err)
}
o.PullRequest.Body = prBody
prMergeCommitTitle, err := tplExecutorFunc(o.PullRequest.Merge.CommitTitle)
if err != nil {
return fmt.Errorf("failed to run template for pull request merge commit title %s: %w", o.PullRequest.Merge.CommitTitle, err)
}
o.PullRequest.Merge.CommitTitle = prMergeCommitTitle
prMergeCommitMessage, err := tplExecutorFunc(o.PullRequest.Merge.CommitMessage)
if err != nil {
return fmt.Errorf("failed to run template for pull request merge commit message %s: %w", o.PullRequest.Merge.CommitMessage, err)
}
o.PullRequest.Merge.CommitMessage = prMergeCommitMessage
return nil
}
func (o *GitHubOptions) setDefaultUpdateOperation(defaultUpdateOperation string) {
if len(o.PullRequest.TitleUpdateOperation) == 0 {
o.PullRequest.TitleUpdateOperation = defaultUpdateOperation
}
if len(o.PullRequest.BodyUpdateOperation) == 0 {
o.PullRequest.BodyUpdateOperation = defaultUpdateOperation
}
}
func (o *GitHubOptions) adjustOptionsFromGitRepository(gitRepo *git.Repository) error {
if len(o.PullRequest.BaseBranch) == 0 {
if gitRepo == nil {
return errors.New("failed to resolve repository branch referenced by HEAD: repository is null")
}
head, err := gitRepo.Head()
if err != nil {
return fmt.Errorf("failed to resolve repository branch referenced by HEAD: %w", err)
}
o.PullRequest.BaseBranch = head.Name().Short()
}
return nil
}
================================================
FILE: repository/options_test.go
================================================
package repository
import (
"fmt"
"os"
"path/filepath"
"testing"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/mholt/archiver"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func loadLocalRepository(repository string, destination string) (*git.Repository, error) {
var err error
gitRepoPath := filepath.Join("testdata", "head-resolution", repository)
err = os.RemoveAll(gitRepoPath)
if err != nil {
return nil, fmt.Errorf("failed to delete %s", gitRepoPath)
}
err = archiver.Unarchive(filepath.Join("testdata", "head-resolution", fmt.Sprintf("%s.tar.gz", repository)), gitRepoPath)
if err != nil {
return nil, fmt.Errorf("failed to decompress git repository at %s", gitRepoPath)
}
err = os.RemoveAll(filepath.Join("testdata", "head-resolution", destination))
if err != nil {
return nil, err
}
repo, err := git.PlainClone(filepath.Join("testdata", "head-resolution", destination), false, &git.CloneOptions{
URL: gitRepoPath,
})
return repo, err
}
func TestAdjustOptionsFromGitRepository(t *testing.T) {
t.Parallel()
tests := []struct {
name string
pullRequestBaseBranch string
repositoryLoader func(string) (*git.Repository, error)
validateFunc func(*testing.T, error, GitHubOptions)
}{
{
name: "explicit",
pullRequestBaseBranch: "master",
repositoryLoader: func(testName string) (*git.Repository, error) {
return loadLocalRepository("resolution-successful", testName)
},
validateFunc: func(t *testing.T, result error, options GitHubOptions) {
t.Helper()
require.NoError(t, result)
assert.Equal(t, "master", options.PullRequest.BaseBranch)
},
},
{
name: "resolved",
pullRequestBaseBranch: "",
repositoryLoader: func(testName string) (*git.Repository, error) {
return loadLocalRepository("resolution-successful", testName)
},
validateFunc: func(t *testing.T, result error, options GitHubOptions) {
t.Helper()
require.NoError(t, result)
assert.Equal(t, "main", options.PullRequest.BaseBranch)
},
},
{
name: "resolved-null-repository",
pullRequestBaseBranch: "",
repositoryLoader: func(testName string) (*git.Repository, error) {
return nil, nil
},
validateFunc: func(t *testing.T, result error, options GitHubOptions) {
t.Helper()
require.Error(t, result)
assert.Equal(t, "", options.PullRequest.BaseBranch)
},
},
{
name: "resolved-head-error",
pullRequestBaseBranch: "",
repositoryLoader: func(testName string) (*git.Repository, error) {
return git.Init(memory.NewStorage(), nil)
},
validateFunc: func(t *testing.T, result error, options GitHubOptions) {
t.Helper()
require.Error(t, result)
assert.Equal(t, "", options.PullRequest.BaseBranch)
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
repo, err := test.repositoryLoader(test.name)
require.NoError(t, err, "failed to load repository: %w", err)
options := GitHubOptions{
PullRequest: PullRequestOptions{
BaseBranch: test.pullRequestBaseBranch,
},
}
err = options.adjustOptionsFromGitRepository(repo)
test.validateFunc(t, err, options)
})
}
}
================================================
FILE: repository/pull_request.go
================================================
package repository
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
"github.com/google/go-github/v57/github"
"github.com/shurcooL/githubv4"
"github.com/sirupsen/logrus"
"github.com/zoumo/goset"
)
func (r Repository) findMatchingPullRequest(ctx context.Context, options GitHubOptions) (*github.PullRequest, error) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"labels": options.PullRequest.Labels,
}).Trace("Looking for existing Pull Requests")
client, _, err := githubClient(ctx, options)
if err != nil {
return nil, fmt.Errorf("failed to create github client: %w", err)
}
page := 1
for {
prs, resp, err := client.PullRequests.List(ctx, r.Owner, r.Name, &github.PullRequestListOptions{
Base: options.PullRequest.BaseBranch,
ListOptions: github.ListOptions{
Page: page,
PerPage: 100,
},
})
if err != nil {
return nil, fmt.Errorf("failed to list opened Pull Requests for repository %s: %w", r.FullName(), err)
}
for _, pr := range prs {
if prHasLabels(pr, options.PullRequest.Labels) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"labels": options.PullRequest.Labels,
"pull-request": pr.GetHTMLURL(),
}).Info("Found existing Pull Request")
return pr, nil
}
}
page = resp.NextPage
if resp.NextPage == 0 {
break
}
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"labels": options.PullRequest.Labels,
}).Debug("No existing Pull Request found")
return nil, nil
}
func (r Repository) createPullRequest(ctx context.Context, options GitHubOptions, branchName string) (*github.PullRequest, error) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Trace("Creating new Pull Request")
client, _, err := githubClient(ctx, options)
if err != nil {
return nil, fmt.Errorf("failed to create github client: %w", err)
}
pr, _, err := client.PullRequests.Create(ctx, r.Owner, r.Name, &github.NewPullRequest{
Title: github.String(options.PullRequest.Title),
Base: github.String(options.PullRequest.BaseBranch),
Head: github.String(branchName),
Body: github.String(options.PullRequest.Body),
MaintainerCanModify: github.Bool(true),
Draft: github.Bool(options.PullRequest.Draft),
})
if err != nil {
return nil, fmt.Errorf("failed to create a new Pull Request for repository %s: %w", r.FullName(), err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Info("New Pull Request created")
err = r.enrichPullRequestWithContextualData(ctx, options, pr)
if err != nil {
return nil, fmt.Errorf("failed to enrich the Pull Request %s: %w", pr.GetHTMLURL(), err)
}
return pr, nil
}
func (r Repository) updatePullRequest(ctx context.Context, options GitHubOptions, pr *github.PullRequest) (*github.PullRequest, error) {
var needUpdate bool
client, _, err := githubClient(ctx, options)
if err != nil {
return nil, fmt.Errorf("failed to create github client: %w", err)
}
if len(options.PullRequest.Title) > 0 {
switch options.PullRequest.TitleUpdateOperation {
case IgnoreUpdateOperation:
// nothing to do
case ReplaceUpdateOperation:
pr.Title = github.String(options.PullRequest.Title)
needUpdate = true
case PrependUpdateOperation:
pr.Title = github.String(fmt.Sprintf("%s %s", options.PullRequest.Title, pr.GetTitle()))
needUpdate = true
case AppendUpdateOperation:
pr.Title = github.String(fmt.Sprintf("%s %s", pr.GetTitle(), options.PullRequest.Title))
needUpdate = true
}
}
if len(options.PullRequest.Body) > 0 {
switch options.PullRequest.BodyUpdateOperation {
case IgnoreUpdateOperation:
// nothing to do
case ReplaceUpdateOperation:
pr.Body = github.String(options.PullRequest.Body)
needUpdate = true
case PrependUpdateOperation:
pr.Body = github.String(fmt.Sprintf("%s\n\n%s", options.PullRequest.Body, pr.GetBody()))
needUpdate = true
case AppendUpdateOperation:
pr.Body = github.String(fmt.Sprintf("%s\n\n%s", pr.GetBody(), options.PullRequest.Body))
needUpdate = true
}
}
if needUpdate {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Updating existing Pull Request")
prURL := pr.GetHTMLURL()
pr, _, err = client.PullRequests.Edit(ctx, r.Owner, r.Name, pr.GetNumber(), pr)
if err != nil {
return nil, fmt.Errorf("failed to update Pull Request %s: %w", prURL, err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Info("Pull Request updated")
} else {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("No need to update the Pull Request")
}
err = r.enrichPullRequestWithContextualData(ctx, options, pr)
if err != nil {
return nil, fmt.Errorf("failed to enrich the Pull Request %s: %w", pr.GetHTMLURL(), err)
}
return pr, nil
}
func (r Repository) ensurePullRequestLabels(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
if prHasLabels(pr, options.PullRequest.Labels) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("No labels to add to the Pull Request")
return nil
}
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Adding labels to Pull Request")
_, _, err = client.Issues.AddLabelsToIssue(ctx, r.Owner, r.Name, pr.GetNumber(), options.PullRequest.Labels)
if err != nil {
return fmt.Errorf("failed to add labels %v on PR %s: %w", options.PullRequest.Labels, pr.GetHTMLURL(), err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("Labels added to Pull Request")
return nil
}
func (r Repository) addPullRequestComments(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
if len(options.PullRequest.Comments) == 0 {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("No comments to add to the Pull Request")
return nil
}
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
for i, comment := range options.PullRequest.Comments {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"comment": i,
}).Trace("Adding a comment to the Pull Request")
_, _, err := client.Issues.CreateComment(ctx, r.Owner, r.Name, pr.GetNumber(), &github.IssueComment{
Body: github.String(comment),
})
if err != nil {
return fmt.Errorf("failed to add comment %v on PR %s: %w", github.String(comment), pr.GetHTMLURL(), err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"comment": i,
}).Debug("Comment added to the Pull Request")
if len(options.PullRequest.Comments) > 1 && i < len(options.PullRequest.Comments)-1 {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"comment": i,
}).Trace("Sleeping a little before adding next comment, for rate limiting...")
time.Sleep(500 * time.Millisecond)
}
}
return nil
}
func (r Repository) addPullRequestAssignees(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
if len(options.PullRequest.Assignees) == 0 {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("No assignees to add to the Pull Request")
return nil
}
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"assignees": options.PullRequest.Assignees,
}).Trace("Adding assignees to the Pull Request")
_, _, err = client.Issues.AddAssignees(ctx, r.Owner, r.Name, pr.GetNumber(), options.PullRequest.Assignees)
if err != nil {
return fmt.Errorf("failed to add assignees %v on PR %s: %w", options.PullRequest.Assignees, pr.GetHTMLURL(), err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"assignees": options.PullRequest.Assignees,
}).Debug("Assignees added to the Pull Request")
return nil
}
func (r Repository) addPullRequestReviewers(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
if len(options.PullRequest.Reviewers) == 0 && len(options.PullRequest.TeamReviewers) == 0 {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("No reviewers to add to the Pull Request")
return nil
}
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"reviewers": options.PullRequest.Reviewers,
"team-reviewers": options.PullRequest.TeamReviewers,
}).Trace("Adding reviewers to the Pull Request")
reviewers := github.ReviewersRequest{
Reviewers: options.PullRequest.Reviewers,
TeamReviewers: options.PullRequest.TeamReviewers,
}
_, _, err = client.PullRequests.RequestReviewers(ctx, r.Owner, r.Name, pr.GetNumber(), reviewers)
if err != nil {
return fmt.Errorf("failed to add reviewers to PR %s: %w", pr.GetHTMLURL(), err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"reviewers": options.PullRequest.Reviewers,
"team-reviewers": options.PullRequest.TeamReviewers,
}).Debug("Reviewers added to the Pull Request")
return nil
}
func (r Repository) enrichPullRequestWithContextualData(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
var err error
err = r.ensurePullRequestLabels(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to ensure that Pull Request %s has the right labels: %w", pr.GetHTMLURL(), err)
}
err = r.addPullRequestComments(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to add comments to Pull Request %s: %w", pr.GetHTMLURL(), err)
}
err = r.addPullRequestAssignees(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to add assignees to Pull Request %s: %w", pr.GetHTMLURL(), err)
}
err = r.addPullRequestReviewers(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to add reviewers for Pull Request %s: %w", pr.GetHTMLURL(), err)
}
return nil
}
func (r Repository) mergePullRequest(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
if options.PullRequest.Merge.Auto {
return r.mergePullRequestUsingAutoMerge(ctx, options, pr)
}
return r.mergePullRequestUsingClient(ctx, options, pr, 0)
}
func (r Repository) mergePullRequestUsingAutoMerge(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
prURL := pr.GetHTMLURL()
mergeStrategy := "auto-merge"
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
gqlClient, err := githubGraphqlClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github GraphQL client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"timeout": options.PullRequest.Merge.PollTimeout.String(),
"merge-strategy": mergeStrategy,
}).Trace("Starting Pull Request merge process")
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Trace("Getting Pull Request status")
pr, _, err = client.PullRequests.Get(ctx, r.Owner, r.Name, pr.GetNumber())
if err != nil {
return fmt.Errorf("failed to retrieve status of Pull Request %s: %w", prURL, err)
}
if pr.GetMerged() {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Info("Pull Request is already merged")
return nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Trace("Enabling auto-merge for Pull Request")
var mutation struct {
EnablePullPullRequestAutoMergeInput struct {
ClientMutationID string
} `graphql:"enablePullRequestAutoMerge(input: $input)"`
}
var mergeMethod githubv4.PullRequestMergeMethod
switch strings.ToLower(options.PullRequest.Merge.Method) {
case "merge":
mergeMethod = githubv4.PullRequestMergeMethodMerge
case "squash":
mergeMethod = githubv4.PullRequestMergeMethodSquash
case "rebase":
mergeMethod = githubv4.PullRequestMergeMethodRebase
default:
mergeMethod = githubv4.PullRequestMergeMethodMerge
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Warnf(
"Unknown Pull Request merge method %v. Falling back to 'merge'",
options.PullRequest.Merge.Method,
)
}
var expectedHeadOid *githubv4.GitObjectID
if options.PullRequest.Merge.SHA != "" {
expectedHeadOid = githubv4.NewGitObjectID(githubv4.GitObjectID(options.PullRequest.Merge.SHA))
}
var commitHeadLine *githubv4.String
if options.PullRequest.Merge.CommitTitle != "" {
commitHeadLine = githubv4.NewString(githubv4.String(options.PullRequest.Merge.CommitTitle))
}
var commitBody *githubv4.String
if options.PullRequest.Merge.CommitMessage != "" {
commitBody = githubv4.NewString(githubv4.String(options.PullRequest.Merge.CommitMessage))
}
inputs := githubv4.EnablePullRequestAutoMergeInput{
PullRequestID: pr.NodeID,
MergeMethod: &mergeMethod,
ExpectedHeadOid: expectedHeadOid,
CommitHeadline: commitHeadLine,
CommitBody: commitBody,
}
attempted := 0
for {
err = gqlClient.Mutate(ctx, &mutation, inputs, nil)
attempted++
if err == nil {
break
}
if attempted > options.PullRequest.Merge.RetryCount {
return fmt.Errorf("failed to enable auto-merge for Pull Request: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"attempted": attempted,
"merge-strategy": mergeStrategy,
}).WithError(err).Warning("Failed to enable auto-merge for Pull Request - will retry")
time.Sleep(options.PullRequest.Merge.PollInterval)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Debug("Enabled auto-merge for Pull Request")
if !options.PullRequest.Merge.AutoWait {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Debugf("Not waiting until Pull Request %s is merged.", prURL)
return nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).Debug("Waiting for Pull Request to be merged")
err = r.waitUntilPullRequestIsMerged(ctx, options, pr)
if err == nil {
return nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"merge-strategy": mergeStrategy,
}).WithError(err).Warning("Timed out waiting for PR to be auto merged. Disabling auto-merge.")
err = r.disableAutoMerge(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to disable auto-merge for PR %s: %w", prURL, err)
}
return nil
}
func (r Repository) disableAutoMerge(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
gqlClient, err := githubGraphqlClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github GraphQL client: %w", err)
}
var mutation struct {
DisablePullRequestAutoMergeInput struct {
ClientMutationID string
} `graphql:"disablePullRequestAutoMerge(input: $input)"`
}
inputs := githubv4.DisablePullRequestAutoMergeInput{
PullRequestID: pr.NodeID,
}
err = gqlClient.Mutate(ctx, &mutation, inputs, nil)
if err != nil {
return fmt.Errorf("GraphQL mutation failed: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("PR auto-merge disabled")
return nil
}
func (r Repository) mergePullRequestUsingClient(ctx context.Context, options GitHubOptions, pr *github.PullRequest, retryCount int) error {
prURL := pr.GetHTMLURL()
mergeStrategy := "client"
if retryCount >= options.PullRequest.Merge.RetryCount {
return fmt.Errorf("failed to merge Pull Request %s after %d retries (max retry count is set to %d)", prURL, retryCount, options.PullRequest.Merge.RetryCount)
}
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"timeout": options.PullRequest.Merge.PollTimeout.String(),
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).Trace("Starting Pull Request merge process")
err = r.waitUntilPullRequestIsMergeable(ctx, options, pr)
if err != nil {
return fmt.Errorf("failed to wait until Pull Request %s is mergeable: %w", prURL, err)
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).Trace("Getting Pull Request status")
pr, _, err = client.PullRequests.Get(ctx, r.Owner, r.Name, pr.GetNumber())
if err != nil {
return fmt.Errorf("failed to retrieve status of Pull Request %s: %w", prURL, err)
}
if pr.GetMerged() {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).Info("Pull Request is already merged")
return nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).Trace("Merging Pull Request")
res, resp, err := client.PullRequests.Merge(ctx, r.Owner, r.Name, pr.GetNumber(), options.PullRequest.Merge.CommitMessage, &github.PullRequestOptions{
MergeMethod: options.PullRequest.Merge.Method,
CommitTitle: options.PullRequest.Merge.CommitTitle,
SHA: options.PullRequest.Merge.SHA,
})
if err != nil && shouldRetryMerge(resp, err) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).WithError(err).Warning("Failed to merge Pull Request - will retry")
retryCount++
err = r.mergePullRequestUsingClient(ctx, options, pr, retryCount)
if err == nil {
return nil
}
}
if err != nil {
return fmt.Errorf("failed to merge Pull Request %s: %w", prURL, err)
}
if !res.GetMerged() {
return fmt.Errorf("pull request %s was not merged: %s", prURL, res.GetMessage())
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": prURL,
"retry": retryCount,
"merge-strategy": mergeStrategy,
}).Info("Pull Request merged")
return nil
}
func (r Repository) waitUntilPullRequestIsMerged(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
var startTime = time.Now()
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
for {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Getting Pull Request status")
var (
prURL = pr.GetHTMLURL()
err error
)
pr, _, err = client.PullRequests.Get(ctx, r.Owner, r.Name, pr.GetNumber())
if err != nil {
return fmt.Errorf("failed to retrieve status of Pull Request %s: %w", prURL, err)
}
if pr.GetMerged() {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("Pull Request merged")
return nil
}
if time.Since(startTime) > options.PullRequest.Merge.PollTimeout {
return fmt.Errorf("timeout after %s waiting for Pull Request %s to be merged", options.PullRequest.Merge.PollTimeout.String(), pr.GetHTMLURL())
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Tracef("Waiting %s until next GitHub request...", options.PullRequest.Merge.PollInterval.String())
time.Sleep(options.PullRequest.Merge.PollInterval)
}
}
func (r Repository) pollPullRequestIsMergeable(ctx context.Context, client *github.Client, gqlClient *githubv4.Client, options GitHubOptions, pr *github.PullRequest) (bool, error) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Getting Pull Request status")
var (
prURL = pr.GetHTMLURL()
err error
)
var statusQuery struct {
Repository struct {
PullRequest struct {
Mergeable githubv4.MergeableState
Merged githubv4.Boolean
MergeStateStatus githubv4.String
ViewerCanMergeAsAdmin githubv4.Boolean
BaseRef struct {
RefUpdateRule struct {
RequiredStatusCheckContexts []string
}
}
HeadRef struct {
Target struct {
Commit struct {
Status struct {
Contexts []struct {
Context string
State githubv4.StatusState
}
}
CheckSuites struct {
Nodes []struct {
CheckRuns struct {
Nodes []struct {
Name string
Status githubv4.CheckStatusState
Conclusion *githubv4.CheckConclusionState
}
} `graphql:"checkRuns(last: 100)"`
}
} `graphql:"checkSuites(last:100)"`
} `graphql:"... on Commit"`
}
}
} `graphql:"pullRequest(number: $prNumber)"`
} `graphql:"repository(owner: $owner, name: $name)"`
}
statusQueryVars := map[string]interface{}{
"owner": githubv4.String(r.Owner),
"name": githubv4.String(r.Name),
"prNumber": githubv4.Int(pr.GetNumber()),
}
err = gqlClient.Query(ctx, &statusQuery, statusQueryVars)
if err != nil {
return false, fmt.Errorf("failed to retrieve status of Pull Request %s: %w", prURL, err)
}
if statusQuery.Repository.PullRequest.Merged {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Pull Request is already merged")
return true, nil
}
if s := statusQuery.Repository.PullRequest.Mergeable; s == githubv4.MergeableStateConflicting {
return false, fmt.Errorf("pull request %s is not mergeable: %s", pr.GetHTMLURL(), s)
}
if s := statusQuery.Repository.PullRequest.Mergeable; s == githubv4.MergeableStateUnknown {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Pull Request mergeability is still being calculated")
return false, nil
}
switch options.PullRequest.Merge.BranchProtection {
case BranchProtectionKindBypass:
{
if statusQuery.Repository.PullRequest.ViewerCanMergeAsAdmin {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Bypassing branch protection rules")
return true, nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("Not able to bypass branch protection rules yet")
// it's possible that the viewer could bypass protection rules at some later point, so don't return an error
return false, nil
}
case BranchProtectionKindAll:
{
if statusQuery.Repository.PullRequest.MergeStateStatus == "CLEAN" {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("All branch protection rules satisfied")
return true, nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Trace("All branch protection rules not satisfied")
return false, nil
}
case BranchProtectionKindStatusChecks:
fallthrough
default:
}
if pr.GetBase().Ref == nil {
return false, errors.New("failed to get PR base ref")
}
requiredContexts := goset.NewSetFromStrings(statusQuery.Repository.PullRequest.BaseRef.RefUpdateRule.RequiredStatusCheckContexts)
rules, _, err := client.Repositories.GetRulesForBranch(ctx, r.Owner, r.Name, pr.GetBase().GetRef())
if err != nil {
return false, fmt.Errorf("failed to fetch Rules for base ref: %w", err)
}
for _, rule := range rules {
if rule.Type != "required_status_checks" {
continue
}
params := github.RequiredStatusChecksRuleParameters{}
if err := json.Unmarshal(*rule.Parameters, ¶ms); err != nil {
return false, fmt.Errorf("failed to parse rule: %w", err)
}
for _, c := range params.RequiredStatusChecks {
err := requiredContexts.Add(c.Context)
if err != nil {
return false, fmt.Errorf("failed to add rule context to required set: %w", err)
}
}
}
commit := statusQuery.Repository.PullRequest.HeadRef.Target.Commit
passingContexts := goset.NewSet()
for _, c := range commit.Status.Contexts {
if !requiredContexts.Contains(c.Context) {
continue
}
if c.State == githubv4.StatusStateSuccess {
err := passingContexts.Add(c.Context)
if err != nil {
return false, fmt.Errorf("failed to add status context to passing set: %w", err)
}
} else {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"status-context": c.Context,
"status-state": c.State,
}).Trace("Waiting for status")
}
}
for _, cs := range commit.CheckSuites.Nodes {
for _, c := range cs.CheckRuns.Nodes {
if !requiredContexts.Contains(c.Name) {
continue
}
if c.Status != githubv4.CheckStatusStateCompleted || !isCheckConclusionPassing(c.Conclusion) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"check-name": c.Name,
"check-status": c.Status,
"check-conclusion": c.Conclusion,
}).Trace("Waiting for check")
} else {
err := passingContexts.Add(c.Name)
if err != nil {
return false, fmt.Errorf("failed to add check context to passing set: %w", err)
}
}
}
}
if !passingContexts.IsSupersetOf(requiredContexts) {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"required-contexts": requiredContexts,
"passing-contexts": passingContexts,
}).Trace("Required status checks not passing")
return false, nil
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
"required-contexts": requiredContexts,
"passing-contexts": passingContexts,
}).Trace("All status checks passing")
// Github's API is not race-free apparently.
// Sometime the merge fails if done too quickly, even if the status/checks report success.
// So wait a little.
time.Sleep(5 * time.Second)
return true, nil
}
func (r Repository) waitUntilPullRequestIsMergeable(ctx context.Context, options GitHubOptions, pr *github.PullRequest) error {
var startTime = time.Now()
client, _, err := githubClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github client: %w", err)
}
gqlClient, err := githubGraphqlClient(ctx, options)
if err != nil {
return fmt.Errorf("failed to create github GraphQL client: %w", err)
}
for {
mergeable, err := r.pollPullRequestIsMergeable(ctx, client, gqlClient, options, pr)
if err != nil {
return err
}
if mergeable {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("Pull Request is mergeable")
return nil
}
if time.Since(startTime) > options.PullRequest.Merge.PollTimeout {
return fmt.Errorf("timeout after %s waiting for Pull Request %s mergeable status", options.PullRequest.Merge.PollTimeout.String(), pr.GetHTMLURL())
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Debug("Pull Request is not mergeable yet")
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"pull-request": pr.GetHTMLURL(),
}).Tracef("Waiting %s until next GitHub request...", options.PullRequest.Merge.PollInterval.String())
time.Sleep(options.PullRequest.Merge.PollInterval)
}
}
func prHasLabels(pr *github.PullRequest, labels []string) bool {
matchingLabels := 0
for _, requiredLabel := range labels {
for _, label := range pr.Labels {
if label.GetName() == requiredLabel {
matchingLabels++
break
}
}
}
return matchingLabels == len(labels)
}
// shouldRetryMerge returns true if we should retry the merge operation at a later time
// see https://github.com/jenkins-x/lighthouse/blob/v0.0.922/pkg/keeper/keeper.go#L1110 for more context
func shouldRetryMerge(resp *github.Response, err error) bool {
var githubErr *github.ErrorResponse
if !errors.As(err, &githubErr) {
return false
}
return resp.StatusCode == 405 && githubErr.Message == "Base branch was modified. Review and try the merge again."
}
func isCheckConclusionPassing(c *githubv4.CheckConclusionState) bool {
if c == nil {
return false
}
switch *c {
case githubv4.CheckConclusionStateSuccess, githubv4.CheckConclusionStateNeutral, githubv4.CheckConclusionStateSkipped:
return true
default:
return false
}
}
================================================
FILE: repository/repository.go
================================================
// Package repository contains everything related to working with git repositories hosted on GitHub: cloning, commits, creating branches, pushing, creating/updating/merging pull requests, and so on.
package repository
import (
"context"
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
"github.com/dailymotion-oss/octopilot/internal/parameters"
"github.com/dailymotion-oss/octopilot/update"
"github.com/google/go-github/v57/github"
"github.com/rs/xid"
"github.com/sirupsen/logrus"
)
var (
// type(params)
repoRegexp = regexp.MustCompile(`^(?P[A-Za-z0-9._\-/]+)(?:\((?P.+)\))?$`)
// owner/name(params)
repoWithNameRegexp = regexp.MustCompile(`^(?P[A-Za-z0-9_\-]+)/(?P[A-Za-z0-9._\-]+)(?:\((?P.+)\))?$`)
)
// SearchType represents the type of search to be performed.
type SearchType int
const (
// Repositories is a search type for repositories.
Repositories SearchType = iota
// Code is a search type for code.
Code
)
const (
// used as a search type for repositories in the GitHub search.
githubRepositoriesSearch = "repositories"
// used as a search type for code in the GitHub search.
githubCodeSearch = "code"
)
var searchTypeMap = map[string]SearchType{
githubRepositoriesSearch: Repositories,
githubCodeSearch: Code,
}
// Repository is a representation of a GitHub repository.
type Repository struct {
Owner string
Name string
Params map[string]string
}
// Parse parses a set of repositories defined as string - from the CLI for example - and returns properly formatted Repositories
// expected syntax is documented in the user documentation: docs/current-version/content/repos/{static,dynamic}.md
func Parse(ctx context.Context, repos []string, githubOpts GitHubOptions) ([]Repository, error) {
var repositories []Repository
for _, repo := range repos {
matches := repoRegexp.FindStringSubmatch(repo)
if len(matches) < 2 {
return nil, fmt.Errorf("invalid syntax for %s: missing repo type or name", repo)
}
switch matches[1] {
case "discover-from":
discoveredRepos, err := discoverRepositoriesFrom(ctx, parameters.Parse(matches[2]), githubOpts)
if err != nil {
return nil, fmt.Errorf("failed to discover repositories: %w", err)
}
repositories = append(repositories, discoveredRepos...)
default:
matches := repoWithNameRegexp.FindStringSubmatch(repo)
if len(matches) < 4 {
return nil, fmt.Errorf("invalid syntax for %s: found %d matches instead of 4: %v", repo, len(matches), matches)
}
repositories = append(repositories, Repository{
Owner: matches[1],
Name: matches[2],
Params: parameters.Parse(matches[3]),
})
}
}
return removeDuplicate(repositories), nil
}
func discoverRepositoriesFrom(ctx context.Context, params map[string]string, githubOpts GitHubOptions) ([]Repository, error) {
searchType := parseSearchType(params["searchtype"])
if query, ok := params["query"]; ok {
return discoverRepositoriesFromQuery(ctx, searchType, query, params, githubOpts)
}
if envVar, ok := params["env"]; ok {
delete(params, "env")
return discoverRepositoriesFromEnvironment(ctx, envVar, params, githubOpts)
}
return nil, fmt.Errorf("can't discover repositories from params %v: missing either query or env param", params)
}
// Update is the entrypoint to update a repository with a set of updaters.
// It returns a boolean indicating whether the repository was updated or not.
func (r Repository) Update(ctx context.Context, updaters []update.Updater, options UpdateOptions) (bool, *github.PullRequest, error) {
r.adjustOptionsFromParams(&options)
repoPath := filepath.Join(options.Git.CloneDir, r.Owner, r.Name)
if !options.KeepFiles {
defer func() {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"path": repoPath,
}).Trace("Deleting temporary files")
if err := os.RemoveAll(repoPath); err != nil {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"path": repoPath,
}).WithError(err).Warning("Failed to delete temporary files")
}
}()
}
var strategy *Strategy
switch options.Strategy {
case "recreate":
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Debug("Using 'recreate' strategy")
strategy = NewRecreateStrategy(r, repoPath, updaters, options)
case "append":
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Debug("Using 'append' strategy")
strategy = NewAppendStrategy(r, repoPath, updaters, options)
default:
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Debug("Using 'reset' strategy")
strategy = NewResetStrategy(r, repoPath, updaters, options)
}
repoUpdated, pr, err := strategy.Run(ctx)
if err != nil {
return false, pr, fmt.Errorf("%w", err)
}
if !repoUpdated {
return false, pr, nil
}
if !options.GitHub.PullRequest.Merge.Enabled {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Debug("Pull Request merging is disabled")
return true, pr, nil
}
if pr == nil {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
}).Warning("No Pull Request was created - can't merge it!")
return true, pr, nil
}
err = r.mergePullRequest(ctx, strategy.Options.GitHub, pr)
if err != nil {
return true, pr, fmt.Errorf("failed to merge Pull Request %s: %w", pr.GetHTMLURL(), err)
}
return true, pr, nil
}
func (r Repository) runUpdaters(ctx context.Context, updaters []update.Updater, repoPath string) (bool, error) {
var repoUpdated bool
for _, updater := range updaters {
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"updater": updater.String(),
}).Trace("Running updater")
updated, err := updater.Update(ctx, repoPath)
if err != nil {
return false, fmt.Errorf("failed to update repository %s: %w", r.FullName(), err)
}
if updated {
repoUpdated = true
}
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"updater": updater.String(),
"changes": repoUpdated,
}).Debug("Updater finished")
}
logrus.WithField("repository", r.FullName()).Debug("All updaters finished")
return repoUpdated, nil
}
func (r Repository) newBranchName(prefix string) string {
branchName := fmt.Sprintf("%s%s", prefix, xid.New().String())
logrus.WithFields(logrus.Fields{
"repository": r.FullName(),
"branch": branchName,
}).Trace("Using new branch")
return branchName
}
func (r Repository) adjustOptionsFromParams(options *UpdateOptions) {
if draftStr, found := r.Params["draft"]; found {
if draft, err := strconv.ParseBool(draftStr); err == nil {
options.GitHub.PullRequest.Draft = draft
}
}
if mergeStr, found := r.Params["merge"]; found {
if merge, err := strconv.ParseBool(mergeStr); err == nil {
options.GitHub.PullRequest.Merge.Enabled = merge
}
}
if mergeAutoStr, found := r.Params["mergeauto"]; found {
if mergeAuto, err := strconv.ParseBool(mergeAutoStr); err == nil {
options.GitHub.PullRequest.Merge.Auto = mergeAuto
}
}
if mergeAutoWaitStr, found := r.Params["mergeautowait"]; found {
if mergeAutoWait, err := strconv.ParseBool(mergeAutoWaitStr); err == nil {
options.GitHub.PullRequest.Merge.AutoWait = mergeAutoWait
}
}
}
// FullName returns the repository full name.
func (r Repository) FullName() string {
return fmt.Sprintf("%s/%s", r.Owner, r.Name)
}
// FullName returns the repository full name with the git extension
func (r Repository) GitFullName() string {
return fmt.Sprintf("%s/%s.git", r.Owner, r.Name)
}
================================================
FILE: repository/repository_test.go
================================================
package repository
import (
"context"
"os"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
t.Parallel()
tests := []struct {
name string
repos []string
preTestHook func()
expected []Repository
expectedErrorMsg string
}{
{
name: "nil input",
},
{
name: "empty input",
repos: []string{""},
expectedErrorMsg: "invalid syntax for : missing repo type or name",
},
{
name: "invalid input",
repos: []string{"whatever"},
expectedErrorMsg: "invalid syntax for whatever: found 0 matches instead of 4: []",
},
{
name: "single repository without parameters",
repos: []string{"dailymotion-oss/octopilot"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{},
},
},
},
{
name: "single repository with dot inside",
repos: []string{"dailymotion-oss/octopilot.test"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot.test",
Params: map[string]string{},
},
},
},
{
name: "multiple repositories without parameters",
repos: []string{"dailymotion-oss/octopilot", "some-owner/MyGreatRepo"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{},
},
},
},
{
name: "single repository with a single parameter",
repos: []string{"dailymotion-oss/octopilot(draft=true)"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"draft": "true",
},
},
},
},
{
name: "single repository with dot inside and a single parameter",
repos: []string{"dailymotion-oss/octopilot.test(draft=true)"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot.test",
Params: map[string]string{
"draft": "true",
},
},
},
},
{
name: "multiple repositories with multiple parameters",
repos: []string{"dailymotion-oss/octopilot(draft=true,merge=true)", "some-owner/MyGreatRepo(merge=false)"},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"draft": "true",
"merge": "true",
},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{
"merge": "false",
},
},
},
},
{
name: "discover from environment",
repos: []string{"discover-from(env=OCTOPILOT_TEST_DISCOVER_FROM,sep=;,merge=true)"},
preTestHook: func() {
os.Setenv("OCTOPILOT_TEST_DISCOVER_FROM", "dailymotion-oss/octopilot;some-owner/MyGreatRepo(merge=false)")
},
expected: []Repository{
{
Owner: "dailymotion-oss",
Name: "octopilot",
Params: map[string]string{
"merge": "true",
},
},
{
Owner: "some-owner",
Name: "MyGreatRepo",
Params: map[string]string{
"merge": "false",
},
},
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
if test.preTestHook != nil {
test.preTestHook()
}
actual, err := Parse(context.Background(), test.repos, GitHubOptions{})
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Empty(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
================================================
FILE: repository/result.go
================================================
package repository
type ResultFile struct {
Repos []RepoUpdateResult `json:"repos"`
}
type RepoUpdateResult struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Error *string `json:"error"`
PullRequest *PullRequestResult `json:"pr"`
IsUpdated bool
}
type PullRequestResult struct {
Number int `json:"number"`
NodeID string `json:"nodeId"`
URL string `json:"url"`
}
================================================
FILE: repository/strategy.go
================================================
package repository
import (
"context"
"fmt"
"github.com/dailymotion-oss/octopilot/update"
"github.com/google/go-github/v57/github"
"github.com/sirupsen/logrus"
)
// Strategy defines how the pull request will be created or updated if one already exists.
type Strategy struct {
Repository Repository
RepoPath string
Updaters []update.Updater
Options UpdateOptions
FindMatchingPullRequest bool
DefaultUpdateOperation string
ResetFromBase bool
}
// Run executes the strategy. It returns:
// - a boolean indicating whether changes have been made to the repository
// - a pull request if one has been created (or updated)
func (s *Strategy) Run(ctx context.Context) (bool, *github.PullRequest, error) {
gitRepo, err := cloneGitRepository(ctx, s.Repository, s.RepoPath, s.Options)
if err != nil {
return false, nil, fmt.Errorf("failed to clone repository %s: %w", s.Repository.FullName(), err)
}
err = s.Options.GitHub.adjustOptionsFromGitRepository(gitRepo)
if err != nil {
return false, nil, fmt.Errorf("failed to adjust options for repository %s: %w", s.Repository.FullName(), err)
}
var existingPR *github.PullRequest
if s.FindMatchingPullRequest {
existingPR, err = s.Repository.findMatchingPullRequest(ctx, s.Options.GitHub)
if err != nil {
return false, nil, fmt.Errorf("failed to find matching pull request for repository %s: %w", s.Repository.FullName(), err)
}
}
var branchName string
if existingPR != nil {
branchName = existingPR.Head.GetRef()
} else {
branchName = s.Repository.newBranchName(s.Options.Git.BranchPrefix)
}
err = switchBranch(ctx, gitRepo, switchBranchOptions{
Repository: s.Repository,
BranchName: branchName,
CreateBranch: s.ResetFromBase || existingPR == nil,
})
if err != nil {
return false, existingPR, fmt.Errorf("failed to switch to branch %s: %w", branchName, err)
}
repoUpdated, err := s.Repository.runUpdaters(ctx, s.Updaters, s.RepoPath)
if err != nil {
return false, existingPR, fmt.Errorf("failed to update repository %s: %w", s.Repository.FullName(), err)
}
if !repoUpdated {
return false, existingPR, nil
}
if err = s.Options.Git.setDefaultValues(s.Updaters, templateExecutorFor(s.Options, s.Repository, s.RepoPath)); err != nil {
return false, existingPR, fmt.Errorf("failed to set default git values: %w", err)
}
if err = s.Options.GitHub.setDefaultValues(s.Options.Git, templateExecutorFor(s.Options, s.Repository, s.RepoPath)); err != nil {
return false, existingPR, fmt.Errorf("failed to set default github values: %w", err)
}
if len(s.DefaultUpdateOperation) > 0 {
s.Options.GitHub.setDefaultUpdateOperation(IgnoreUpdateOperation)
}
commitMessage := NewCommitMessage(s.Options.Git.CommitTitle, s.Options.Git.CommitBody, s.Options.Git.CommitFooter)
changesCommitted, err := commitChanges(ctx, gitRepo, commitOptions{
Repository: s.Repository,
CommitMessage: commitMessage,
GitOpts: s.Options.Git,
})
if err != nil {
return false, existingPR, fmt.Errorf("failed to commit changes to git repository %s: %w", s.Repository.FullName(), err)
}
if !changesCommitted {
logrus.WithField("repository", s.Repository.FullName()).Debug("No changes recorded, nothing to push")
return false, existingPR, nil
}
if s.Options.DryRun {
logrus.WithField("repository", s.Repository.FullName()).Warning("Running in dry-run mode, not pushing changes")
return false, existingPR, nil
}
err = pushChanges(ctx, gitRepo, pushOptions{
GitHubOpts: s.Options.GitHub,
GitCloneDir: s.Options.Git.CloneDir,
Repository: s.Repository,
BranchName: branchName,
CreateBranch: existingPR == nil,
ResetFromBase: s.ResetFromBase,
CommitMessage: commitMessage,
})
if err != nil {
return false, existingPR, fmt.Errorf("failed to push changes to git repository %s: %w", s.Repository.FullName(), err)
}
var pr *github.PullRequest
if existingPR != nil {
pr, err = s.Repository.updatePullRequest(ctx, s.Options.GitHub, existingPR)
} else {
pr, err = s.Repository.createPullRequest(ctx, s.Options.GitHub, branchName)
}
if err != nil {
return false, existingPR, fmt.Errorf("failed to create or update Pull Request: %w", err)
}
return true, pr, nil
}
================================================
FILE: repository/strategy_append.go
================================================
package repository
import (
"github.com/dailymotion-oss/octopilot/update"
)
// AppendStrategy is a strategy that appends new commits to any existing Pull Request.
// So it will try to find a matching PR first, and use it (its branch). Then it will commit on this branch, and update the existing PR - or create a new one if there is no matching PR.
func NewAppendStrategy(repository Repository, repoPath string, updaters []update.Updater, options UpdateOptions) *Strategy {
return &Strategy{
Repository: repository,
RepoPath: repoPath,
Updaters: updaters,
Options: options,
FindMatchingPullRequest: true,
DefaultUpdateOperation: IgnoreUpdateOperation,
ResetFromBase: false,
}
}
================================================
FILE: repository/strategy_recreate.go
================================================
package repository
import (
"github.com/dailymotion-oss/octopilot/update"
)
// RecreateStrategy is a strategy implementation that always creates a new Pull Request - even if an existing one for the same labels already exists.
func NewRecreateStrategy(repository Repository, repoPath string, updaters []update.Updater, options UpdateOptions) *Strategy {
return &Strategy{
Repository: repository,
RepoPath: repoPath,
Updaters: updaters,
Options: options,
FindMatchingPullRequest: false,
DefaultUpdateOperation: "",
ResetFromBase: false,
}
}
================================================
FILE: repository/strategy_reset.go
================================================
package repository
import (
"github.com/dailymotion-oss/octopilot/update"
)
// ResetStrategy is a strategy implementation that resets any existing Pull Request from the base branch.
// So it will try to find a matching PR first, and use it (its branch) - but it will "reset" the branch from the base branch. And it will update the existing PR - or create a new one.
func NewResetStrategy(repository Repository, repoPath string, updaters []update.Updater, options UpdateOptions) *Strategy {
return &Strategy{
Repository: repository,
RepoPath: repoPath,
Updaters: updaters,
Options: options,
FindMatchingPullRequest: true,
DefaultUpdateOperation: ReplaceUpdateOperation,
ResetFromBase: true,
}
}
================================================
FILE: repository/template.go
================================================
package repository
import (
"bytes"
"context"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"text/template"
"github.com/Masterminds/sprig/v3"
stripmd "github.com/writeas/go-strip-markdown"
)
type templateExecutor func(text string) (string, error)
func templateExecutorFor(options UpdateOptions, repo Repository, repoPath string) templateExecutor {
return func(text string) (string, error) {
return executeTemplate(options, repo, repoPath, text)
}
}
func executeTemplate(options UpdateOptions, repo Repository, repoPath string, text string) (string, error) {
t, err := template.
New("").
Funcs(sprig.TxtFuncMap()).
Funcs(template.FuncMap{
"readFile": tplReadFileFunc(repoPath),
"githubRelease": tplGitHubReleaseFunc(options.GitHub),
"expandGithubLinks": tplExpandGitHubLinksToMarkdownFunc(),
"extractMarkdownURLs": tplExtractMarkdownURLsFunc(),
"md2txt": stripmd.Strip,
}).
Parse(text)
if err != nil {
return "", fmt.Errorf("failed to parse template %s: %w", text, err)
}
var buffer bytes.Buffer
err = t.Execute(&buffer, map[string]interface{}{
"repo": repo,
})
if err != nil {
return "", fmt.Errorf("failed to execute template %s: %w", text, err)
}
return buffer.String(), nil
}
func tplReadFileFunc(repoPath string) func(string) string {
return func(path string) string {
if !filepath.IsAbs(path) {
path = filepath.Join(repoPath, path)
}
content, err := os.ReadFile(path)
if err != nil {
panic(fmt.Sprintf("failed to readFile %s: %v", path, err))
}
return string(content)
}
}
func tplGitHubReleaseFunc(githubOpts GitHubOptions) func(string) string {
return func(releaseID string) string {
elems := strings.SplitN(releaseID, "/", 3)
if len(elems) < 3 {
panic("invalid syntax for the commitBodyFromRelease flag - expected 3 parts got " + fmt.Sprint(len(elems)))
}
owner, repo, tag := elems[0], elems[1], elems[2]
ctx := context.Background()
ghClient, _, err := githubClient(ctx, githubOpts)
if err != nil {
panic(fmt.Sprintf("failed to create github client: %s", err))
}
release, _, err := ghClient.Repositories.GetReleaseByTag(ctx, owner, repo, tag)
if err != nil {
panic(fmt.Sprintf("failed to retrieve GitHub Release for %s/%s %s: %v", owner, repo, tag, err))
}
return fmt.Sprintf("# **%s** release [%s](%s)\n\nReleased %s\n\n%s",
repo, tag, release.GetHTMLURL(), release.GetPublishedAt().Format("on Monday January 2, 2006 at 15:04 (UTC)"), release.GetBody(),
)
}
}
func tplExpandGitHubLinksToMarkdownFunc() func(string, string) string {
linkReg := regexp.MustCompile(`([^[]|\s)(#([0-9]+))`)
return func(fullRepoName, input string) string {
return linkReg.ReplaceAllString(input, fmt.Sprintf("$1[$2](https://github.com/%s/issues/$3)", fullRepoName))
}
}
func tplExtractMarkdownURLsFunc() func(string) string {
linkReg := regexp.MustCompile(`\[(.*?)\][\[\(](.*?)[\]\)]`)
return func(input string) string {
return linkReg.ReplaceAllString(input, "$2")
}
}
================================================
FILE: repository/template_test.go
================================================
package repository
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestTplExpandGitHubLinksToMarkdownFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
fullRepoName string
input string
expected string
}{
{
name: "input with no url",
fullRepoName: "owner/name",
input: "some text",
expected: "some text",
},
{
name: "basic PR link",
fullRepoName: "owner/name",
input: "PR #42: some changes",
expected: "PR [#42](https://github.com/owner/name/issues/42): some changes",
},
{
name: "multiple PR links",
fullRepoName: "owner/name",
input: "PR #42: some changes - see also #43 and #44",
expected: "PR [#42](https://github.com/owner/name/issues/42): some changes - see also [#43](https://github.com/owner/name/issues/43) and [#44](https://github.com/owner/name/issues/44)",
},
{
name: "already expanded PR link",
fullRepoName: "owner/name",
input: "[#42](https://github.com/some/where/pull/42)",
expected: "[#42](https://github.com/some/where/pull/42)",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual := tplExpandGitHubLinksToMarkdownFunc()(test.fullRepoName, test.input)
assert.Equal(t, test.expected, actual)
})
}
}
func TestTplExtractMarkdownURLsFunc(t *testing.T) {
t.Parallel()
tests := []struct {
name string
input string
expected string
}{
{
name: "input with no url",
input: "some text",
expected: "some text",
},
{
name: "basic link",
input: "PR [#42](https://github.com/owner/name/issues/42): some changes",
expected: "PR https://github.com/owner/name/issues/42: some changes",
},
{
name: "multiple PR links",
input: "PR [#42](https://github.com/owner/name/issues/42): some changes - see also [#43](https://github.com/owner/name/issues/43) and [#44](https://github.com/owner/name/issues/44)",
expected: "PR https://github.com/owner/name/issues/42: some changes - see also https://github.com/owner/name/issues/43 and https://github.com/owner/name/issues/44",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual := tplExtractMarkdownURLsFunc()(test.input)
assert.Equal(t, test.expected, actual)
})
}
}
================================================
FILE: repository/testdata/head-resolution/.gitignore
================================================
/explicit
/resolution-successful
/resolved
================================================
FILE: repository/testdata/parse-signing-key/invalid-format/private-key.pgp
================================================
-----BEGIN PGP PUBLIC KEY BLOCK-----
xsBNBGRP210BCACv8M8UsPDgDSDk4dD2siK/Sb4ULLxLg5S/8E2YVVtIDv4ZJpAg
MNgOABR1+d+yzlOaJbDdxIULqfXloIor6D6Crdt1aD8oes4v1GdSlKTqd5B+8st5
7F8OF/Tqa3/xNokoNw5a4MpSP2ZnKkLwILJIeZ+a3vb8z0rE55T98Q4j/2thqu4H
7HwPyOJ5OXrUqU7Ic/oMvG4y8lAwWXX+CGVcQeFhETIFdBVHc5PZreIr7NBpVJJL
=A9OI
-----END PGP PUBLIC KEY BLOCK-----
================================================
FILE: repository/testdata/parse-signing-key/valid-encrypted/private-key.pgp
================================================
-----BEGIN PGP PRIVATE KEY BLOCK-----
xcFGBGRQFYkBBADPRP14D4oJq58WUTa1JdwTp349nir9SnODKMwAKvKptFvKsEzT
a/pmM4/qFwQtCSJGzqTCrq33X9+UIoV4wwXoY4YP2zVZ1/gUDhzdia4j84JaLOyp
IVfzRjQF7/tcYZJexGeDnfMraOXgdGPTEoITCMeRWcya9PtK8pFzGd6v/QARAQAB
/gkDCA7IDqA++eodYGC5uN4PQdI34NdOebSiQP/0R42CnxIdYNNB2vZqjhiinTjF
5HGhlB/HDZCfQaReYEIY92VlK44GYJrAXXhyKZXKx68rvbimjEFsZaXiMi4Gc1CR
raBXY5x33rc6l9GVDWw0FVzvBbtcEZp+JTrfDm60dPSLN3B1szONcIrAEiVT4wgl
oP7q7msTgnDgjqzpWFTSr6PrO68U/18Ev0HEgoqdK22oP77BmgQKYszHXWoNJ76N
d9Ux6JelI38ItTi8g5YvdxXaxDaBVLLkwFdT7PIXZ+vtyZsGFVreppt0V+w7sn7H
v3jp1FoHg4XOvHChgzYXXcpTbaogar2ajUGcx4BojMbWi+92MC0B3xgPOvOqgEJi
jlp6yrLQ6uPS4tXT7Ls57mrOcryE+ugaKx50tE1FVgvWLFDbcN6uG7iTmIjiJiOX
IyBlAo2VhabP+2FzjxMmF66vxFEZINnmgRCb9K3MyqzcvqX8Vq0DNdXNLG9jdG9w
aWxvdCAodGVzdCkgPG9jdG9waWxvdEBkYWlseW1vdGlvbi5jb20+wroEEwEKACQF
AmRQFYkCGy8DCwkHAxUKCAIeAQIXgAMWAgECGQEFCQAAAAAACgkQJO+VNYEzlaII
VgQApYUFmdj8uZAtoAFXTI36Q3AsYnPCGXzOfdpqtAclxFvyma1XvWZ4G6Pp81bs
cuUV8QjijgGHSMTBO0kqJdpwwOBm5FMgJFgZBKZGE4cbYZ6YuA3XhvAGfyHfaVdK
Hs0AaZhJ6GxFNiTwvSeaEJo+8BP3fginEdbdkh68PbFxWmzHwUYEZFAViQEEAKYC
Rfz5c7Yv9fqCm42Q7QdcOj02uHKVX8pvfPKe4LduWbUR+9QGUCZtawKObnxuJGKE
YwxJTJzZ2aouw8iTLi6TS/v2Kye6e0jfLYK1QUvRfsw/Ygfssw/ASxgounQ1rA9C
ab3MIKjQ+6x+rlTX11Dl4ZSMJN9Hq8zJtM4g/SwTABEBAAH+CQMIr/42b3e4y55g
kgRHUUsoaJEvmM1y2Q5KsOOECKy6L5ZUihCbhWJfqs3rE78R919P6PzaZCxTHPK2
vS3b+0xo8QDR972XAGqZnTeXvs+nOQ+j6uvI6KOJJy5y8THElrL/BSAFIFRLIh6L
VM45HvZ6smhayrPkFpN1eUBbWTm6pI7v4GWJIlR7iwqe0S7muO0Z0AltrddZ1RNH
Kr4FjebgZemVwAUqiGUFbQ/5mgaKnDjz+YrfhM+XXx20MdCebA0lYbE8mw1Wr49z
DrnjCxuB8AUsUy9DcTK1+5alScTxZREkxXJGh4YTJU+v9pXxSsYT6Hr2q3/kgJif
9MZZTmFVx5El+Vp/vC8JzZV8vOLDL/vu6XnuYCnuV2pKuzdy94Ef3uEHf1EGJka/
gDCLrsrFI21/+kCHSLFRLYAhZ0pMYThkPo9fvAzarY9I1TrjAq5iyyCDDYbCT7ut
srgMlMX4G5GxrNbdayoTD8/rh2b2dhTjDjmIS8LAgwQYAQoADwUCZFAViQUJAAAA
AAIbLgCoCRAk75U1gTOVop0gBBkBCgAGBQJkUBWJAAoJED9bfABunmQ3tq4D/jxN
a6sHQz1Vy+klGqfOepfEENKYcK4Whz2g5LNSu3gYboOBoXJdH+pyApo/MyBYuuN5
wsEAWAot3G2mMySH+qy5Gp2dxrjOIHw488/FioQDC7D9lbEzZytRdVwreW1E6CTy
uNBLcbbAv5AshRm2+/LC1RUlxRDcUM1q7ycT6sLgc0gD/3z4OvET21qS/LKZct+7
TkL7aWUYGCn0/I1RwFLRN+gHFta003GCxDHoVcXRNX5d4/TX/sbAURAdA0v8Pz3S
Gz+iMSqPU25SoJ22TAktcIEWekjS7nTq+9iqro841OPJtjWELLdBFEX9gXxyIQVx
idPYtugUxTy8f1ZM3Ru4WZW2x8FGBGRQFYkBBADEjqgq5UuPP/gXWR9nuEf9O0qw
g63fF6nOf+ZBmbuedI6bwjTyS5AR1xVAHHUGu8zoQ+XUZ/H+zF6t+mvkX3q9hxxS
CztN51/an7/yZy+XPCPVTegn/BOQ7ILiTIe0bnwInW3+ZK55c/dAoblVmb9TwylT
wymYLU3P+Pwph9zUjQARAQAB/gkDCJpVGJ3mAxtaYFnD+Y6QXBkjDRVxPEc2RIhd
WU980osgYCipF0NxzJbkMUhvlints5aoWAmuhSgc4NiDJnaytv32euG2hwnPo3hF
0Xjc9yhGWC5saTSuoHF3N3jdbhAXwQfkv6g9rTLmSpsMXKjrsZ0PIK3rLDnamvLs
v41PEbtGWzV2GoQdcZimNFD/e+7OcD5gh7o8sLH5PnuqPWPNOzrOKSKYrMJVD1lC
VC9u3de33DlV8eaPXZ2QgRBsYD9kbkQms/X4xxPfGOpCx13K6sFvEhyWk896UNfk
wRdMRI3282SV2EbgwvtlCrjLAGD9LQgoxH4AKc4Fcp4p5l2Q56pPj/yDS4QjxUc1
NbeDRmvpk2eNAen28eakGm4s866OAT2IPTISPNFnuzMx6m/9oNGZZgQk5Xg2HDqJ
AHwRE8giK9o7bTTdi2nOeATgFHdffZKoYQIIoNlJU9qvJlKW9AxbatrOz3naF8ra
2d3klEsIwMIbWiTCwIMEGAEKAA8FAmRQFYkFCQAAAAACGy4AqAkQJO+VNYEzlaKd
IAQZAQoABgUCZFAViQAKCRBPOvc0hmy/E+nEBACetrDffOnsi3rR9jhJ60/gD3KN
rtdWSYLPjeT1jVBszwRDVbj7x9czxUMjnwYKB8V1Lzx/2s0YLrdTcF5vPC2jPmHn
/MPY/634MqX5SKak3gIcDMo9W70LG3bAAFPumGsvXmWP6a4TBTlqsCGvQykzX8KF
AEnMkXOhLfSiXtCETg/HBACj8buC6ymoVXDO5N6k7/tjCCGR9UY44ovcH9AESgfR
dEunXSAJ0iXNdFFB3thpIujtUx1jXFM5AyTFrAvjmpp+tbou8YoPgL/3+sk5yEKo
33lqpOXl3i0z2hOk/5gwO+hgaySxW379yUcE3CEJ3ylmh13SKiRDWF30T0ktoXb5
NQ==
=jmZA
-----END PGP PRIVATE KEY BLOCK-----
================================================
FILE: repository/testdata/parse-signing-key/valid-unencrypted/private-key.pgp
================================================
-----BEGIN PGP PRIVATE KEY BLOCK-----
xcLYBGRQF/oBCACkFCvbaYxZvqTmtrwObAtQIi+Gv6/s0smLTYsqbpJdJJCm
nYR9GQXoBi2P7/pXA25CqZDe9N/AWdwzDXzYJsUtpPFPoIpRQTPKNMxNrYWt
1F/b6KuPANd01TfjtbtY+4ybqKjl48BsfBCOEczdDniMMXEygqGQ3Dx4v8sU
aC8l+Q9C5sUBW2GwGVW+S4htJEV3XzEMWf7SdNO8XXnpXQCXqB4dKtZRF4HZ
BsWFQvgzGgdbX8dwk1iV/BdmIh7hGBmFLjZqUxPACoBLWpES0vojeSjk2FKB
wWzw43tZ5Dugf2cODVXBYJH2iyqcy17HYblPM+XzQQfvlNz/EsJeK+HfABEB
AAEAB/41plbUzoVSzvByc+u3t4JXeGYb5E+s2xuFjhxkCnWXOR6HLFgm42i3
/lUljG1JyFhkObeh/2WuKnPCybU5pCuzCgzRYYf4m55Ijs0C1SsxtJCHgmOe
RcMtc45ryX9x0Aag2xwm1zqS/loXaiCXY2TtSjleL7KOgETRorzPdmV8P5ZR
fKT8rApl6O8L4N+9ZzYgdM7xq2zRsPN3kV5ZPIeWBacsw0+RKLN+YNe28Vy9
1FaTze1uo1fO+D2pslWlgLoo2xgAKeJNXQHr1exair8o58aBrSxSQGLUpEZX
M7AQljgGl8GSgEzfzgdJbFrsHKTNzgrzqi/ovo/r0LhHkvBZBAC86ErOYoNS
uOiWAaaW8ORkygBr7VJO2dzKq3rd6HssJyslrNRSpqpzrKBeNOwYjr1l9c0M
PbWpKUep8PTR8+rjAGocFr5HjmCYcwftmmW9GjNGijRJ0hi9aXzH4hrfMHHd
+O+l5UxCFc5RowvcNIGlLD3jfxFmvZvg7PLzvWgvLQQA3lpuM/AOMuaqIA0d
zETXss6R8ZeQqMcmfqLxte6R2cLL05RBSyQ9ko0EycdidBYH+SQ+e3If/poQ
ljIfJt357lTSbaZV5OVxGNPF6EnJYoEezXFCWReuEpCAytFG5BYLi4ij+YrM
IJGbD90wPo6gp/TQUk6pIUMAqINSKQLanLsEAJI8oh0a0dYkXEKvsaC11JBo
wdJEH7tUf1KeVInln6p6SorZkHQch2XGclcIZhjBr5oVrvhO/5A0gb9MjDgf
cBLK5SbMr9EPFEDTbYYD5qmVO9Vi0QoIAJZGsdoNs1UfWjFjEVFumzxIJHOD
Sr4fxNNkGaM1TzM5994AYKY2D7xeRFvNJW9jdG9waWxvdCA8b2N0b3BpbG90
QGRhaWx5bW90aW9uLmNvbT7CwI0EEAEIACAFAmRQF/oGCwkHCAMCBBUICgIE
FgIBAAIZAQIbAwIeAQAhCRC2sjDe28xtmxYhBLkKgr4DSnNgP0U6s7ayMN7b
zG2bj+gH/illHgV1m4Yj6h4UQCU61fsj84AvpwhoqFWOF3m7CjtJfj0uTshu
aE3svPScP3MHjn14Zl47p+HYAOX64PHPCllbvJ95ABxb0sy6ELL8q8hhhOCx
k/lzmA9Ah6tZ6kJGkzrMYDZtImber68E9aRXCtTRYJxLroZBnuRuswxZl/cX
PuycQ+x9PHORCMwzLDWyR18MWn7mZNpvV1CWu3O+Qbhn+WCpjXqPpvshvbXl
LksIDq+rsBL3WyMufm/NrXuBEz2eJSrhaGgQOnuaXtvHOJ81C5WkM0yBBgxE
QwuU0rduP5zPveDDgWk+1vCVdbRNfGxBmaBbnQS4zdgt6lwjIPXHwtgEZFAX
+gEIAKbWyhTE2T72uEOVntfXbBCArneiEnMKd8ws9UbhSwWM9kZL35Qplghu
LhU/DYgR9GJftDLOp2XZTMcvXiWVfRX71eE0rSqXweLStIzSFtNLbxIvlySn
rTvjW5nv3sT0pZOBD7/R4VzEIWDhkkdAzz8qz+jSCWODNxmIY1sKHxLSw1y8
bxCsvYNWxgE31p/ejoXFuoDLxzgZrL1wcT9D8Nj8AHVwEkF1y/92edPh7Pxi
TzFpyiibtLWnxcikL7Q/EJWiF9165aSPQSDr3QyyGTVx/C2qBH9dXqkwM5qo
cn0YWXU77RkQAPNTDzv3lnyaVuzsyvFTSfbYymTTwbJ7u9cAEQEAAQAH/R8H
9Tcus8+DuRsM8anorfdVz919fhv6lvSZaheAYOFL6iSCCTg4EelIgPa/rwcf
e8puTYhjqnwFkkO7+jFYYBceK5ZDI3A4IL5M/XrxuoAbWDHUOzL8ovpwG8IC
fPc6H6/TQfgmE9oaurCX1Aq/saxojJobstZY+f8cQIqW09e+odtAoVP8H+Fb
OCpkYGJzGxovMaGH/+2b0jIEbwaZWsdsXdIPStSvRu7oEIi8l0jft9o81Ntp
y7wxdnVie/G2nOBvnXFj9YcNWX+5328gcf7KOAE4ZazFFTZq0kmDR7ok5erR
OK1yyxN+sD05OllASvkwhdtekjM6C6kFA6nn+EUEAMbl4gVBZzyQ4mAcyA+x
dfbrqpxyiQY2sZarEFae3Nd5GPimeNMFD4aj9SVo5+Ec4gRmaf2j1jqNCKmR
1Ax58tUe3ktZwkliyx5f81Fp3gh4fp671uw9XGP2VF+NuXXmloY8hWThx20e
wncOSmhxvr4fs8POmgcMfh5Zab/sJzwtBADWvLcuaht+H2187cgP9TE7DU3v
Un4S86ffWEQrvgSCYIubGvVBEEXPczy1QBQDtvJjuQ9WkWv0U2B1gYcY7BjJ
acvlx4mhn2I8P4z7YtFahcZUyxATSZR8Jy0BiyxZOllf4uMA1eY538N/Y0YB
8HdZ5Dg9RQ1slkd/+J/Z9QumkwP/dV6gdqK8b1GO8H8VfXW5SdmPHdFiYyRf
oIB9rpae9A8tcaMPT7YkzQbb6nZI5JWjrMevJXpHVFqQJM8UHo/x4xyUcDlD
TTGaI9pFwTRb0nVvEpcsQ3jGLgm5O7NwhFd+5wqdQ3fnCdXorblj0ZE2qbOr
IRZJOLnoyWd9RjiuXhk7Z8LAdgQYAQgACQUCZFAX+gIbDAAhCRC2sjDe28xt
mxYhBLkKgr4DSnNgP0U6s7ayMN7bzG2b3TUIAI2Eb+r6qAT7mTZMUiiQuCCT
Q6w14PgCIzUufR2Wl7lUXTXa0jgNgUzxzNCEQXiLvY/73kfp8buP8SenFPaa
+PgUx/H6mgG00Eyb6q/vdg+Kvqj6W4WA3IgeXlrTxiwIKsExj4g7inMu8AFs
KuKFqOWOn6Es5ZJuDAoL2DkUg1IgwNkx/kbkAiRpWD0tCmuwgnN7qv31mjwl
XZxJZtGbCbv8vyJmnU4oCZeEm9AvjlhbKODW4m60JkYf1vN0aAVC3+dVTr5b
nd3lEjDolpJEigpM/w6yBSNXMikTNQE53m2cQVVuQXz3xMPhxlkHRGsFK8Zf
dS7peJBD08NgFuj5Aco=
=bS/b
-----END PGP PRIVATE KEY BLOCK-----
================================================
FILE: repository/testdata/switch-branch/.gitignore
================================================
/create-new-branch
/existing-branch
/git-repo
================================================
FILE: repository/utils.go
================================================
package repository
import (
"context"
"fmt"
"slices"
"github.com/google/go-github/v57/github"
)
// removeDuplicate removes duplicate repositories from the input list and returns a new slice of unique repositories.
// It checks for duplicates based on the combination of the "Owner" and "Name" attributes
func removeDuplicate(inputList []Repository) []Repository {
if len(inputList) == 0 {
return inputList
}
seen := make(map[string]bool)
isDuplicate := func(repo Repository) bool {
key := fmt.Sprintf("%s-%s", repo.Owner, repo.Name)
if seen[key] {
return true
}
seen[key] = true
return false
}
repositories := slices.DeleteFunc(inputList, isDuplicate)
return repositories
}
// parseSearchType converts a string representation to a SearchType.
// It maps specific string values to corresponding SearchType constants.
// If the input string is not recognized, it defaults to Repositories.
func parseSearchType(str string) SearchType {
if searchType, ok := searchTypeMap[str]; ok {
return searchType
}
return Repositories
}
// searchCodeRepositories searches GitHub repositories using the Github Code Search feature
func searchCodeRepositories(ctx context.Context, ghClient *github.Client, query string, opts *github.SearchOptions, params map[string]string) ([]Repository, *github.Response, error) {
repos := []Repository{}
codeResults, resp, err := ghClient.Search.Code(ctx, query, opts)
if err != nil {
return repos, nil, err
}
for _, result := range codeResults.CodeResults {
repos = append(repos, Repository{
Owner: result.Repository.Owner.GetLogin(),
Name: result.Repository.GetName(),
Params: params,
})
}
return repos, resp, nil
}
// searchRepositories searches GitHub repositories using the Github Repositories Search feature
func searchRepositories(ctx context.Context, ghClient *github.Client, query string, opts *github.SearchOptions, params map[string]string) ([]Repository, *github.Response, error) {
repos := []Repository{}
repoResults, resp, err := ghClient.Search.Repositories(ctx, query, opts)
if err != nil {
return repos, nil, err
}
for _, result := range repoResults.Repositories {
repos = append(repos, Repository{
Owner: result.Owner.GetLogin(),
Name: result.GetName(),
Params: params,
})
}
return repos, resp, nil
}
================================================
FILE: repository/utils_test.go
================================================
package repository
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseSearchType(t *testing.T) {
t.Parallel()
tests := []struct {
name string
input string
expected SearchType
}{
{
name: "Valid search type (repositories)",
input: "repositories",
expected: Repositories,
},
{
name: "Valid search type (code)",
input: "code",
expected: Code,
},
{
name: "Empty search type",
input: "",
expected: Repositories,
},
{
name: "Invalid search type",
input: "invalid_type",
expected: Repositories, // Defaults to Repositories
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := parseSearchType(test.input)
assert.Equal(t, test.expected, actual)
})
}
}
func TestRemoveDuplicate(t *testing.T) {
t.Parallel()
repositories := []Repository{
{Owner: "owner1", Name: "repo1"},
{Owner: "owner1", Name: "repo1"},
{Owner: "owner1", Name: "repo2"},
{Owner: "owner2", Name: "repo2"},
{Owner: "owner3", Name: "repo3"},
}
result := removeDuplicate(repositories)
expected := []Repository{
{Owner: "owner1", Name: "repo1"},
{Owner: "owner1", Name: "repo2"},
{Owner: "owner2", Name: "repo2"},
{Owner: "owner3", Name: "repo3"},
}
assert.ElementsMatch(t, expected, result)
}
================================================
FILE: update/doc.go
================================================
// Package update provides the updaters that change content in the git repositories
package update
================================================
FILE: update/exec/exec.go
================================================
// Package exec provides an updater that executes an external command to update the repository.
package exec
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/cosiner/argv"
)
// ExecUpdater is an updater that executes an external command to update the repository.
type ExecUpdater struct {
Command string
Path string
Args []string
Stdout string
Stderr string
Timeout time.Duration
}
// NewUpdater builds a new exec updater from the given parameters
func NewUpdater(params map[string]string) (*ExecUpdater, error) {
updater := &ExecUpdater{}
updater.Command = params["cmd"]
if len(updater.Command) == 0 {
return nil, errors.New("missing cmd parameter")
}
updater.Path = params["path"]
if args, ok := params["args"]; ok {
argv, err := argv.Argv(args, func(backquoted string) (string, error) {
return backquoted, nil
}, nil)
if err != nil {
return nil, fmt.Errorf("failed to convert args '%s' with argv: %w", args, err)
}
if len(argv) > 0 {
updater.Args = argv[0]
}
}
updater.Stdout = params["stdout"]
updater.Stderr = params["stderr"]
timeout := params["timeout"]
if len(timeout) > 0 {
var err error
updater.Timeout, err = time.ParseDuration(timeout)
if err != nil {
return nil, fmt.Errorf("failed to parse duration for cmd timeout '%s': %w", timeout, err)
}
}
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u *ExecUpdater) Update(ctx context.Context, repoPath string) (bool, error) {
if u.Timeout > 0 {
var cancelFunc context.CancelFunc
ctx, cancelFunc = context.WithTimeout(ctx, u.Timeout)
defer cancelFunc()
}
var (
stdout bytes.Buffer
stderr bytes.Buffer
)
cmd := exec.CommandContext(ctx, u.Command, u.Args...)
cmd.Dir = repoPath + u.Path
cmd.Stdout = &stdout
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return false, fmt.Errorf("failed to run cmd '%s' with args %v in path: %s - got stdout [%s] and stderr [%s]: %w", u.Command, u.Args, u.Path, strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err)
}
if len(u.Stdout) > 0 {
if err = u.writeCmdOutputToFile(stdout, repoPath, u.Stdout); err != nil {
return false, fmt.Errorf("failed to write stdout of cmd '%s' to %s: %w", u.Command, u.Stdout, err)
}
}
if len(u.Stderr) > 0 {
if err = u.writeCmdOutputToFile(stderr, repoPath, u.Stderr); err != nil {
return false, fmt.Errorf("failed to write stderr of cmd '%s' to %s: %w", u.Command, u.Stderr, err)
}
}
return true, nil
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u *ExecUpdater) Message() (title, body string) {
title = fmt.Sprintf("Run %s", u.Command)
body = fmt.Sprintf("Running command `%s`", u.Command)
if len(u.Args) > 0 {
body = fmt.Sprintf("%s with args %v", body, u.Args)
}
return title, body
}
// String returns a string representation of the updater
func (u *ExecUpdater) String() string {
return fmt.Sprintf("Exec[cmd=%s,args=%v]", u.Command, u.Args)
}
func (u *ExecUpdater) writeCmdOutputToFile(output bytes.Buffer, repoPath, filePath string) error {
if !filepath.IsAbs(filePath) {
filePath = filepath.Join(repoPath, filePath)
}
err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm)
if err != nil {
return fmt.Errorf("failed to create directory %s: %w", filepath.Dir(filePath), err)
}
err = os.WriteFile(filePath, output.Bytes(), 0644)
if err != nil {
return fmt.Errorf("failed to write output of cmd '%s' to %s: %w", u.Command, filePath, err)
}
return nil
}
================================================
FILE: update/exec/exec_test.go
================================================
package exec
import (
"bytes"
"context"
"os"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *ExecUpdater
expectedErrorMsg string
}{
{
name: "valid params with cmd",
params: map[string]string{
"cmd": "ls",
},
expected: &ExecUpdater{
Command: "ls",
},
},
{
name: "valid params with cmd and multiple args",
params: map[string]string{
"cmd": "ls",
"args": "one two three",
},
expected: &ExecUpdater{
Command: "ls",
Args: []string{"one", "two", "three"},
},
},
{
name: "valid params with cmd, args, stdout, stderr and timeout",
params: map[string]string{
"cmd": "ls",
"args": "-lh",
"stdout": "/path/to/some/file",
"stderr": "/path/to/some/other/file",
"timeout": "3s",
},
expected: &ExecUpdater{
Command: "ls",
Args: []string{"-lh"},
Stdout: "/path/to/some/file",
Stderr: "/path/to/some/other/file",
Timeout: 3 * time.Second,
},
},
{
name: "valid params with cmd, path, args, stdout, stderr and timeout",
params: map[string]string{
"cmd": "ls",
"path": ".",
"args": "-lh",
"stdout": "/path/to/some/file",
"stderr": "/path/to/some/other/file",
"timeout": "3s",
},
expected: &ExecUpdater{
Command: "ls",
Path: ".",
Args: []string{"-lh"},
Stdout: "/path/to/some/file",
Stderr: "/path/to/some/other/file",
Timeout: 3 * time.Second,
},
},
{
name: "nil params",
expectedErrorMsg: "missing cmd parameter",
},
{
name: "missing mandatory cmd param",
params: map[string]string{
"args": "-lh",
},
expectedErrorMsg: "missing cmd parameter",
},
{
name: "invalid timeout",
params: map[string]string{
"cmd": "ls",
"timeout": "15 seconds",
},
expectedErrorMsg: "failed to parse duration for cmd timeout '15 seconds': time: unknown unit \" seconds\" in duration \"15 seconds\"",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *ExecUpdater
expected bool
expectedErrorMessages []string
extraCheck func() bool
}{
{
name: "delete a file",
files: map[string]string{
"file-to-delete.txt": "whatever content",
},
updater: &ExecUpdater{
Command: "rm",
Args: []string{"file-to-delete.txt"},
Timeout: 1 * time.Second,
},
expected: true,
extraCheck: func() bool {
// ensure the file has been deleted
_, err := os.Stat(filepath.Join("testdata", "file-to-delete.txt"))
return err != nil
},
},
{
name: "fail deleting a non-existing file",
updater: &ExecUpdater{
Command: "rm",
Args: []string{"does-not-exists.txt"},
Timeout: 1 * time.Second,
},
expected: false,
expectedErrorMessages: []string{
"failed to run cmd 'rm' with args [does-not-exists.txt] in path: - got stdout [] and stderr [rm: does-not-exists.txt: No such file or directory]: exit status 1",
"failed to run cmd 'rm' with args [does-not-exists.txt] in path: - got stdout [] and stderr [rm: cannot remove 'does-not-exists.txt': No such file or directory]: exit status 1",
},
},
{
name: "run a cmd and write its stdout to a file",
files: map[string]string{
"file-to-print.txt": "some content",
},
updater: &ExecUpdater{
Command: "cat",
Args: []string{"file-to-print.txt"},
Stdout: "file-to-print.stdout",
Timeout: 1 * time.Second,
},
expected: true,
extraCheck: func() bool {
actualFileContent, _ := os.ReadFile(filepath.Join("testdata", "file-to-print.stdout"))
return bytes.Equal(actualFileContent, []byte("some content"))
},
},
{
name: "run a cmd using sh -c with a specified args containing * and write its stdout to a file",
files: map[string]string{
"sh-c-file-to-list.txt": "some content",
},
updater: &ExecUpdater{
Command: "sh",
Args: []string{"-c", `ls sh-c-file-*-list.*`},
Stdout: "ls-result.stdout",
Timeout: 1 * time.Second,
},
expected: true,
extraCheck: func() bool {
actualFileContent, _ := os.ReadFile(filepath.Join("testdata", "ls-result.stdout"))
return bytes.Equal(actualFileContent, []byte("sh-c-file-to-list.txt\n"))
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
{
for filename, content := range test.files {
err := os.MkdirAll(filepath.Dir(filepath.Join("testdata", filename)), 0755)
require.NoErrorf(t, err, "can't create testdata directories for %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), []byte(content), 0644)
require.NoErrorf(t, err, "can't write testdata file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMessages) > 0 {
require.Error(t, err)
assert.Contains(t, test.expectedErrorMessages, err.Error())
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
if test.extraCheck != nil {
assert.True(t, test.extraCheck())
}
}
})
}
}
================================================
FILE: update/exec/testdata/.gitignore
================================================
*
!.gitignore
================================================
FILE: update/helm/helm.go
================================================
// Package helm provides an updater that updates Helm charts dependencies.
package helm
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"strconv"
"github.com/dailymotion-oss/octopilot/update/value"
"gopkg.in/yaml.v3"
)
// HelmUpdater is an updater that updates Helm charts dependencies.
type HelmUpdater struct {
Dependency string
Indent int
Valuer value.Valuer
}
// NewUpdater builds a new Helm updater from the given parameters and valuer
func NewUpdater(params map[string]string, valuer value.Valuer) (*HelmUpdater, error) {
updater := &HelmUpdater{}
updater.Dependency = params["dependency"]
if len(updater.Dependency) == 0 {
return nil, errors.New("missing dependency parameter")
}
updater.Indent, _ = strconv.Atoi(params["indent"])
if updater.Indent <= 0 {
updater.Indent = 2
}
updater.Valuer = valuer
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u *HelmUpdater) Update(ctx context.Context, repoPath string) (bool, error) {
charts, err := extractHelmChartsDirectories(repoPath)
if err != nil {
return false, fmt.Errorf("failed to find Helm Charts located in %s: %w", repoPath, err)
}
value, err := u.Valuer.Value(ctx, repoPath)
if err != nil {
return false, fmt.Errorf("failed to get value: %w", err)
}
var updated bool
for _, chartDir := range charts {
dependenciesFilesPaths := []string{
filepath.Join(chartDir, "requirements.yaml"), // helm2
filepath.Join(chartDir, "Chart.yaml"), // helm3
}
for _, dependenciesFilePath := range dependenciesFilesPaths {
if _, err = os.Stat(dependenciesFilePath); err == nil {
chartUpdated, err := u.updateChartDependenciesFile(dependenciesFilePath, value)
if err != nil {
return false, fmt.Errorf("failed to update Helm Chart located in %s: %w", chartDir, err)
}
if chartUpdated {
updated = true
}
}
}
}
return updated, nil
}
func (u *HelmUpdater) updateChartDependenciesFile(filePath string, version string) (bool, error) {
data, err := os.ReadFile(filePath)
if err != nil {
return false, fmt.Errorf("failed to read file %s: %w", filePath, err)
}
var rootNode yaml.Node
err = yaml.Unmarshal(data, &rootNode)
if err != nil {
return false, fmt.Errorf("failed to unmarshal YAML file %s: %w", filePath, err)
}
updated := u.updateChartDependenciesNode(&rootNode, version)
if !updated {
return false, nil
}
f, err := os.Create(filePath)
if err != nil {
return false, fmt.Errorf("failed to create file %s: %w", filePath, err)
}
defer f.Close()
enc := yaml.NewEncoder(f)
enc.SetIndent(u.Indent)
err = enc.Encode(&rootNode)
if err != nil {
return false, fmt.Errorf("failed to encode updated YAML content for %s: %w", filePath, err)
}
err = enc.Close()
if err != nil {
return false, fmt.Errorf("failed to close the YAML encoder for %s: %w", filePath, err)
}
return updated, nil
}
func (u *HelmUpdater) updateChartDependenciesNode(node *yaml.Node, version string) bool {
if node == nil {
return false
}
var updated bool
for i, child := range node.Content {
if child == nil {
continue
}
if child.Value == "dependencies" {
if i+1 < len(node.Content) {
dependenciesValueNode := node.Content[i+1]
for _, dependency := range dependenciesValueNode.Content {
if u.updateChartDependencyNode(dependency, version) {
updated = true
}
}
}
}
if u.updateChartDependenciesNode(child, version) {
updated = true
}
}
return updated
}
func (u *HelmUpdater) updateChartDependencyNode(node *yaml.Node, version string) bool {
if node == nil {
return false
}
if node.Kind != yaml.MappingNode {
return false
}
var dependencyNameMatch bool
for i := 0; i < len(node.Content); i += 2 {
var (
keyNode = node.Content[i]
valueNode = node.Content[i+1]
)
if keyNode.Value == "name" && valueNode.Value == u.Dependency {
dependencyNameMatch = true
break
}
}
if !dependencyNameMatch {
return false
}
for i := 0; i < len(node.Content); i += 2 {
var (
keyNode = node.Content[i]
valueNode = node.Content[i+1]
)
if keyNode.Value == "version" && valueNode.Value != version {
valueNode.SetString(version)
return true
}
}
return false
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u *HelmUpdater) Message() (title, body string) {
title = fmt.Sprintf("Update %s", u.Dependency)
body = fmt.Sprintf("Updating dependency `%s`", u.Dependency)
return title, body
}
// String returns a string representation of the updater
func (u *HelmUpdater) String() string {
return fmt.Sprintf("Helm[dependency=%s]", u.Dependency)
}
func extractHelmChartsDirectories(baseDir string) ([]string, error) {
var chartDirectories []string
err := filepath.Walk(baseDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
switch filepath.Base(path) {
case ".git":
return filepath.SkipDir
default:
return nil
}
}
switch filepath.Base(path) {
case "Chart.yaml":
chartDirectories = append(chartDirectories, filepath.Dir(path))
}
return nil
})
if err != nil {
return nil, err
}
return chartDirectories, nil
}
================================================
FILE: update/helm/helm_test.go
================================================
package helm
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *HelmUpdater
expectedErrorMsg string
}{
{
name: "valid params",
params: map[string]string{
"dependency": "some-chart",
"indent": "4",
},
expected: &HelmUpdater{
Dependency: "some-chart",
Indent: 4,
},
},
{
name: "nil params",
expectedErrorMsg: "missing dependency parameter",
},
{
name: "missing mandatory dependency param",
params: map[string]string{
"whatever": "here too",
},
expectedErrorMsg: "missing dependency parameter",
},
{
name: "missing optional indent param",
params: map[string]string{
"dependency": "some-chart",
},
expected: &HelmUpdater{
Dependency: "some-chart",
Indent: 2,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params, nil)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *HelmUpdater
expected bool
expectedErrorMsg string
expectedFiles map[string]string
}{
{
name: "update a single version in a single chart in helm 2 format",
files: map[string]string{
filepath.Join("helm2", "Chart.yaml"): "",
filepath.Join("helm2", "requirements.yaml"): `
# some comment
dependencies:
# this is a comment for my chart
- name: my-chart
# and a version I like
version: 1.0.0
# our enterprise repo
repository: example.com/charts
# an unknown field
whatever: something else
`,
},
updater: &HelmUpdater{
Dependency: "my-chart",
Valuer: value.StringValuer("2.0.0"),
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
filepath.Join("helm2", "requirements.yaml"): `# some comment
dependencies:
# this is a comment for my chart
- name: my-chart
# and a version I like
version: 2.0.0
# our enterprise repo
repository: example.com/charts
# an unknown field
whatever: something else
`,
},
},
{
name: "update a single version in a single chart in helm 3 format",
files: map[string]string{
filepath.Join("helm3", "Chart.yaml"): `
# metadata fields
name: some-chart
version: 1.2.3
# all dependencies
dependencies:
# first dependency
- name: first-chart
version: 1.0.0
# second dependency
- name: second-chart
version: 1.0.0
# third dependency
- name: third-chart
version: 1.0.0
`,
},
updater: &HelmUpdater{
Dependency: "second-chart",
Valuer: value.StringValuer("2.0.0"),
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
filepath.Join("helm3", "Chart.yaml"): `# metadata fields
name: some-chart
version: 1.2.3
# all dependencies
dependencies:
# first dependency
- name: first-chart
version: 1.0.0
# second dependency
- name: second-chart
version: 2.0.0
# third dependency
- name: third-chart
version: 1.0.0
`,
},
},
{
name: "no matching dependency to update",
files: map[string]string{
filepath.Join("no-update", "Chart.yaml"): `
dependencies:
- name: some-chart
version: 1.0.0
`,
},
updater: &HelmUpdater{
Dependency: "not-a-dependency-chart",
Valuer: value.StringValuer("2.0.0"),
},
expected: false,
expectedFiles: map[string]string{
filepath.Join("no-update", "Chart.yaml"): `
dependencies:
- name: some-chart
version: 1.0.0
`,
},
},
{
name: "no version change",
files: map[string]string{
filepath.Join("same-version", "Chart.yaml"): `
dependencies:
- name: already-uptodate-chart
version: 1.0.0
`,
},
updater: &HelmUpdater{
Dependency: "already-uptodate-chart",
Valuer: value.StringValuer("1.0.0"),
},
expected: false,
expectedFiles: map[string]string{
filepath.Join("same-version", "Chart.yaml"): `
dependencies:
- name: already-uptodate-chart
version: 1.0.0
`,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
{
for filename, content := range test.files {
err := os.MkdirAll(filepath.Dir(filepath.Join("testdata", filename)), 0755)
require.NoErrorf(t, err, "can't create testdata directories for %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), []byte(content), 0644)
require.NoErrorf(t, err, "can't write testdata file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
for expectedFilePath, expectedFileContent := range test.expectedFiles {
actualFilePath := filepath.Join("testdata", expectedFilePath)
actualFileContent, err := os.ReadFile(actualFilePath)
require.NoErrorf(t, err, "can't read actual testdata file %s", actualFilePath)
assert.Equalf(t, expectedFileContent, string(actualFileContent), "testdata file %s doesn't match", actualFilePath)
}
}
})
}
}
================================================
FILE: update/regex/regex.go
================================================
// Package regex provides an updater that uses a regex to update files.
package regex
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"github.com/dailymotion-oss/octopilot/internal/glob"
"github.com/dailymotion-oss/octopilot/update/value"
)
// RegexUpdater is an updater that uses a regex to update files.
type RegexUpdater struct {
FilePath string
Pattern string
Regexp *regexp.Regexp
Valuer value.Valuer
}
// NewUpdater builds a new regex updater from the given parameters and valuer
func NewUpdater(params map[string]string, valuer value.Valuer) (*RegexUpdater, error) {
updater := &RegexUpdater{}
updater.FilePath = params["file"]
if len(updater.FilePath) == 0 {
return nil, errors.New("missing file parameter")
}
updater.Pattern = params["pattern"]
if len(updater.Pattern) == 0 {
return nil, errors.New("missing pattern parameter")
}
var err error
updater.Regexp, err = regexp.Compile(updater.Pattern)
if err != nil {
return nil, fmt.Errorf("invalid pattern %s: %w", updater.Pattern, err)
}
if subexp := updater.Regexp.NumSubexp(); subexp != 1 {
return nil, fmt.Errorf("invalid pattern %s: it must have a single parenthesized subexpression, but it has %d", updater.Pattern, subexp)
}
updater.Valuer = valuer
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u RegexUpdater) Update(ctx context.Context, repoPath string) (bool, error) {
value, err := u.Valuer.Value(ctx, repoPath)
if err != nil {
return false, fmt.Errorf("failed to get value: %w", err)
}
filePaths, err := glob.ExpandGlobPattern(repoPath, u.FilePath)
if err != nil {
return false, fmt.Errorf("failed to expand glob pattern %s: %w", u.FilePath, err)
}
var updated bool
for _, filePath := range filePaths {
relFilePath, err := filepath.Rel(repoPath, filePath)
if err != nil {
relFilePath = filePath
}
fileInfo, err := os.Stat(filePath)
if err != nil {
return false, fmt.Errorf("failed to access file %s: %w", relFilePath, err)
}
content, err := os.ReadFile(filePath)
if err != nil {
return false, fmt.Errorf("failed to read file %s: %w", relFilePath, err)
}
if !u.Regexp.Match(content) {
continue
}
var (
updatedContent bytes.Buffer
currentPosition int
)
allIndexes := u.Regexp.FindAllSubmatchIndex(content, -1)
for _, indexes := range allIndexes {
if len(indexes) == 4 {
valueStartPosition := indexes[2]
valueEndPosition := indexes[3]
if _, err = updatedContent.Write(content[currentPosition:valueStartPosition]); err != nil {
return false, fmt.Errorf("failed to copy existing content to the buffer: %w", err)
}
if _, err = updatedContent.WriteString(value); err != nil {
return false, fmt.Errorf("failed to write new value to the buffer: %w", err)
}
currentPosition = valueEndPosition
}
}
if _, err = updatedContent.Write(content[currentPosition:]); err != nil {
return false, fmt.Errorf("failed to copy existing content to the buffer: %w", err)
}
if err = os.WriteFile(filePath, updatedContent.Bytes(), fileInfo.Mode()); err != nil {
return false, fmt.Errorf("failed to write updated content to file %s: %w", relFilePath, err)
}
updated = true
}
return updated, nil
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u RegexUpdater) Message() (title, body string) {
title = fmt.Sprintf("Update %s", u.FilePath)
body = fmt.Sprintf("Updating file(s) `%s` using pattern `%s`", u.FilePath, u.Pattern)
return title, body
}
// String returns a string representation of the updater
func (u RegexUpdater) String() string {
return fmt.Sprintf("Regex[pattern=%s,file=%s]", u.Pattern, u.FilePath)
}
================================================
FILE: update/regex/regex_test.go
================================================
package regex
import (
"context"
"os"
"path/filepath"
"regexp"
"testing"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *RegexUpdater
expectedErrorMsg string
}{
{
name: "valid params with single file",
params: map[string]string{
"file": "helmfile.yaml",
"pattern": `\s+version: \"(.*)\"`,
},
expected: &RegexUpdater{
FilePath: "helmfile.yaml",
Pattern: `\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`\s+version: \"(.*)\"`),
},
},
{
name: "valid params with multiple files using a glob pattern",
params: map[string]string{
"file": "**/helmfile.yaml",
"pattern": `\s+version: \"(.*)\"`,
},
expected: &RegexUpdater{
FilePath: "**/helmfile.yaml",
Pattern: `\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`\s+version: \"(.*)\"`),
},
},
{
name: "nil params",
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory file param",
params: map[string]string{
"pattern": `\s+version: \"(.*)\"`,
},
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory pattern param",
params: map[string]string{
"file": "helmfile.yaml",
},
expectedErrorMsg: "missing pattern parameter",
},
{
name: "invalid pattern",
params: map[string]string{
"file": "helmfile.yaml",
"pattern": `(.*`,
},
expectedErrorMsg: "invalid pattern (.*: error parsing regexp: missing closing ): `(.*`",
},
{
name: "pattern with 0 parenthesized subexpression",
params: map[string]string{
"file": "helmfile.yaml",
"pattern": `.*`,
},
expectedErrorMsg: "invalid pattern .*: it must have a single parenthesized subexpression, but it has 0",
},
{
name: "pattern with 2 parenthesized subexpressions",
params: map[string]string{
"file": "helmfile.yaml",
"pattern": `([0-9]+).*([a-z]+)`,
},
expectedErrorMsg: "invalid pattern ([0-9]+).*([a-z]+): it must have a single parenthesized subexpression, but it has 2",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params, nil)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *RegexUpdater
expected bool
expectedErrorMsg string
expectedFiles map[string]string
}{
{
name: "update multiple versions in a single file",
files: map[string]string{
"helmfile-multiple-versions.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "1.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
updater: &RegexUpdater{
FilePath: "helmfile-multiple-versions.yaml",
Pattern: `\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`\s+version: \"(.*)\"`),
Valuer: value.StringValuer("2.0.0"),
},
expected: true,
expectedFiles: map[string]string{
"helmfile-multiple-versions.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "2.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "2.0.0"
namespace: another-ns
`,
},
},
{
name: "update a single version in a single file",
files: map[string]string{
"helmfile-single-version.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "1.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
updater: &RegexUpdater{
FilePath: "helmfile-single-version.yaml",
Pattern: `chart: example/my-chart\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`chart: example/my-chart\s+version: \"(.*)\"`),
Valuer: value.StringValuer("2.0.0"),
},
expected: true,
expectedFiles: map[string]string{
"helmfile-single-version.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "2.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
},
{
name: "update in multi-line mode in a single file",
files: map[string]string{
"readme.txt": `
whatever content
`,
},
updater: &RegexUpdater{
FilePath: "readme.txt",
Pattern: `(?ms)(.*)`,
Regexp: regexp.MustCompile(`(?ms)(.*)`),
Valuer: value.StringValuer("new content"),
},
expected: true,
expectedFiles: map[string]string{
"readme.txt": `new content`,
},
},
{
name: "no update in a single file",
files: map[string]string{
"helmfile-no-update.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "1.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
updater: &RegexUpdater{
FilePath: "helmfile-no-update.yaml",
Pattern: `chart: example/some-chart\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`chart: example/some-chart\s+version: \"(.*)\"`),
Valuer: value.StringValuer("2.0.0"),
},
expected: false,
expectedFiles: map[string]string{
"helmfile-no-update.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "1.0.0"
namespace: default
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
},
{
name: "updates in multiple files",
files: map[string]string{
"app1/helmfile.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "1.0.0"
namespace: default
`,
"app2/helmfile.yaml": `
releases:
- name: another-release
chart: example/another-chart
version: "1.0.0"
namespace: another-ns
`,
},
updater: &RegexUpdater{
FilePath: "app*/helmfile.yaml",
Pattern: `\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`\s+version: \"(.*)\"`),
Valuer: value.StringValuer("2.0.0"),
},
expected: true,
expectedFiles: map[string]string{
"app1/helmfile.yaml": `
releases:
- name: my-release
chart: example/my-chart
version: "2.0.0"
namespace: default
`,
"app2/helmfile.yaml": `
releases:
- name: another-release
chart: example/another-chart
version: "2.0.0"
namespace: another-ns
`,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
{
for filename, content := range test.files {
err := os.MkdirAll(filepath.Dir(filepath.Join("testdata", filename)), 0755)
require.NoErrorf(t, err, "can't create testdata directories for %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), []byte(content), 0644)
require.NoErrorf(t, err, "can't write testdata file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
actualFilePaths, err := filepath.Glob(filepath.Join("testdata", test.updater.FilePath))
require.NoError(t, err, "can't expand glob pattern for actual testdata file")
for _, actualFilePath := range actualFilePaths {
actualRelFilePath, err := filepath.Rel("testdata", actualFilePath)
require.NoErrorf(t, err, "can't get relative path for actual testdata file %s", actualFilePath)
actualFileContent, err := os.ReadFile(actualFilePath)
require.NoErrorf(t, err, "can't read actual testdata file %s", actualFilePath)
expectedFileContent := test.expectedFiles[actualRelFilePath]
assert.Equalf(t, expectedFileContent, string(actualFileContent), "testdata file %s doesn't match", actualFilePath)
}
}
})
}
}
================================================
FILE: update/regex/testdata/.gitignore
================================================
*
!.gitignore
================================================
FILE: update/sops/sops.go
================================================
// Package sops provides an updater that uses the sops lib to update sops-encrypted files.
package sops
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"go.mozilla.org/sops/v3"
"go.mozilla.org/sops/v3/aes"
"go.mozilla.org/sops/v3/cmd/sops/common"
"go.mozilla.org/sops/v3/cmd/sops/formats"
"go.mozilla.org/sops/v3/keyservice"
"github.com/dailymotion-oss/octopilot/internal/glob"
"github.com/dailymotion-oss/octopilot/update/value"
)
// SopsUpdater is an updater that uses the sops lib to update sops-encrypted files.
type SopsUpdater struct {
FilePath string
Key string
Valuer value.Valuer
}
// NewUpdater builds a new SOPS updater from the given parameters and valuer
func NewUpdater(params map[string]string, valuer value.Valuer) (*SopsUpdater, error) {
updater := &SopsUpdater{}
updater.FilePath = params["file"]
if len(updater.FilePath) == 0 {
return nil, errors.New("missing file parameter")
}
updater.Key = params["key"]
if len(updater.Key) == 0 {
return nil, errors.New("missing key parameter")
}
updater.Valuer = valuer
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u SopsUpdater) Update(ctx context.Context, repoPath string) (bool, error) {
var (
cipher = aes.NewCipher()
svcs = []keyservice.KeyServiceClient{keyservice.NewLocalClient()}
)
value, err := u.Valuer.Value(ctx, repoPath)
if err != nil {
return false, fmt.Errorf("failed to get value: %w", err)
}
filePaths, err := glob.ExpandGlobPattern(repoPath, u.FilePath)
if err != nil {
return false, fmt.Errorf("failed to expand glob pattern %s: %w", u.FilePath, err)
}
var updated bool
for _, filePath := range filePaths {
relFilePath, err := filepath.Rel(repoPath, filePath)
if err != nil {
relFilePath = filePath
}
fileInfo, err := os.Stat(filePath)
if err != nil {
return false, fmt.Errorf("failed to access file %s: %w", relFilePath, err)
}
var (
format = formats.FormatForPath(filePath)
store = common.StoreForFormat(format)
)
tree, err := common.LoadEncryptedFileWithBugFixes(common.GenericDecryptOpts{
Cipher: cipher,
InputStore: store,
InputPath: filePath,
KeyServices: svcs,
})
if err != nil {
return false, fmt.Errorf("failed to load encrypted file %s: %w", filePath, err)
}
dataKey, err := common.DecryptTree(common.DecryptTreeOpts{
Cipher: cipher,
Tree: tree,
KeyServices: svcs,
})
if err != nil {
return false, fmt.Errorf("failed to decrypt tree for %s: %w", filePath, err)
}
originalData, err := store.EmitPlainFile(tree.Branches)
if err != nil {
return false, fmt.Errorf("failed to emit original tree for %s: %w", filePath, err)
}
path := convertKeyToPath(u.Key)
for i := range tree.Branches {
newTree := tree.Branches[i].Set(path, value)
// fix for https://github.com/mozilla/sops/issues/407
// to be removed once https://github.com/mozilla/sops/pull/899 gets merged & released
if previousTreeHasBeenErased(tree.Branches[i], newTree) {
// if the path top-level element doesn't exist, it will return a new tree with only our path
// the workaround is to add a single-level item first, and then the whole new branch
rootEntry := []interface{}{
path[0],
}
newTree = tree.Branches[i].Set(rootEntry, value)
newTree = newTree.Set(path, value)
}
tree.Branches[i] = newTree
}
// check if we updated something or not, before re-encrypting...
updatedData, err := store.EmitPlainFile(tree.Branches)
if err != nil {
return false, fmt.Errorf("failed to emit updated tree for %s: %w", filePath, err)
}
if string(updatedData) == string(originalData) {
continue
}
err = common.EncryptTree(common.EncryptTreeOpts{
DataKey: dataKey,
Tree: tree,
Cipher: cipher,
})
if err != nil {
return false, fmt.Errorf("failed to encrypt tree for %s: %w", filePath, err)
}
encryptedFile, err := store.EmitEncryptedFile(*tree)
if err != nil {
return false, fmt.Errorf("failed to generate re-encrypted file %s: %w", filePath, err)
}
err = os.WriteFile(filePath, encryptedFile, fileInfo.Mode())
if err != nil {
return false, fmt.Errorf("failed to write re-encrypted data to file %s: %w", filePath, err)
}
updated = true
}
return updated, nil
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u SopsUpdater) Message() (title, body string) {
title = fmt.Sprintf("Update %s %s", u.FilePath, u.Key)
body = fmt.Sprintf("Updating sops-encrypted file `%s` key `%s`", u.FilePath, u.Key)
return title, body
}
// String returns a string representation of the updater
func (u SopsUpdater) String() string {
return fmt.Sprintf("Sops[key=%s,file=%s]", u.Key, u.FilePath)
}
func convertKeyToPath(key string) []interface{} {
path := make([]interface{}, 0)
for _, entry := range strings.Split(key, ".") {
path = append(path, entry)
}
return path
}
func previousTreeHasBeenErased(previous, next sops.TreeBranch) bool {
if len(next) != 1 {
// when the previous tree is "erased", the new one will have a single entry
return false
}
if len(previous) != 1 {
// if the tree size has changed, the previous tree has been erased
return true
}
if reflect.DeepEqual(previous[0].Key, next[0].Key) {
// same size, same key -> it's a simple tree with 1 element which hasn't changed
return false
}
// otherwise, it's a 1 element tree which has changed
return true
}
================================================
FILE: update/sops/sops_test.go
================================================
package sops
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.mozilla.org/sops/v3"
"go.mozilla.org/sops/v3/aes"
"go.mozilla.org/sops/v3/age"
"go.mozilla.org/sops/v3/cmd/sops/common"
"go.mozilla.org/sops/v3/cmd/sops/formats"
"go.mozilla.org/sops/v3/decrypt"
"go.mozilla.org/sops/v3/keys"
"github.com/dailymotion-oss/octopilot/update/value"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *SopsUpdater
expectedErrorMsg string
}{
{
name: "valid params",
params: map[string]string{
"file": "secrets.yaml",
"key": "path.to.key",
},
expected: &SopsUpdater{
FilePath: "secrets.yaml",
Key: "path.to.key",
},
},
{
name: "nil params",
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory file param",
params: map[string]string{
"key": "path.to.key",
},
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory key param",
params: map[string]string{
"file": "secrets.yaml",
},
expectedErrorMsg: "missing key parameter",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params, nil)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *SopsUpdater
expected bool
expectedErrorMsg string
expectedFiles map[string]string
}{
{
name: "update an existing secret value",
files: map[string]string{
"existing-secrets.yaml": `app:
token: old-token
`,
},
updater: &SopsUpdater{
FilePath: "existing-secrets.yaml",
Key: "app.token",
Valuer: value.StringValuer("new-token"),
},
expected: true,
expectedFiles: map[string]string{
"existing-secrets.yaml": `app:
token: new-token
`,
},
},
{
name: "no change to an existing secret value",
files: map[string]string{
"no-changes-secrets.yaml": `app:
token: good-token
`,
},
updater: &SopsUpdater{
FilePath: "no-changes-secrets.yaml",
Key: "app.token",
Valuer: value.StringValuer("good-token"),
},
expected: false,
expectedFiles: map[string]string{
"no-changes-secrets.yaml": `app:
token: good-token
`,
},
},
{
name: "add a new secret value",
files: map[string]string{
"new-secrets.yaml": `first-app:
token: some-token
`,
},
updater: &SopsUpdater{
FilePath: "new-secrets.yaml",
Key: "second-app.token",
Valuer: value.StringValuer("new-token"),
},
expected: true,
expectedFiles: map[string]string{
"new-secrets.yaml": `first-app:
token: some-token
second-app:
token: new-token
`,
},
},
{
name: "add a new deeply nested secret value",
files: map[string]string{
"new-secrets-deeply-nested.yaml": `first-app:
token: some-token
`,
},
updater: &SopsUpdater{
FilePath: "new-secrets-deeply-nested.yaml",
Key: "second-app.path.to.my.token",
Valuer: value.StringValuer("new-token"),
},
expected: true,
expectedFiles: map[string]string{
"new-secrets-deeply-nested.yaml": `first-app:
token: some-token
second-app:
path:
to:
my:
token: new-token
`,
},
},
{
name: "add a new root secret value",
files: map[string]string{
"new-secrets-root.yaml": `first-app:
token: some-token
`,
},
updater: &SopsUpdater{
FilePath: "new-secrets-root.yaml",
Key: "newtoken",
Valuer: value.StringValuer("new-token-value"),
},
expected: true,
expectedFiles: map[string]string{
"new-secrets-root.yaml": `first-app:
token: some-token
newtoken: new-token-value
`,
},
},
}
// we use https://age-encryption.org to encrypt/decrypt
// an age key for unit-tests purpose was created with the following command:
// $ age-keygen -o testdata/age.key
// if you need to regenerate it, you'll also need to update its public key here:
const (
ageKeyFile = "testdata/age.key"
agePublicKey = "age16fvu9n7dkhdkrrrtfwctfzf94zvh58ars22k2fv9rmhkr9rkfszsyw8zzq"
)
os.Setenv("SOPS_AGE_KEY_FILE", ageKeyFile)
masterKeys, err := age.MasterKeysFromRecipients(agePublicKey)
require.NoErrorf(t, err, "can't get age master keys from pubkey %s", agePublicKey)
require.Len(t, masterKeys, 1, "expected one master key from pubkey %s", agePublicKey)
masterKey := masterKeys[0]
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
// setup
{
for filename, content := range test.files {
format := formats.FormatForPath(filename)
store := common.StoreForFormat(format)
branches, err := store.LoadPlainFile([]byte(content))
require.NoErrorf(t, err, "can't parse data for file %s", filename)
tree := sops.Tree{
FilePath: filename,
Metadata: sops.Metadata{
KeyGroups: []sops.KeyGroup{
[]keys.MasterKey{masterKey},
},
Version: "3.5.0",
},
Branches: branches,
}
dataKey, errs := tree.GenerateDataKey()
require.Len(t, errs, 0)
tree.Metadata.DataKey = dataKey
err = common.EncryptTree(common.EncryptTreeOpts{
Cipher: aes.NewCipher(),
DataKey: dataKey,
Tree: &tree,
})
require.NoErrorf(t, err, "failed to encrypt file %s", filename)
encryptedData, err := store.EmitEncryptedFile(tree)
require.NoErrorf(t, err, "failed to generate encrypted file %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), encryptedData, 0644)
require.NoErrorf(t, err, "failed to write encrypted data to file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
actualEncryptedData, err := os.ReadFile(filepath.Join("testdata", test.updater.FilePath))
require.NoError(t, err, "can't read actual encrypted file")
actualCleartextData, err := decrypt.DataWithFormat(actualEncryptedData, formats.FormatForPath(test.updater.FilePath))
require.NoError(t, err, "can't decrypt actual encrypted content")
expectedFileContent := test.expectedFiles[test.updater.FilePath]
assert.Equal(t, expectedFileContent, string(actualCleartextData))
}
})
}
}
================================================
FILE: update/sops/testdata/.gitignore
================================================
*.yaml
================================================
FILE: update/sops/testdata/age.key
================================================
# created: 2021-07-02T10:33:34+02:00
# public key: age16fvu9n7dkhdkrrrtfwctfzf94zvh58ars22k2fv9rmhkr9rkfszsyw8zzq
AGE-SECRET-KEY-1NVURWLQX30ZZRMEXZHP2QWGNT3U0W9JYFLZVHNLA2WXD72XSDAKSRTM97U
================================================
FILE: update/updater.go
================================================
package update
import (
"context"
"fmt"
"regexp"
"strings"
"github.com/dailymotion-oss/octopilot/internal/parameters"
"github.com/dailymotion-oss/octopilot/update/exec"
"github.com/dailymotion-oss/octopilot/update/helm"
"github.com/dailymotion-oss/octopilot/update/regex"
"github.com/dailymotion-oss/octopilot/update/sops"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/dailymotion-oss/octopilot/update/yaml"
"github.com/dailymotion-oss/octopilot/update/yq"
)
var (
// name(params)
updaterRegexp = regexp.MustCompile(`^(?P[a-z]+)\((?P.+)\)`)
// name(params)=value
updaterWithValueRegexp = regexp.MustCompile(`^(?P[a-z]+)\((?P.+)\)=(?P.*)$`)
)
// Updater updates a git repository
type Updater interface {
// Update updates the repository cloned at the given path, and returns true if changes have been made
Update(ctx context.Context, repoPath string) (bool, error)
// Message returns the default title and body that should be used in the commits / pull requests
Message() (title, body string)
// String returns a string representation of the updater
String() string
}
// Parse parses a set of updates defined as string - from the CLI for example - and returns properly formatted Updaters.
// expected syntax is documented in the user documentation: docs/current-version/content/updaters/
func Parse(updates []string) ([]Updater, error) {
var updaters []Updater
for _, update := range updates {
if len(strings.TrimSpace(update)) == 0 {
continue
}
matches := updaterRegexp.FindStringSubmatch(update)
if len(matches) < 2 {
return nil, fmt.Errorf("invalid syntax for %s: missing updater name", update)
}
updaterName := matches[1]
var paramsStr, valueStr string
switch updaterName {
case "exec", "yq":
if len(matches) < 3 {
return nil, fmt.Errorf("invalid syntax for %s: found %d matches instead of 3: %v", update, len(matches), matches)
}
paramsStr = matches[2]
default:
matches = updaterWithValueRegexp.FindStringSubmatch(update)
if len(matches) < 4 {
return nil, fmt.Errorf("invalid syntax for %s: found %d matches instead of 4: %v", update, len(matches), matches)
}
paramsStr = matches[2]
valueStr = matches[3]
}
// hack to fix the value if coming from shell expansion, which adds quotes around it
if strings.HasPrefix(valueStr, "\"") && strings.HasSuffix(valueStr, "\"") {
valueStr = strings.TrimPrefix(valueStr, "\"")
valueStr = strings.TrimSuffix(valueStr, "\"")
}
params := parameters.Parse(paramsStr)
valuer, err := value.ParseValuer(valueStr)
if err != nil {
return nil, fmt.Errorf("failed to parse value %s for %s: %w", valueStr, updaterName, err)
}
var updater Updater
switch updaterName {
case "regex":
updater, err = regex.NewUpdater(params, valuer)
case "sops":
updater, err = sops.NewUpdater(params, valuer)
case "helm":
updater, err = helm.NewUpdater(params, valuer)
case "yaml":
updater, err = yaml.NewUpdater(params, valuer)
case "yq":
updater, err = yq.NewUpdater(params)
case "exec":
updater, err = exec.NewUpdater(params)
default:
return nil, fmt.Errorf("unknown updater %s", updaterName)
}
if err != nil {
return nil, fmt.Errorf("failed to create an updater instance for %s: %w", updaterName, err)
}
updaters = append(updaters, updater)
}
return updaters, nil
}
================================================
FILE: update/updater_test.go
================================================
package update
import (
"regexp"
"testing"
"github.com/dailymotion-oss/octopilot/update/exec"
"github.com/dailymotion-oss/octopilot/update/helm"
"github.com/dailymotion-oss/octopilot/update/regex"
"github.com/dailymotion-oss/octopilot/update/sops"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/dailymotion-oss/octopilot/update/yaml"
"github.com/dailymotion-oss/octopilot/update/yq"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
t.Parallel()
tests := []struct {
name string
updates []string
expected []Updater
expectedErrorMsg string
}{
{
name: "nil input",
},
{
name: "empty input",
updates: []string{""},
},
{
name: "invalid input",
updates: []string{"whatever"},
expectedErrorMsg: "invalid syntax for whatever: missing updater name",
},
{
name: "invalid updater syntax input",
updates: []string{"sops(key=value)"},
expectedErrorMsg: "invalid syntax for sops(key=value): found 0 matches instead of 4: []",
},
{
name: "invalid regex updater syntax input",
updates: []string{"regex(key=value)=value"},
expectedErrorMsg: "failed to create an updater instance for regex: missing file parameter",
},
{
name: "invalid valuer syntax input",
updates: []string{"helm(dependency=my-chart)=whatever(key=value)"},
expectedErrorMsg: "failed to parse value whatever(key=value) for helm: unknown valuer whatever",
},
{
name: "unknown updater",
updates: []string{"whatever(key=value)=value"},
expectedErrorMsg: "unknown updater whatever",
},
{
name: "single exec updater",
updates: []string{"exec(cmd=something)"},
expected: []Updater{
&exec.ExecUpdater{
Command: "something",
},
},
},
{
name: "single helm updater",
updates: []string{"helm(dependency=my-chart)=1.2.3"},
expected: []Updater{
&helm.HelmUpdater{
Dependency: "my-chart",
Valuer: value.StringValuer("1.2.3"),
Indent: 2,
},
},
},
{
name: "single helm deleter",
updates: []string{"helm(dependency=my-chart)="},
expected: []Updater{
&helm.HelmUpdater{
Dependency: "my-chart",
Valuer: value.StringValuer(""),
Indent: 2,
},
},
},
{
name: "single yq updater",
updates: []string{`yq(file=values.yaml,expression='.path.to.subkey = "value"')`},
expected: []Updater{
&yq.YQUpdater{
FilePath: "values.yaml",
Expression: `.path.to.subkey = "value"`,
Output: "",
OutputFormat: yqlib.YamlOutputFormat,
Trim: false,
UnwrapScalar: true,
Indent: 2,
},
},
},
{
name: "single regex updater",
updates: []string{`regex(file=helmfile.yaml,pattern='chart: example/my-chart\s+version: \"(.*)\"')=1.2.3`},
expected: []Updater{
®ex.RegexUpdater{
FilePath: "helmfile.yaml",
Pattern: `chart: example/my-chart\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`chart: example/my-chart\s+version: \"(.*)\"`),
Valuer: value.StringValuer("1.2.3"),
},
},
},
{
name: "single regex deleter",
updates: []string{`regex(file=helmfile.yaml,pattern='chart: example/my-chart\s+version: \"(.*)\"')=`},
expected: []Updater{
®ex.RegexUpdater{
FilePath: "helmfile.yaml",
Pattern: `chart: example/my-chart\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`chart: example/my-chart\s+version: \"(.*)\"`),
Valuer: value.StringValuer(""),
},
},
},
{
name: "complex yaml updater",
updates: []string{"yaml(file=values.yaml,path='array.(key==prefix*).**.subkey',trim=true,indent=4)=1.2.3"},
expected: []Updater{
&yaml.YamlUpdater{
FilePath: "values.yaml",
Path: "array.(key==prefix*).**.subkey",
Valuer: value.StringValuer("1.2.3"),
Trim: true,
Indent: 4,
},
},
},
{
name: "regex and sops updaters",
updates: []string{
`regex(file=helmfile.yaml,pattern='chart: example/my-chart\s+version: \"(.*)\"')=file(path=VERSION)`,
`sops(file=certificates/secrets.yaml,key=certificates.b64encKey)=e30k`,
},
expected: []Updater{
®ex.RegexUpdater{
FilePath: "helmfile.yaml",
Pattern: `chart: example/my-chart\s+version: \"(.*)\"`,
Regexp: regexp.MustCompile(`chart: example/my-chart\s+version: \"(.*)\"`),
Valuer: &value.FileValuer{
Path: "VERSION",
},
},
&sops.SopsUpdater{
FilePath: "certificates/secrets.yaml",
Key: "certificates.b64encKey",
Valuer: value.StringValuer("e30k"),
},
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := Parse(test.updates)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Empty(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
================================================
FILE: update/value/doc.go
================================================
// Package value provides diffferent implementations to retrieve the value to replace while updating files.
package value
================================================
FILE: update/value/file.go
================================================
package value
import (
"context"
"errors"
"fmt"
"os"
"path/filepath"
)
// FileValuer is a valuer that returns the content of a specific file.
type FileValuer struct {
Path string
}
func newFileValuer(params map[string]string) (*FileValuer, error) {
valuer := &FileValuer{}
valuer.Path = params["path"]
if len(valuer.Path) == 0 {
return nil, errors.New("missing path parameter")
}
return valuer, nil
}
// Value returns the value to replace while updating files in the given repository.
func (v FileValuer) Value(_ context.Context, repoPath string) (string, error) {
filePath := v.Path
if !filepath.IsAbs(filePath) {
filePath = filepath.Join(repoPath, v.Path)
}
content, err := os.ReadFile(filePath)
if err != nil {
return "", fmt.Errorf("failed to read file %s: %w", v.Path, err)
}
return string(content), nil
}
================================================
FILE: update/value/file_test.go
================================================
package value
import (
"context"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestFileValuerValue(t *testing.T) {
t.Parallel()
tests := []struct {
name string
path string
expected string
expectedErrorMsg string
}{
{
name: "file does not exists",
path: "does-not-exists",
expectedErrorMsg: "failed to read file does-not-exists: open testdata/does-not-exists: no such file or directory",
},
{
name: "regular file",
path: "test.txt",
expected: "some content",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
valuer := FileValuer{
Path: test.path,
}
actual, err := valuer.Value(context.Background(), filepath.Join(".", "testdata"))
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Empty(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
================================================
FILE: update/value/string.go
================================================
package value
import (
"context"
)
// StringValuer is a valuer to replace a string.
type StringValuer string
// Value returns the value to replace while updating files in the given repository.
func (v StringValuer) Value(_ context.Context, _ string) (string, error) {
return string(v), nil
}
================================================
FILE: update/value/string_test.go
================================================
package value
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestStringValuerValue(t *testing.T) {
t.Parallel()
expected := "some value"
valuer := StringValuer(expected)
actual, err := valuer.Value(context.Background(), ".")
require.NoError(t, err)
assert.Equal(t, expected, actual)
}
================================================
FILE: update/value/testdata/test.txt
================================================
some content
================================================
FILE: update/value/valuer.go
================================================
package value
import (
"context"
"fmt"
"regexp"
"github.com/dailymotion-oss/octopilot/internal/parameters"
)
var (
// name(params)
valueRegexp = regexp.MustCompile(`(?P[a-z]+)\((?P.+)\)`)
)
// Valuer is the interface for retrieving a value to replace while updating files.
type Valuer interface {
// Value returns the value to replace while updating files in the given repository.
Value(ctx context.Context, repoPath string) (string, error)
}
// ParseValuer parses the valuer defined as string - from the CLI for example - and returns a properly formatted valuer.
func ParseValuer(valueStr string) (Valuer, error) {
matches := valueRegexp.FindStringSubmatch(valueStr)
if len(matches) == 0 {
return StringValuer(valueStr), nil
}
if len(matches) < 3 {
return nil, fmt.Errorf("invalid syntax for %s", valueStr)
}
valuerName := matches[1]
paramsStr := matches[2]
params := parameters.Parse(paramsStr)
var (
valuer Valuer
err error
)
switch valuerName {
case "file":
valuer, err = newFileValuer(params)
default:
return nil, fmt.Errorf("unknown valuer %s", valuerName)
}
if err != nil {
return nil, fmt.Errorf("failed to create a valuer instance for %s: %w", valuerName, err)
}
return valuer, nil
}
================================================
FILE: update/value/valuer_test.go
================================================
package value
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParse(t *testing.T) {
t.Parallel()
tests := []struct {
name string
value string
expected Valuer
expectedErrorMsg string
}{
{
name: "nil input",
expected: StringValuer(""),
},
{
name: "empty input",
value: "",
expected: StringValuer(""),
},
{
name: "unknown valuer",
value: "whatever(key=value)",
expectedErrorMsg: "unknown valuer whatever",
},
{
name: "string value",
value: "1.2.3",
expected: StringValuer("1.2.3"),
},
{
name: "file value",
value: "file(path=/path/to/something)",
expected: &FileValuer{
Path: "/path/to/something",
},
},
{
name: "file value without path",
value: "file(path=)",
expectedErrorMsg: "failed to create a valuer instance for file: missing path parameter",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := ParseValuer(test.value)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Empty(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
================================================
FILE: update/yaml/testdata/.gitignore
================================================
*
!.gitignore
================================================
FILE: update/yaml/yaml.go
================================================
// Package yaml provides an updater that uses the yq lib to update YAML files.
package yaml
import (
"bytes"
"context"
"errors"
"fmt"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"github.com/dailymotion-oss/octopilot/internal/glob"
"github.com/dailymotion-oss/octopilot/internal/yaml"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/mikefarah/yq/v4/pkg/yqlib"
gologging "gopkg.in/op/go-logging.v1"
)
func init() {
gologging.SetLevel(gologging.CRITICAL, "yq-lib")
yqlib.InitExpressionParser()
}
// YamlUpdater is an updater that uses the yq lib to update YAML files.
type YamlUpdater struct {
FilePath string
Path string
AutoCreate bool
Style string
Trim bool
Indent int
Valuer value.Valuer
}
// NewUpdater builds a new YAML updater from the given parameters and valuer
func NewUpdater(params map[string]string, valuer value.Valuer) (*YamlUpdater, error) {
updater := &YamlUpdater{}
updater.FilePath = params["file"]
if len(updater.FilePath) == 0 {
return nil, errors.New("missing file parameter")
}
updater.Path = params["path"]
if len(updater.Path) == 0 {
return nil, errors.New("missing path parameter")
}
updater.Indent, _ = strconv.Atoi(params["indent"])
if updater.Indent <= 0 {
updater.Indent = 2
}
updater.AutoCreate, _ = strconv.ParseBool(params["create"])
updater.Trim, _ = strconv.ParseBool(params["trim"])
updater.Style = params["style"]
updater.Valuer = valuer
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u *YamlUpdater) Update(ctx context.Context, repoPath string) (bool, error) {
value, err := u.Valuer.Value(ctx, repoPath)
if err != nil {
return false, fmt.Errorf("failed to get value: %w", err)
}
expression, expressionNode, err := u.yqExpression(value)
if err != nil {
return false, fmt.Errorf("failed to parse yq expression %s: %w", expression, err)
}
filePaths, err := glob.ExpandGlobPattern(repoPath, u.FilePath)
if err != nil {
return false, fmt.Errorf("failed to expand glob pattern %s: %w", u.FilePath, err)
}
const (
yamlColorise = false
yamlPrintDocSeparators = true
yamlUnwrapScalar = false
)
var (
yamlEncoder = yqlib.NewYamlEncoder(u.Indent, yamlColorise, yamlPrintDocSeparators, yamlUnwrapScalar)
streamEvaluator = yqlib.NewStreamEvaluator()
updated = false
)
for _, filePath := range filePaths {
relFilePath, err := filepath.Rel(repoPath, filePath)
if err != nil {
relFilePath = filePath
}
fileInfo, err := os.Stat(filePath)
if err != nil {
return false, fmt.Errorf("failed to access file %s: %w", relFilePath, err)
}
fileData, err := os.ReadFile(filePath)
if err != nil {
return false, fmt.Errorf("failed to read file %s: %w", relFilePath, err)
}
reader, leadingContent, err := yaml.ExtractLeadingContentForYQ(bytes.NewReader(fileData))
if err != nil {
return false, fmt.Errorf("failed to extract leading content from file %s: %w", relFilePath, err)
}
buffer := new(bytes.Buffer)
printer := yqlib.NewPrinter(yamlEncoder, yqlib.NewSinglePrinterWriter(buffer))
_, err = streamEvaluator.Evaluate(relFilePath, reader, expressionNode, printer, leadingContent, yqlib.NewYamlDecoder())
if err != nil {
return false, fmt.Errorf("failed to evaluate expression `%s` for file %s: %w", expression, filePath, err)
}
if u.Trim {
buffer = bytes.NewBuffer(bytes.TrimSpace(buffer.Bytes()))
}
if reflect.DeepEqual(fileData, buffer.Bytes()) {
continue
}
err = os.WriteFile(filePath, buffer.Bytes(), fileInfo.Mode())
if err != nil {
return false, fmt.Errorf("failed to write file %s: %w", filePath, err)
}
updated = true
}
return updated, nil
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u *YamlUpdater) Message() (title, body string) {
title = fmt.Sprintf("Update %s", u.FilePath)
body = fmt.Sprintf("Updating path `%s` in file(s) `%s`", u.Path, u.FilePath)
return title, body
}
// String returns a string representation of the updater
func (u *YamlUpdater) String() string {
return fmt.Sprintf("YAML[path=%s,file=%s,style=%s,create=%v,trim=%v,indent=%v]", u.Path, u.FilePath, u.Style, u.AutoCreate, u.Trim, u.Indent)
}
func (u *YamlUpdater) yqExpression(value string) (string, *yqlib.ExpressionNode, error) {
var (
parser = yqlib.ExpressionParser
rawExpression string
)
if _, err := parser.ParseExpression(u.Path); err == nil && strings.HasPrefix(u.Path, ".") {
// we have a valid yq v4 expression - that starts with a dot
rawExpression = u.Path
} else {
// most likely an old v3 path format, let's convert it to a valid v4 path
rawExpression = convertYqExpressionToV4(u.Path)
}
// add the assignment operator to set the new value
expression := fmt.Sprintf(`(%s) ref $x | $x = %q`, rawExpression, value)
if u.AutoCreate {
// ensure the new path is created first (the `... ref $x | $x = ...` doesn't create it)
expression = fmt.Sprintf(`%s = %q | %s`, rawExpression, value, expression)
}
if u.Style != "" {
// set the style if needed
expression = fmt.Sprintf(`%s | $x style=%q`, expression, u.Style)
}
expressionNode, err := parser.ParseExpression(expression)
return expression, expressionNode, err
}
// convertYqExpressionToV4 converts from the old yq v3 format to the new yq v4 format
func convertYqExpressionToV4(v3Format string) string {
if !strings.ContainsAny(v3Format, "()=") {
// this is a simple path expression to traverse a hierarchy
expression := v3Format
if !strings.HasPrefix(expression, ".") {
// let's ensure it starts with a dot
expression = "." + expression
}
return expression
}
if strings.Contains(v3Format, "(") && strings.Contains(v3Format, ")") && strings.Contains(v3Format, "==") {
// this is a path selection in an array, such as 'array.(name==foo).field'
// let's rewrite it as '.array[] | select(.name == "foo") | .field'
return fmt.Sprintf(`.%s[] | select(.%s == %q) | %s`,
strings.TrimSuffix(strings.SplitN(v3Format, "(", 2)[0], "."),
strings.SplitN(strings.SplitN(v3Format, "(", 2)[1], "==", 2)[0],
strings.SplitN(strings.SplitN(v3Format, "==", 2)[1], ")", 2)[0],
strings.SplitN(v3Format, ")", 2)[1],
)
}
return ""
}
================================================
FILE: update/yaml/yaml_test.go
================================================
package yaml
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/dailymotion-oss/octopilot/update/value"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *YamlUpdater
expectedErrorMsg string
}{
{
name: "valid params with single file",
params: map[string]string{
"file": "values.yaml",
"path": "level1.level2",
"create": "true",
"style": "double",
"trim": "true",
"indent": "4",
},
expected: &YamlUpdater{
FilePath: "values.yaml",
Path: "level1.level2",
AutoCreate: true,
Style: "double",
Trim: true,
Indent: 4,
},
},
{
name: "invalid create boolean value",
params: map[string]string{
"file": "values.yaml",
"path": "level1.level2",
"create": "maybe",
"indent": "not-an-int",
},
expected: &YamlUpdater{
FilePath: "values.yaml",
Path: "level1.level2",
AutoCreate: false,
Trim: false,
Indent: 2,
},
},
{
name: "valid params with multiple files using a glob pattern",
params: map[string]string{
"file": "**/values.yaml",
"path": "level1.level2",
},
expected: &YamlUpdater{
FilePath: "**/values.yaml",
Path: "level1.level2",
Indent: 2,
},
},
{
name: "nil params",
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory file param",
params: map[string]string{
"path": "level1.level2",
},
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory path param",
params: map[string]string{
"file": "values.yaml",
},
expectedErrorMsg: "missing path parameter",
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params, nil)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *YamlUpdater
expected bool
expectedErrorMsg string
expectedFiles map[string]string
}{
{
name: "update simple value in a single file",
files: map[string]string{
"basic-values.yaml": `# top level comment
# a simple key
key: value
# an object
object:
# with a key we want to update
mykey: some-value
# and another one we don't care about
anotherkey: another-value
`,
},
updater: &YamlUpdater{
FilePath: "basic-values.yaml",
Path: "object.mykey",
Valuer: value.StringValuer("updated-value"),
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"basic-values.yaml": `# top level comment
# a simple key
key: value
# an object
object:
# with a key we want to update
mykey: updated-value
# and another one we don't care about
anotherkey: another-value
`,
},
},
{
name: "update complex value in a single file",
files: map[string]string{
"complex-values.yaml": `
array:
- name: first entry
key: first value
- name: my entry
key: old value
- name: third entry
key: third value
`,
},
updater: &YamlUpdater{
FilePath: "complex-values.yaml",
Path: "array.(name==my entry).key",
Valuer: value.StringValuer("new value"),
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"complex-values.yaml": `array:
- name: first entry
key: first value
- name: my entry
key: new value
- name: third entry
key: third value
`,
},
},
{
name: "update multiple values in a single file",
files: map[string]string{
"multiple-values.yaml": `
array:
- name: first entry
ref: abc123
key: first value
- name: second entry
ref: xyz789
key: second value
- name: third entry
ref: abc456
key: third value
`,
},
updater: &YamlUpdater{
FilePath: "multiple-values.yaml",
Path: "array.(ref==abc*).key",
Valuer: value.StringValuer("updated value"),
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"multiple-values.yaml": `array:
- name: first entry
ref: abc123
key: updated value
- name: second entry
ref: xyz789
key: second value
- name: third entry
ref: abc456
key: updated value
`,
},
},
{
name: "update with custom style",
files: map[string]string{
"custom-style.yaml": `
# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "custom-style.yaml",
Path: "key",
Style: "double",
Valuer: value.StringValuer("updated-value"),
},
expected: true,
expectedFiles: map[string]string{
"custom-style.yaml": `
# a simple key
key: "updated-value"
`,
},
},
{
name: "update with folded style",
files: map[string]string{
"folded-style.yaml": `# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "folded-style.yaml",
Path: "key",
Style: "folded",
Valuer: value.StringValuer("updated-value"),
},
expected: true,
expectedFiles: map[string]string{
"folded-style.yaml": `# a simple key
key: >-
updated-value
`,
},
},
{
name: "trim file",
files: map[string]string{
"trim.yaml": `
# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "trim.yaml",
Path: "key",
Trim: true,
Valuer: value.StringValuer("updated-value"),
},
expected: true,
expectedFiles: map[string]string{
"trim.yaml": `# a simple key
key: updated-value`,
},
},
{
name: "create missing key/value in a single file",
files: map[string]string{
"missing-key-values.yaml": `# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "missing-key-values.yaml",
Path: "object.mykey",
AutoCreate: true,
Valuer: value.StringValuer("new-value"),
},
expected: true,
expectedFiles: map[string]string{
"missing-key-values.yaml": `# a simple key
key: value
object:
mykey: new-value
`,
},
},
{
name: "no changes if new key but no auto-create",
files: map[string]string{
"no-changes-without-auto-create.yaml": `# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "no-changes-without-auto-create.yaml",
Path: "object.mykey",
Valuer: value.StringValuer("value"),
},
expected: false,
expectedFiles: map[string]string{
"no-changes-without-auto-create.yaml": `# a simple key
key: value
`,
},
},
{
name: "no changes",
files: map[string]string{
"no-changes.yaml": `# a simple key
key: value
`,
},
updater: &YamlUpdater{
FilePath: "no-changes.yaml",
Path: "key",
Valuer: value.StringValuer("value"),
},
expected: false,
expectedFiles: map[string]string{
"no-changes.yaml": `# a simple key
key: value
`,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
{
for filename, content := range test.files {
err := os.MkdirAll(filepath.Dir(filepath.Join("testdata", filename)), 0755)
require.NoErrorf(t, err, "can't create testdata directories for %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), []byte(content), 0644)
require.NoErrorf(t, err, "can't write testdata file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
actualFilePaths, err := filepath.Glob(filepath.Join("testdata", test.updater.FilePath))
require.NoError(t, err, "can't expand glob pattern for actual testdata file")
for _, actualFilePath := range actualFilePaths {
actualRelFilePath, err := filepath.Rel("testdata", actualFilePath)
require.NoErrorf(t, err, "can't get relative path for actual testdata file %s", actualFilePath)
actualFileContent, err := os.ReadFile(actualFilePath)
require.NoErrorf(t, err, "can't read actual testdata file %s", actualFilePath)
expectedFileContent := test.expectedFiles[actualRelFilePath]
assert.Equalf(t, expectedFileContent, string(actualFileContent), "testdata file %s doesn't match", actualFilePath)
}
}
})
}
}
func TestYqExpression(t *testing.T) {
t.Parallel()
tests := []struct {
name string
updater YamlUpdater
value string
expectedExpression string
expectedErrorMsg string
}{
{
name: "simple v4 path",
updater: YamlUpdater{
Path: ".version",
},
value: "1.2.3",
expectedExpression: `(.version) ref $x | $x = "1.2.3"`,
},
{
name: "v4 path with custom style",
updater: YamlUpdater{
Path: ".path.to.version",
Style: "double",
},
value: "1.2.3",
expectedExpression: `(.path.to.version) ref $x | $x = "1.2.3" | $x style="double"`,
},
{
name: "v4 path with auto-create and custom style",
updater: YamlUpdater{
Path: ".path.to.version",
Style: "folded",
AutoCreate: true,
},
value: "1.2.3",
expectedExpression: `.path.to.version = "1.2.3" | (.path.to.version) ref $x | $x = "1.2.3" | $x style="folded"`,
},
{
name: "complex v4 path",
updater: YamlUpdater{
Path: `.releases[] | select(.chart == "repo/chart") | .version`,
},
value: "1.2.3",
expectedExpression: `(.releases[] | select(.chart == "repo/chart") | .version) ref $x | $x = "1.2.3"`,
},
{
name: "simple v3 path",
updater: YamlUpdater{
Path: "version",
},
value: "1.2.3",
expectedExpression: `(.version) ref $x | $x = "1.2.3"`,
},
{
name: "v3 path with custom style",
updater: YamlUpdater{
Path: "path.to.version",
Style: "double",
},
value: "1.2.3",
expectedExpression: `(.path.to.version) ref $x | $x = "1.2.3" | $x style="double"`,
},
{
name: "complex v3 path",
updater: YamlUpdater{
Path: `releases.(chart==repo/chart).version`,
},
value: "1.2.3",
expectedExpression: `(.releases[] | select(.chart == "repo/chart") | .version) ref $x | $x = "1.2.3"`,
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
expression, expressionNode, err := test.updater.yqExpression(test.value)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
} else {
require.NoError(t, err)
assert.Equal(t, test.expectedExpression, expression)
assert.NotNil(t, expressionNode)
}
})
}
}
================================================
FILE: update/yq/testdata/.gitignore
================================================
*
!.gitignore
================================================
FILE: update/yq/yq.go
================================================
// Package yq provides an updater that uses the yq lib to manipulate YAML (or JSON) files.
package yq
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"reflect"
"strconv"
"github.com/dailymotion-oss/octopilot/internal/glob"
"github.com/dailymotion-oss/octopilot/internal/yaml"
"github.com/mikefarah/yq/v4/pkg/yqlib"
gologging "gopkg.in/op/go-logging.v1"
)
func init() {
gologging.SetLevel(gologging.CRITICAL, "yq-lib")
yqlib.InitExpressionParser()
}
// YQUpdater is an updater that uses the yq lib to manipulate YAML (or JSON) files.
type YQUpdater struct {
FilePath string
Expression string
Output string
OutputFormat yqlib.PrinterOutputFormat
Indent int
Trim bool
UnwrapScalar bool
}
// NewUpdater builds a new YQ updater from the given parameters
func NewUpdater(params map[string]string) (*YQUpdater, error) {
updater := &YQUpdater{}
updater.FilePath = params["file"]
if len(updater.FilePath) == 0 {
return nil, errors.New("missing file parameter")
}
updater.Expression = params["expression"]
if len(updater.Expression) == 0 {
return nil, errors.New("missing expression parameter")
}
updater.Indent, _ = strconv.Atoi(params["indent"])
if updater.Indent <= 0 {
updater.Indent = 2
}
var err error
if updater.UnwrapScalar, err = strconv.ParseBool(params["unwrapscalar"]); err != nil {
// let's unwrap scalar by default, same as yq
updater.UnwrapScalar = true
}
updater.OutputFormat = yqlib.YamlOutputFormat
if outputToJSON, _ := strconv.ParseBool(params["json"]); outputToJSON {
updater.OutputFormat = yqlib.JSONOutputFormat
}
updater.Trim, _ = strconv.ParseBool(params["trim"])
updater.Output = params["output"]
return updater, nil
}
// Update updates the repository cloned at the given path, and returns true if changes have been made
func (u *YQUpdater) Update(_ context.Context, repoPath string) (bool, error) {
expressionNode, err := yqlib.ExpressionParser.ParseExpression(u.Expression)
if err != nil {
return false, fmt.Errorf("failed to parse yq expression %s: %w", u.Expression, err)
}
var output io.Writer
switch u.Output {
case "stdout":
output = os.Stdout
case "stderr":
output = os.Stderr
case "":
// will be handled later, because we'll be writing in-place to the source file
default:
outputFilePath := u.Output
if !filepath.IsAbs(outputFilePath) {
outputFilePath = filepath.Join(repoPath, outputFilePath)
}
f, err := os.Create(outputFilePath)
if err != nil {
return false, fmt.Errorf("failed to create output file %s: %w", outputFilePath, err)
}
defer f.Close()
output = f
}
filePaths, err := glob.ExpandGlobPattern(repoPath, u.FilePath)
if err != nil {
return false, fmt.Errorf("failed to expand glob pattern %s: %w", u.FilePath, err)
}
var encoder yqlib.Encoder
switch u.OutputFormat {
case yqlib.YamlOutputFormat:
const (
yamlColorise = false
yamlPrintDocSeparators = true
)
encoder = yqlib.NewYamlEncoder(u.Indent, yamlColorise, yamlPrintDocSeparators, u.UnwrapScalar)
case yqlib.JSONOutputFormat:
const (
jsonColorise = false
)
encoder = yqlib.NewJSONEncoder(u.Indent, jsonColorise)
default:
return false, fmt.Errorf("unknown output format %v", u.OutputFormat)
}
var (
streamEvaluator = yqlib.NewStreamEvaluator()
updated = false
)
for _, filePath := range filePaths {
relFilePath, err := filepath.Rel(repoPath, filePath)
if err != nil {
relFilePath = filePath
}
fileInfo, err := os.Stat(filePath)
if err != nil {
return false, fmt.Errorf("failed to access file %s: %w", relFilePath, err)
}
fileData, err := os.ReadFile(filePath)
if err != nil {
return false, fmt.Errorf("failed to read file %s: %w", relFilePath, err)
}
reader, leadingContent, err := yaml.ExtractLeadingContentForYQ(bytes.NewReader(fileData))
if err != nil {
return false, fmt.Errorf("failed to extract leading content from file %s: %w", relFilePath, err)
}
buffer := new(bytes.Buffer)
printer := yqlib.NewPrinter(encoder, yqlib.NewSinglePrinterWriter(buffer))
_, err = streamEvaluator.Evaluate(relFilePath, reader, expressionNode, printer, leadingContent, yqlib.NewYamlDecoder())
if err != nil {
return false, fmt.Errorf("failed to evaluate expression `%s` for file %s: %w", u.Expression, filePath, err)
}
if u.Trim {
buffer = bytes.NewBuffer(bytes.TrimSpace(buffer.Bytes()))
}
if reflect.DeepEqual(fileData, buffer.Bytes()) {
continue
}
if output != nil {
_, err = buffer.WriteTo(output)
} else {
// we need to write in-place in the same (source) file
err = os.WriteFile(filePath, buffer.Bytes(), fileInfo.Mode())
}
if err != nil {
return false, fmt.Errorf("failed to write yq result to the output: %w", err)
}
updated = true
}
return updated, nil
}
// Message returns the default title and body that should be used in the commits / pull requests
func (u *YQUpdater) Message() (title, body string) {
title = fmt.Sprintf("Update %s", u.FilePath)
body = fmt.Sprintf("Updating file(s) `%s` using yq expression `%s`", u.FilePath, u.Expression)
return title, body
}
// String returns a string representation of the updater
func (u *YQUpdater) String() string {
return fmt.Sprintf("YQ[file=%s,expression=%s,output=%s,indent=%v]", u.FilePath, u.Expression, u.Output, u.Indent)
}
================================================
FILE: update/yq/yq_test.go
================================================
package yq
import (
"context"
"os"
"path/filepath"
"testing"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestNewUpdater(t *testing.T) {
t.Parallel()
tests := []struct {
name string
params map[string]string
expected *YQUpdater
expectedErrorMsg string
}{
{
name: "valid params with single file",
params: map[string]string{
"file": "values.yaml",
"expression": ".version = 1.2.3",
"output": "/tmp/output.yaml",
"indent": "4",
"trim": "true",
"unwrapscalar": "false",
"json": "true",
},
expected: &YQUpdater{
FilePath: "values.yaml",
Expression: ".version = 1.2.3",
Output: "/tmp/output.yaml",
Indent: 4,
Trim: true,
UnwrapScalar: false,
OutputFormat: yqlib.JSONOutputFormat,
},
},
{
name: "valid params with multiple files using a glob pattern",
params: map[string]string{
"file": "**/values.yaml",
"expression": "something",
},
expected: &YQUpdater{
FilePath: "**/values.yaml",
Expression: "something",
Indent: 2,
Trim: false,
UnwrapScalar: true,
OutputFormat: yqlib.YamlOutputFormat,
},
},
{
name: "nil params",
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory file param",
params: map[string]string{
"expression": "something",
},
expectedErrorMsg: "missing file parameter",
},
{
name: "missing mandatory expression param",
params: map[string]string{
"file": "values.yaml",
},
expectedErrorMsg: "missing expression parameter",
},
{
name: "invalid trim boolean value",
params: map[string]string{
"file": "values.yaml",
"expression": "something",
"trim": "maybe",
},
expected: &YQUpdater{
FilePath: "values.yaml",
Expression: "something",
Trim: false,
UnwrapScalar: true,
OutputFormat: yqlib.YamlOutputFormat,
Indent: 2,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
actual, err := NewUpdater(test.params)
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.Nil(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
}
})
}
}
func TestUpdate(t *testing.T) {
t.Parallel()
tests := []struct {
name string
files map[string]string
updater *YQUpdater
expected bool
expectedErrorMsg string
expectedFiles map[string]string
}{
{
name: "update simple value in a single file",
files: map[string]string{
"basic-values.yaml": `# top level comment
# a simple key
key: value
# an object
object:
# with a key we want to update
mykey: some-value
# and another one we don't care about
anotherkey: another-value
`,
},
updater: &YQUpdater{
FilePath: "basic-values.yaml",
Expression: `.object.mykey = "updated-value"`,
OutputFormat: yqlib.YamlOutputFormat,
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"basic-values.yaml": `# top level comment
# a simple key
key: value
# an object
object:
# with a key we want to update
mykey: updated-value
# and another one we don't care about
anotherkey: another-value
`,
},
},
{
name: "extract a sub object from a single file to a new file",
files: map[string]string{
"extract-source.yaml": `# a simple key
key: value
# an object
object:
# with a key
mykey: some-value
# and another one
anotherkey: another-value
`,
},
updater: &YQUpdater{
FilePath: "extract-source.yaml",
Expression: `.object`,
Output: "extract-output.yaml",
OutputFormat: yqlib.YamlOutputFormat,
},
expected: true,
expectedFiles: map[string]string{
"extract-output.yaml": `# with a key
mykey: some-value
# and another one
anotherkey: another-value
`,
},
},
{
name: "update complex value in a single file",
files: map[string]string{
"complex-values.yaml": `
array:
- name: first entry
key: first value
- name: my entry
key: old value
- name: third entry
key: third value
`,
},
updater: &YQUpdater{
FilePath: "complex-values.yaml",
Expression: `(.array[] | select(.name == "my entry") | .key) = "new value"`,
OutputFormat: yqlib.YamlOutputFormat,
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"complex-values.yaml": `array:
- name: first entry
key: first value
- name: my entry
key: new value
- name: third entry
key: third value
`,
},
},
{
name: "update multiple values in a single file",
files: map[string]string{
"multiple-values.yaml": `
array:
- name: first entry
ref: abc123
key: first value
- name: second entry
ref: xyz789
key: second value
- name: third entry
ref: abc456
key: third value
`,
},
updater: &YQUpdater{
FilePath: "multiple-values.yaml",
Expression: `(.array[] | select(.ref == "abc*") | .key) = "updated value"`,
OutputFormat: yqlib.YamlOutputFormat,
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"multiple-values.yaml": `array:
- name: first entry
ref: abc123
key: updated value
- name: second entry
ref: xyz789
key: second value
- name: third entry
ref: abc456
key: updated value
`,
},
},
{
name: "update with folded style",
files: map[string]string{
"folded-style.yaml": `# a simple key
key: value
anotherkey: another-value
`,
},
updater: &YQUpdater{
FilePath: "folded-style.yaml",
Expression: `.key = "updated-value" | .key style="folded"`,
OutputFormat: yqlib.YamlOutputFormat,
},
expected: true,
expectedFiles: map[string]string{
"folded-style.yaml": `# a simple key
key: >-
updated-value
anotherkey: another-value
`,
},
},
{
name: "trim file",
files: map[string]string{
"trim.yaml": `
# a simple key
key: value
`,
},
updater: &YQUpdater{
FilePath: "trim.yaml",
Expression: `.key = "updated-value"`,
OutputFormat: yqlib.YamlOutputFormat,
Trim: true,
},
expected: true,
expectedFiles: map[string]string{
"trim.yaml": `# a simple key
key: updated-value`,
},
},
{
name: "create missing key/value in a single file",
files: map[string]string{
"missing-key-values.yaml": `
# a simple key
key: value
`,
},
updater: &YQUpdater{
FilePath: "missing-key-values.yaml",
Expression: `.object.mykey = "new-value"`,
OutputFormat: yqlib.YamlOutputFormat,
},
expected: true,
expectedFiles: map[string]string{
"missing-key-values.yaml": `
# a simple key
key: value
object:
mykey: new-value
`,
},
},
{
name: "unwrap scalar",
files: map[string]string{
"unwrap-scalar.yaml": `
object:
key: value # comment
`,
},
updater: &YQUpdater{
FilePath: "unwrap-scalar.yaml",
Expression: `.object.key`,
OutputFormat: yqlib.YamlOutputFormat,
UnwrapScalar: true,
},
expected: true,
expectedFiles: map[string]string{
"unwrap-scalar.yaml": `value
`,
},
},
{
name: "do not unwrap scalar",
files: map[string]string{
"no-unwrap-scalar.yaml": `
object:
key: value # comment
`,
},
updater: &YQUpdater{
FilePath: "no-unwrap-scalar.yaml",
Expression: `.object.key`,
OutputFormat: yqlib.YamlOutputFormat,
UnwrapScalar: false,
},
expected: true,
expectedFiles: map[string]string{
"no-unwrap-scalar.yaml": `value # comment
`,
},
},
{
name: "output to json",
files: map[string]string{
"output-to-json.yaml": `
object:
key: value # comment
`,
},
updater: &YQUpdater{
FilePath: "output-to-json.yaml",
Expression: `.`,
Output: "output-to-json.json",
OutputFormat: yqlib.JSONOutputFormat,
Indent: 2,
},
expected: true,
expectedFiles: map[string]string{
"output-to-json.json": `{
"object": {
"key": "value"
}
}
`,
},
},
{
name: "no changes",
files: map[string]string{
"no-changes.yaml": `# a simple key
key: value
`,
},
updater: &YQUpdater{
FilePath: "no-changes.yaml",
Expression: `.key = "value"`,
OutputFormat: yqlib.YamlOutputFormat,
},
expected: false,
expectedFiles: map[string]string{
"no-changes.yaml": `# a simple key
key: value
`,
},
},
}
for i := range tests {
test := tests[i]
t.Run(test.name, func(t *testing.T) {
t.Parallel()
{
for filename, content := range test.files {
err := os.MkdirAll(filepath.Dir(filepath.Join("testdata", filename)), 0755)
require.NoErrorf(t, err, "can't create testdata directories for %s", filename)
err = os.WriteFile(filepath.Join("testdata", filename), []byte(content), 0644)
require.NoErrorf(t, err, "can't write testdata file %s", filename)
}
}
actual, err := test.updater.Update(context.Background(), "testdata")
if len(test.expectedErrorMsg) > 0 {
require.EqualError(t, err, test.expectedErrorMsg)
assert.False(t, actual)
} else {
require.NoError(t, err)
assert.Equal(t, test.expected, actual)
actualFilePath := test.updater.Output
if actualFilePath == "" {
actualFilePath = test.updater.FilePath
}
actualFilePaths, err := filepath.Glob(filepath.Join("testdata", actualFilePath))
require.NoError(t, err, "can't expand glob pattern for actual testdata file")
for _, actualFilePath := range actualFilePaths {
actualRelFilePath, err := filepath.Rel("testdata", actualFilePath)
require.NoErrorf(t, err, "can't get relative path for actual testdata file %s", actualFilePath)
actualFileContent, err := os.ReadFile(actualFilePath)
require.NoErrorf(t, err, "can't read actual testdata file %s", actualFilePath)
expectedFileContent := test.expectedFiles[actualRelFilePath]
assert.Equalf(t, expectedFileContent, string(actualFileContent), "testdata file %s doesn't match", actualFilePath)
}
}
})
}
}
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/CHANGES.md
================================================
# Changes
## [0.3.0](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.2.3...compute/metadata/v0.3.0) (2024-04-15)
### Features
* **compute/metadata:** Add context aware functions ([#9733](https://github.com/googleapis/google-cloud-go/issues/9733)) ([e4eb5b4](https://github.com/googleapis/google-cloud-go/commit/e4eb5b46ee2aec9d2fc18300bfd66015e25a0510))
## [0.2.3](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.2.2...compute/metadata/v0.2.3) (2022-12-15)
### Bug Fixes
* **compute/metadata:** Switch DNS lookup to an absolute lookup ([119b410](https://github.com/googleapis/google-cloud-go/commit/119b41060c7895e45e48aee5621ad35607c4d021)), refs [#7165](https://github.com/googleapis/google-cloud-go/issues/7165)
## [0.2.2](https://github.com/googleapis/google-cloud-go/compare/compute/metadata/v0.2.1...compute/metadata/v0.2.2) (2022-12-01)
### Bug Fixes
* **compute/metadata:** Set IdleConnTimeout for http.Client ([#7084](https://github.com/googleapis/google-cloud-go/issues/7084)) ([766516a](https://github.com/googleapis/google-cloud-go/commit/766516aaf3816bfb3159efeea65aa3d1d205a3e2)), refs [#5430](https://github.com/googleapis/google-cloud-go/issues/5430)
## [0.1.0] (2022-10-26)
Initial release of metadata being it's own module.
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/README.md
================================================
# Compute API
[](https://pkg.go.dev/cloud.google.com/go/compute/metadata)
This is a utility library for communicating with Google Cloud metadata service
on Google Cloud.
## Install
```bash
go get cloud.google.com/go/compute/metadata
```
## Go Version Support
See the [Go Versions Supported](https://github.com/googleapis/google-cloud-go#go-versions-supported)
section in the root directory's README.
## Contributing
Contributions are welcome. Please, see the [CONTRIBUTING](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/main/CONTRIBUTING.md)
document for details.
Please note that this project is released with a Contributor Code of Conduct.
By participating in this project you agree to abide by its terms. See
[Contributor Code of Conduct](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/main/CONTRIBUTING.md#contributor-code-of-conduct)
for more information.
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/metadata.go
================================================
// Copyright 2014 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package metadata provides access to Google Compute Engine (GCE)
// metadata and API service accounts.
//
// This package is a wrapper around the GCE metadata service,
// as documented at https://cloud.google.com/compute/docs/metadata/overview.
package metadata // import "cloud.google.com/go/compute/metadata"
import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strings"
"sync"
"time"
)
const (
// metadataIP is the documented metadata server IP address.
metadataIP = "169.254.169.254"
// metadataHostEnv is the environment variable specifying the
// GCE metadata hostname. If empty, the default value of
// metadataIP ("169.254.169.254") is used instead.
// This is variable name is not defined by any spec, as far as
// I know; it was made up for the Go package.
metadataHostEnv = "GCE_METADATA_HOST"
userAgent = "gcloud-golang/0.1"
)
type cachedValue struct {
k string
trim bool
mu sync.Mutex
v string
}
var (
projID = &cachedValue{k: "project/project-id", trim: true}
projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
instID = &cachedValue{k: "instance/id", trim: true}
)
var defaultClient = &Client{hc: newDefaultHTTPClient()}
func newDefaultHTTPClient() *http.Client {
return &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
IdleConnTimeout: 60 * time.Second,
},
Timeout: 5 * time.Second,
}
}
// NotDefinedError is returned when requested metadata is not defined.
//
// The underlying string is the suffix after "/computeMetadata/v1/".
//
// This error is not returned if the value is defined to be the empty
// string.
type NotDefinedError string
func (suffix NotDefinedError) Error() string {
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
}
func (c *cachedValue) get(cl *Client) (v string, err error) {
defer c.mu.Unlock()
c.mu.Lock()
if c.v != "" {
return c.v, nil
}
if c.trim {
v, err = cl.getTrimmed(context.Background(), c.k)
} else {
v, err = cl.GetWithContext(context.Background(), c.k)
}
if err == nil {
c.v = v
}
return
}
var (
onGCEOnce sync.Once
onGCE bool
)
// OnGCE reports whether this process is running on Google Compute Engine.
func OnGCE() bool {
onGCEOnce.Do(initOnGCE)
return onGCE
}
func initOnGCE() {
onGCE = testOnGCE()
}
func testOnGCE() bool {
// The user explicitly said they're on GCE, so trust them.
if os.Getenv(metadataHostEnv) != "" {
return true
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
resc := make(chan bool, 2)
// Try two strategies in parallel.
// See https://github.com/googleapis/google-cloud-go/issues/194
go func() {
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
req.Header.Set("User-Agent", userAgent)
res, err := newDefaultHTTPClient().Do(req.WithContext(ctx))
if err != nil {
resc <- false
return
}
defer res.Body.Close()
resc <- res.Header.Get("Metadata-Flavor") == "Google"
}()
go func() {
resolver := &net.Resolver{}
addrs, err := resolver.LookupHost(ctx, "metadata.google.internal.")
if err != nil || len(addrs) == 0 {
resc <- false
return
}
resc <- strsContains(addrs, metadataIP)
}()
tryHarder := systemInfoSuggestsGCE()
if tryHarder {
res := <-resc
if res {
// The first strategy succeeded, so let's use it.
return true
}
// Wait for either the DNS or metadata server probe to
// contradict the other one and say we are running on
// GCE. Give it a lot of time to do so, since the system
// info already suggests we're running on a GCE BIOS.
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case res = <-resc:
return res
case <-timer.C:
// Too slow. Who knows what this system is.
return false
}
}
// There's no hint from the system info that we're running on
// GCE, so use the first probe's result as truth, whether it's
// true or false. The goal here is to optimize for speed for
// users who are NOT running on GCE. We can't assume that
// either a DNS lookup or an HTTP request to a blackholed IP
// address is fast. Worst case this should return when the
// metaClient's Transport.ResponseHeaderTimeout or
// Transport.Dial.Timeout fires (in two seconds).
return <-resc
}
// systemInfoSuggestsGCE reports whether the local system (without
// doing network requests) suggests that we're running on GCE. If this
// returns true, testOnGCE tries a bit harder to reach its metadata
// server.
func systemInfoSuggestsGCE() bool {
if runtime.GOOS != "linux" {
// We don't have any non-Linux clues available, at least yet.
return false
}
slurp, _ := os.ReadFile("/sys/class/dmi/id/product_name")
name := strings.TrimSpace(string(slurp))
return name == "Google" || name == "Google Compute Engine"
}
// Subscribe calls Client.SubscribeWithContext on the default client.
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
return defaultClient.SubscribeWithContext(context.Background(), suffix, func(ctx context.Context, v string, ok bool) error { return fn(v, ok) })
}
// SubscribeWithContext calls Client.SubscribeWithContext on the default client.
func SubscribeWithContext(ctx context.Context, suffix string, fn func(ctx context.Context, v string, ok bool) error) error {
return defaultClient.SubscribeWithContext(ctx, suffix, fn)
}
// Get calls Client.GetWithContext on the default client.
//
// Deprecated: Please use the context aware variant [GetWithContext].
func Get(suffix string) (string, error) {
return defaultClient.GetWithContext(context.Background(), suffix)
}
// GetWithContext calls Client.GetWithContext on the default client.
func GetWithContext(ctx context.Context, suffix string) (string, error) {
return defaultClient.GetWithContext(ctx, suffix)
}
// ProjectID returns the current instance's project ID string.
func ProjectID() (string, error) { return defaultClient.ProjectID() }
// NumericProjectID returns the current instance's numeric project ID.
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
// InternalIP returns the instance's primary internal IP address.
func InternalIP() (string, error) { return defaultClient.InternalIP() }
// ExternalIP returns the instance's primary external (public) IP address.
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
// Email calls Client.Email on the default client.
func Email(serviceAccount string) (string, error) { return defaultClient.Email(serviceAccount) }
// Hostname returns the instance's hostname. This will be of the form
// ".c..internal".
func Hostname() (string, error) { return defaultClient.Hostname() }
// InstanceTags returns the list of user-defined instance tags,
// assigned when initially creating a GCE instance.
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
// InstanceID returns the current VM's numeric instance ID.
func InstanceID() (string, error) { return defaultClient.InstanceID() }
// InstanceName returns the current VM's instance ID string.
func InstanceName() (string, error) { return defaultClient.InstanceName() }
// Zone returns the current VM's zone, such as "us-central1-b".
func Zone() (string, error) { return defaultClient.Zone() }
// InstanceAttributes calls Client.InstanceAttributes on the default client.
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
// ProjectAttributes calls Client.ProjectAttributes on the default client.
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
func InstanceAttributeValue(attr string) (string, error) {
return defaultClient.InstanceAttributeValue(attr)
}
// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
func ProjectAttributeValue(attr string) (string, error) {
return defaultClient.ProjectAttributeValue(attr)
}
// Scopes calls Client.Scopes on the default client.
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
func strsContains(ss []string, s string) bool {
for _, v := range ss {
if v == s {
return true
}
}
return false
}
// A Client provides metadata.
type Client struct {
hc *http.Client
}
// NewClient returns a Client that can be used to fetch metadata.
// Returns the client that uses the specified http.Client for HTTP requests.
// If nil is specified, returns the default client.
func NewClient(c *http.Client) *Client {
if c == nil {
return defaultClient
}
return &Client{hc: c}
}
// getETag returns a value from the metadata service as well as the associated ETag.
// This func is otherwise equivalent to Get.
func (c *Client) getETag(ctx context.Context, suffix string) (value, etag string, err error) {
// Using a fixed IP makes it very difficult to spoof the metadata service in
// a container, which is an important use-case for local testing of cloud
// deployments. To enable spoofing of the metadata service, the environment
// variable GCE_METADATA_HOST is first inspected to decide where metadata
// requests shall go.
host := os.Getenv(metadataHostEnv)
if host == "" {
// Using 169.254.169.254 instead of "metadata" here because Go
// binaries built with the "netgo" tag and without cgo won't
// know the search suffix for "metadata" is
// ".google.internal", and this IP address is documented as
// being stable anyway.
host = metadataIP
}
suffix = strings.TrimLeft(suffix, "/")
u := "http://" + host + "/computeMetadata/v1/" + suffix
req, err := http.NewRequestWithContext(ctx, "GET", u, nil)
if err != nil {
return "", "", err
}
req.Header.Set("Metadata-Flavor", "Google")
req.Header.Set("User-Agent", userAgent)
var res *http.Response
var reqErr error
retryer := newRetryer()
for {
res, reqErr = c.hc.Do(req)
var code int
if res != nil {
code = res.StatusCode
}
if delay, shouldRetry := retryer.Retry(code, reqErr); shouldRetry {
if err := sleep(ctx, delay); err != nil {
return "", "", err
}
continue
}
break
}
if reqErr != nil {
return "", "", reqErr
}
defer res.Body.Close()
if res.StatusCode == http.StatusNotFound {
return "", "", NotDefinedError(suffix)
}
all, err := io.ReadAll(res.Body)
if err != nil {
return "", "", err
}
if res.StatusCode != 200 {
return "", "", &Error{Code: res.StatusCode, Message: string(all)}
}
return string(all), res.Header.Get("Etag"), nil
}
// Get returns a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
//
// If the GCE_METADATA_HOST environment variable is not defined, a default of
// 169.254.169.254 will be used instead.
//
// If the requested metadata is not defined, the returned error will
// be of type NotDefinedError.
//
// Deprecated: Please use the context aware variant [Client.GetWithContext].
func (c *Client) Get(suffix string) (string, error) {
return c.GetWithContext(context.Background(), suffix)
}
// GetWithContext returns a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
//
// If the GCE_METADATA_HOST environment variable is not defined, a default of
// 169.254.169.254 will be used instead.
//
// If the requested metadata is not defined, the returned error will
// be of type NotDefinedError.
func (c *Client) GetWithContext(ctx context.Context, suffix string) (string, error) {
val, _, err := c.getETag(ctx, suffix)
return val, err
}
func (c *Client) getTrimmed(ctx context.Context, suffix string) (s string, err error) {
s, err = c.GetWithContext(ctx, suffix)
s = strings.TrimSpace(s)
return
}
func (c *Client) lines(suffix string) ([]string, error) {
j, err := c.GetWithContext(context.Background(), suffix)
if err != nil {
return nil, err
}
s := strings.Split(strings.TrimSpace(j), "\n")
for i := range s {
s[i] = strings.TrimSpace(s[i])
}
return s, nil
}
// ProjectID returns the current instance's project ID string.
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
// NumericProjectID returns the current instance's numeric project ID.
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
// InstanceID returns the current VM's numeric instance ID.
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
// InternalIP returns the instance's primary internal IP address.
func (c *Client) InternalIP() (string, error) {
return c.getTrimmed(context.Background(), "instance/network-interfaces/0/ip")
}
// Email returns the email address associated with the service account.
// The account may be empty or the string "default" to use the instance's
// main account.
func (c *Client) Email(serviceAccount string) (string, error) {
if serviceAccount == "" {
serviceAccount = "default"
}
return c.getTrimmed(context.Background(), "instance/service-accounts/"+serviceAccount+"/email")
}
// ExternalIP returns the instance's primary external (public) IP address.
func (c *Client) ExternalIP() (string, error) {
return c.getTrimmed(context.Background(), "instance/network-interfaces/0/access-configs/0/external-ip")
}
// Hostname returns the instance's hostname. This will be of the form
// ".c..internal".
func (c *Client) Hostname() (string, error) {
return c.getTrimmed(context.Background(), "instance/hostname")
}
// InstanceTags returns the list of user-defined instance tags,
// assigned when initially creating a GCE instance.
func (c *Client) InstanceTags() ([]string, error) {
var s []string
j, err := c.GetWithContext(context.Background(), "instance/tags")
if err != nil {
return nil, err
}
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
return nil, err
}
return s, nil
}
// InstanceName returns the current VM's instance ID string.
func (c *Client) InstanceName() (string, error) {
return c.getTrimmed(context.Background(), "instance/name")
}
// Zone returns the current VM's zone, such as "us-central1-b".
func (c *Client) Zone() (string, error) {
zone, err := c.getTrimmed(context.Background(), "instance/zone")
// zone is of the form "projects//zones/".
if err != nil {
return "", err
}
return zone[strings.LastIndex(zone, "/")+1:], nil
}
// InstanceAttributes returns the list of user-defined attributes,
// assigned when initially creating a GCE VM instance. The value of an
// attribute can be obtained with InstanceAttributeValue.
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
// ProjectAttributes returns the list of user-defined attributes
// applying to the project as a whole, not just this VM. The value of
// an attribute can be obtained with ProjectAttributeValue.
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
// InstanceAttributeValue returns the value of the provided VM
// instance attribute.
//
// If the requested attribute is not defined, the returned error will
// be of type NotDefinedError.
//
// InstanceAttributeValue may return ("", nil) if the attribute was
// defined to be the empty string.
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
return c.GetWithContext(context.Background(), "instance/attributes/"+attr)
}
// ProjectAttributeValue returns the value of the provided
// project attribute.
//
// If the requested attribute is not defined, the returned error will
// be of type NotDefinedError.
//
// ProjectAttributeValue may return ("", nil) if the attribute was
// defined to be the empty string.
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
return c.GetWithContext(context.Background(), "project/attributes/"+attr)
}
// Scopes returns the service account scopes for the given account.
// The account may be empty or the string "default" to use the instance's
// main account.
func (c *Client) Scopes(serviceAccount string) ([]string, error) {
if serviceAccount == "" {
serviceAccount = "default"
}
return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
}
// Subscribe subscribes to a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
// The suffix may contain query parameters.
//
// Deprecated: Please use the context aware variant [Client.SubscribeWithContext].
func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
return c.SubscribeWithContext(context.Background(), suffix, func(ctx context.Context, v string, ok bool) error { return fn(v, ok) })
}
// SubscribeWithContext subscribes to a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
// The suffix may contain query parameters.
//
// SubscribeWithContext calls fn with the latest metadata value indicated by the
// provided suffix. If the metadata value is deleted, fn is called with the
// empty string and ok false. Subscribe blocks until fn returns a non-nil error
// or the value is deleted. Subscribe returns the error value returned from the
// last call to fn, which may be nil when ok == false.
func (c *Client) SubscribeWithContext(ctx context.Context, suffix string, fn func(ctx context.Context, v string, ok bool) error) error {
const failedSubscribeSleep = time.Second * 5
// First check to see if the metadata value exists at all.
val, lastETag, err := c.getETag(ctx, suffix)
if err != nil {
return err
}
if err := fn(ctx, val, true); err != nil {
return err
}
ok := true
if strings.ContainsRune(suffix, '?') {
suffix += "&wait_for_change=true&last_etag="
} else {
suffix += "?wait_for_change=true&last_etag="
}
for {
val, etag, err := c.getETag(ctx, suffix+url.QueryEscape(lastETag))
if err != nil {
if _, deleted := err.(NotDefinedError); !deleted {
time.Sleep(failedSubscribeSleep)
continue // Retry on other errors.
}
ok = false
}
lastETag = etag
if err := fn(ctx, val, ok); err != nil || !ok {
return err
}
}
}
// Error contains an error response from the server.
type Error struct {
// Code is the HTTP response status code.
Code int
// Message is the server response message.
Message string
}
func (e *Error) Error() string {
return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
}
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/retry.go
================================================
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package metadata
import (
"context"
"io"
"math/rand"
"net/http"
"time"
)
const (
maxRetryAttempts = 5
)
var (
syscallRetryable = func(error) bool { return false }
)
// defaultBackoff is basically equivalent to gax.Backoff without the need for
// the dependency.
type defaultBackoff struct {
max time.Duration
mul float64
cur time.Duration
}
func (b *defaultBackoff) Pause() time.Duration {
d := time.Duration(1 + rand.Int63n(int64(b.cur)))
b.cur = time.Duration(float64(b.cur) * b.mul)
if b.cur > b.max {
b.cur = b.max
}
return d
}
// sleep is the equivalent of gax.Sleep without the need for the dependency.
func sleep(ctx context.Context, d time.Duration) error {
t := time.NewTimer(d)
select {
case <-ctx.Done():
t.Stop()
return ctx.Err()
case <-t.C:
return nil
}
}
func newRetryer() *metadataRetryer {
return &metadataRetryer{bo: &defaultBackoff{
cur: 100 * time.Millisecond,
max: 30 * time.Second,
mul: 2,
}}
}
type backoff interface {
Pause() time.Duration
}
type metadataRetryer struct {
bo backoff
attempts int
}
func (r *metadataRetryer) Retry(status int, err error) (time.Duration, bool) {
if status == http.StatusOK {
return 0, false
}
retryOk := shouldRetry(status, err)
if !retryOk {
return 0, false
}
if r.attempts == maxRetryAttempts {
return 0, false
}
r.attempts++
return r.bo.Pause(), true
}
func shouldRetry(status int, err error) bool {
if 500 <= status && status <= 599 {
return true
}
if err == io.ErrUnexpectedEOF {
return true
}
// Transient network errors should be retried.
if syscallRetryable(err) {
return true
}
if err, ok := err.(interface{ Temporary() bool }); ok {
if err.Temporary() {
return true
}
}
if err, ok := err.(interface{ Unwrap() error }); ok {
return shouldRetry(status, err.Unwrap())
}
return false
}
================================================
FILE: vendor/cloud.google.com/go/compute/metadata/retry_linux.go
================================================
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build linux
// +build linux
package metadata
import "syscall"
func init() {
// Initialize syscallRetryable to return true on transient socket-level
// errors. These errors are specific to Linux.
syscallRetryable = func(err error) bool { return err == syscall.ECONNRESET || err == syscall.ECONNREFUSED }
}
================================================
FILE: vendor/dario.cat/mergo/.deepsource.toml
================================================
version = 1
test_patterns = [
"*_test.go"
]
[[analyzers]]
name = "go"
enabled = true
[analyzers.meta]
import_path = "dario.cat/mergo"
================================================
FILE: vendor/dario.cat/mergo/.gitignore
================================================
#### joe made this: http://goel.io/joe
#### go ####
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Golang/Intellij
.idea
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
#### vim ####
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# Session
Session.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
================================================
FILE: vendor/dario.cat/mergo/.travis.yml
================================================
language: go
arch:
- amd64
- ppc64le
install:
- go get -t
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
script:
- go test -race -v ./...
after_script:
- $HOME/gopath/bin/goveralls -service=travis-ci -repotoken $COVERALLS_TOKEN
================================================
FILE: vendor/dario.cat/mergo/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at i@dario.im. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: vendor/dario.cat/mergo/CONTRIBUTING.md
================================================
# Contributing to mergo
First off, thanks for taking the time to contribute! ❤️
All types of contributions are encouraged and valued. See the [Table of Contents](#table-of-contents) for different ways to help and details about how this project handles them. Please make sure to read the relevant section before making your contribution. It will make it a lot easier for us maintainers and smooth out the experience for all involved. The community looks forward to your contributions. 🎉
> And if you like the project, but just don't have time to contribute, that's fine. There are other easy ways to support the project and show your appreciation, which we would also be very happy about:
> - Star the project
> - Tweet about it
> - Refer this project in your project's readme
> - Mention the project at local meetups and tell your friends/colleagues
## Table of Contents
- [Code of Conduct](#code-of-conduct)
- [I Have a Question](#i-have-a-question)
- [I Want To Contribute](#i-want-to-contribute)
- [Reporting Bugs](#reporting-bugs)
- [Suggesting Enhancements](#suggesting-enhancements)
## Code of Conduct
This project and everyone participating in it is governed by the
[mergo Code of Conduct](https://github.com/imdario/mergoblob/master/CODE_OF_CONDUCT.md).
By participating, you are expected to uphold this code. Please report unacceptable behavior
to <>.
## I Have a Question
> If you want to ask a question, we assume that you have read the available [Documentation](https://pkg.go.dev/github.com/imdario/mergo).
Before you ask a question, it is best to search for existing [Issues](https://github.com/imdario/mergo/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first.
If you then still feel the need to ask a question and need clarification, we recommend the following:
- Open an [Issue](https://github.com/imdario/mergo/issues/new).
- Provide as much context as you can about what you're running into.
- Provide project and platform versions (nodejs, npm, etc), depending on what seems relevant.
We will then take care of the issue as soon as possible.
## I Want To Contribute
> ### Legal Notice
> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license.
### Reporting Bugs
#### Before Submitting a Bug Report
A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible.
- Make sure that you are using the latest version.
- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](). If you are looking for support, you might want to check [this section](#i-have-a-question)).
- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/imdario/mergoissues?q=label%3Abug).
- Also make sure to search the internet (including Stack Overflow) to see if users outside of the GitHub community have discussed the issue.
- Collect information about the bug:
- Stack trace (Traceback)
- OS, Platform and Version (Windows, Linux, macOS, x86, ARM)
- Version of the interpreter, compiler, SDK, runtime environment, package manager, depending on what seems relevant.
- Possibly your input and the output
- Can you reliably reproduce the issue? And can you also reproduce it with older versions?
#### How Do I Submit a Good Bug Report?
> You must never report security related issues, vulnerabilities or bugs including sensitive information to the issue tracker, or elsewhere in public. Instead sensitive bugs must be sent by email to .
We use GitHub issues to track bugs and errors. If you run into an issue with the project:
- Open an [Issue](https://github.com/imdario/mergo/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.)
- Explain the behavior you would expect and the actual behavior.
- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case.
- Provide the information you collected in the previous section.
Once it's filed:
- The project team will label the issue accordingly.
- A team member will try to reproduce the issue with your provided steps. If there are no reproduction steps or no obvious way to reproduce the issue, the team will ask you for those steps and mark the issue as `needs-repro`. Bugs with the `needs-repro` tag will not be addressed until they are reproduced.
- If the team is able to reproduce the issue, it will be marked `needs-fix`, as well as possibly other tags (such as `critical`), and the issue will be left to be implemented by someone.
### Suggesting Enhancements
This section guides you through submitting an enhancement suggestion for mergo, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions.
#### Before Submitting an Enhancement
- Make sure that you are using the latest version.
- Read the [documentation]() carefully and find out if the functionality is already covered, maybe by an individual configuration.
- Perform a [search](https://github.com/imdario/mergo/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library.
#### How Do I Submit a Good Enhancement Suggestion?
Enhancement suggestions are tracked as [GitHub issues](https://github.com/imdario/mergo/issues).
- Use a **clear and descriptive title** for the issue to identify the suggestion.
- Provide a **step-by-step description of the suggested enhancement** in as many details as possible.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you.
- You may want to **include screenshots and animated GIFs** which help you demonstrate the steps or point out the part which the suggestion is related to. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
- **Explain why this enhancement would be useful** to most mergo users. You may also want to point out the other projects that solved it better and which could serve as inspiration.
## Attribution
This guide is based on the **contributing-gen**. [Make your own](https://github.com/bttger/contributing-gen)!
================================================
FILE: vendor/dario.cat/mergo/LICENSE
================================================
Copyright (c) 2013 Dario Castañé. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/dario.cat/mergo/README.md
================================================
# Mergo
[![GitHub release][5]][6]
[![GoCard][7]][8]
[![Test status][1]][2]
[![OpenSSF Scorecard][21]][22]
[![OpenSSF Best Practices][19]][20]
[![Coverage status][9]][10]
[![Sourcegraph][11]][12]
[![FOSSA status][13]][14]
[![GoDoc][3]][4]
[![Become my sponsor][15]][16]
[![Tidelift][17]][18]
[1]: https://github.com/imdario/mergo/workflows/tests/badge.svg?branch=master
[2]: https://github.com/imdario/mergo/actions/workflows/tests.yml
[3]: https://godoc.org/github.com/imdario/mergo?status.svg
[4]: https://godoc.org/github.com/imdario/mergo
[5]: https://img.shields.io/github/release/imdario/mergo.svg
[6]: https://github.com/imdario/mergo/releases
[7]: https://goreportcard.com/badge/imdario/mergo
[8]: https://goreportcard.com/report/github.com/imdario/mergo
[9]: https://coveralls.io/repos/github/imdario/mergo/badge.svg?branch=master
[10]: https://coveralls.io/github/imdario/mergo?branch=master
[11]: https://sourcegraph.com/github.com/imdario/mergo/-/badge.svg
[12]: https://sourcegraph.com/github.com/imdario/mergo?badge
[13]: https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield
[14]: https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield
[15]: https://img.shields.io/github/sponsors/imdario
[16]: https://github.com/sponsors/imdario
[17]: https://tidelift.com/badges/package/go/github.com%2Fimdario%2Fmergo
[18]: https://tidelift.com/subscription/pkg/go-github.com-imdario-mergo
[19]: https://bestpractices.coreinfrastructure.org/projects/7177/badge
[20]: https://bestpractices.coreinfrastructure.org/projects/7177
[21]: https://api.securityscorecards.dev/projects/github.com/imdario/mergo/badge
[22]: https://api.securityscorecards.dev/projects/github.com/imdario/mergo
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
Mergo merges same-type structs and maps by setting default values in zero-value fields. Mergo won't merge unexported (private) fields. It will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
Also a lovely [comune](http://en.wikipedia.org/wiki/Mergo) (municipality) in the Province of Ancona in the Italian region of Marche.
## Status
Mergo is stable and frozen, ready for production. Check a short list of the projects using at large scale it [here](https://github.com/imdario/mergo#mergo-in-the-wild).
No new features are accepted. They will be considered for a future v2 that improves the implementation and fixes bugs for corner cases.
### Important notes
#### 1.0.0
In [1.0.0](//github.com/imdario/mergo/releases/tag/1.0.0) Mergo moves to a vanity URL `dario.cat/mergo`. No more v1 versions will be released.
If the vanity URL is causing issues in your project due to a dependency pulling Mergo - it isn't a direct dependency in your project - it is recommended to use [replace](https://github.com/golang/go/wiki/Modules#when-should-i-use-the-replace-directive) to pin the version to the last one with the old import URL:
```
replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
```
#### 0.3.9
Please keep in mind that a problematic PR broke [0.3.9](//github.com/imdario/mergo/releases/tag/0.3.9). I reverted it in [0.3.10](//github.com/imdario/mergo/releases/tag/0.3.10), and I consider it stable but not bug-free. Also, this version adds support for go modules.
Keep in mind that in [0.3.2](//github.com/imdario/mergo/releases/tag/0.3.2), Mergo changed `Merge()`and `Map()` signatures to support [transformers](#transformers). I added an optional/variadic argument so that it won't break the existing code.
If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with ```go get -u dario.cat/mergo```. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
### Donations
If Mergo is useful to you, consider buying me a coffee, a beer, or making a monthly donation to allow me to keep building great free software. :heart_eyes:
### Mergo in the wild
Mergo is used by [thousands](https://deps.dev/go/dario.cat%2Fmergo/v1.0.0/dependents) [of](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.16/dependents) [projects](https://deps.dev/go/github.com%2Fimdario%2Fmergo/v0.3.12), including:
* [containerd/containerd](https://github.com/containerd/containerd)
* [datadog/datadog-agent](https://github.com/datadog/datadog-agent)
* [docker/cli/](https://github.com/docker/cli/)
* [goreleaser/goreleaser](https://github.com/goreleaser/goreleaser)
* [go-micro/go-micro](https://github.com/go-micro/go-micro)
* [grafana/loki](https://github.com/grafana/loki)
* [kubernetes/kubernetes](https://github.com/kubernetes/kubernetes)
* [masterminds/sprig](github.com/Masterminds/sprig)
* [moby/moby](https://github.com/moby/moby)
* [slackhq/nebula](https://github.com/slackhq/nebula)
* [volcano-sh/volcano](https://github.com/volcano-sh/volcano)
## Install
go get dario.cat/mergo
// use in your .go code
import (
"dario.cat/mergo"
)
## Usage
You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as [they are zero values](https://golang.org/ref/spec#The_zero_value) too. Also, maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
```go
if err := mergo.Merge(&dst, src); err != nil {
// ...
}
```
Also, you can merge overwriting values using the transformer `WithOverride`.
```go
if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
// ...
}
```
If you need to override pointers, so the source pointer's value is assigned to the destination's pointer, you must use `WithoutDereference`:
```go
package main
import (
"fmt"
"dario.cat/mergo"
)
type Foo struct {
A *string
B int64
}
func main() {
first := "first"
second := "second"
src := Foo{
A: &first,
B: 2,
}
dest := Foo{
A: &second,
B: 1,
}
mergo.Merge(&dest, src, mergo.WithOverride, mergo.WithoutDereference)
}
```
Additionally, you can map a `map[string]interface{}` to a struct (and otherwise, from struct to map), following the same restrictions as in `Merge()`. Keys are capitalized to find each corresponding exported field.
```go
if err := mergo.Map(&dst, srcMap); err != nil {
// ...
}
```
Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as `map[string]interface{}`. They will be just assigned as values.
Here is a nice example:
```go
package main
import (
"fmt"
"dario.cat/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
B: 2,
}
dest := Foo{
A: "two",
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}
```
Note: if test are failing due missing package, please execute:
go get gopkg.in/yaml.v3
### Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, `time.Time` is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero `time.Time`?
```go
package main
import (
"fmt"
"dario.cat/mergo"
"reflect"
"time"
)
type timeTransformer struct {
}
func (t timeTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ == reflect.TypeOf(time.Time{}) {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
isZero := dst.MethodByName("IsZero")
result := isZero.Call([]reflect.Value{})
if result[0].Bool() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
type Snapshot struct {
Time time.Time
// ...
}
func main() {
src := Snapshot{time.Now()}
dest := Snapshot{}
mergo.Merge(&dest, src, mergo.WithTransformers(timeTransformer{}))
fmt.Println(dest)
// Will print
// { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
}
```
## Contact me
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): [@im_dario](https://twitter.com/im_dario)
## About
Written by [Dario Castañé](http://dario.im).
## License
[BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE).
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large)
================================================
FILE: vendor/dario.cat/mergo/SECURITY.md
================================================
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 0.3.x | :white_check_mark: |
| < 0.3 | :x: |
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
================================================
FILE: vendor/dario.cat/mergo/doc.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
A helper to merge structs and maps in Golang. Useful for configuration default values, avoiding messy if-statements.
Mergo merges same-type structs and maps by setting default values in zero-value fields. Mergo won't merge unexported (private) fields. It will do recursively any exported one. It also won't merge structs inside maps (because they are not addressable using Go reflection).
# Status
It is ready for production use. It is used in several projects by Docker, Google, The Linux Foundation, VMWare, Shopify, etc.
# Important notes
1.0.0
In 1.0.0 Mergo moves to a vanity URL `dario.cat/mergo`.
0.3.9
Please keep in mind that a problematic PR broke 0.3.9. We reverted it in 0.3.10. We consider 0.3.10 as stable but not bug-free. . Also, this version adds suppot for go modules.
Keep in mind that in 0.3.2, Mergo changed Merge() and Map() signatures to support transformers. We added an optional/variadic argument so that it won't break the existing code.
If you were using Mergo before April 6th, 2015, please check your project works as intended after updating your local copy with go get -u dario.cat/mergo. I apologize for any issue caused by its previous behavior and any future bug that Mergo could cause in existing projects after the change (release 0.2.0).
# Install
Do your usual installation procedure:
go get dario.cat/mergo
// use in your .go code
import (
"dario.cat/mergo"
)
# Usage
You can only merge same-type structs with exported fields initialized as zero value of their type and same-types maps. Mergo won't merge unexported (private) fields but will do recursively any exported one. It won't merge empty structs value as they are zero values too. Also, maps will be merged recursively except for structs inside maps (because they are not addressable using Go reflection).
if err := mergo.Merge(&dst, src); err != nil {
// ...
}
Also, you can merge overwriting values using the transformer WithOverride.
if err := mergo.Merge(&dst, src, mergo.WithOverride); err != nil {
// ...
}
Additionally, you can map a map[string]interface{} to a struct (and otherwise, from struct to map), following the same restrictions as in Merge(). Keys are capitalized to find each corresponding exported field.
if err := mergo.Map(&dst, srcMap); err != nil {
// ...
}
Warning: if you map a struct to map, it won't do it recursively. Don't expect Mergo to map struct members of your struct as map[string]interface{}. They will be just assigned as values.
Here is a nice example:
package main
import (
"fmt"
"dario.cat/mergo"
)
type Foo struct {
A string
B int64
}
func main() {
src := Foo{
A: "one",
B: 2,
}
dest := Foo{
A: "two",
}
mergo.Merge(&dest, src)
fmt.Println(dest)
// Will print
// {two 2}
}
# Transformers
Transformers allow to merge specific types differently than in the default behavior. In other words, now you can customize how some types are merged. For example, time.Time is a struct; it doesn't have zero value but IsZero can return true because it has fields with zero value. How can we merge a non-zero time.Time?
package main
import (
"fmt"
"dario.cat/mergo"
"reflect"
"time"
)
type timeTransformer struct {
}
func (t timeTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error {
if typ == reflect.TypeOf(time.Time{}) {
return func(dst, src reflect.Value) error {
if dst.CanSet() {
isZero := dst.MethodByName("IsZero")
result := isZero.Call([]reflect.Value{})
if result[0].Bool() {
dst.Set(src)
}
}
return nil
}
}
return nil
}
type Snapshot struct {
Time time.Time
// ...
}
func main() {
src := Snapshot{time.Now()}
dest := Snapshot{}
mergo.Merge(&dest, src, mergo.WithTransformers(timeTransformer{}))
fmt.Println(dest)
// Will print
// { 2018-01-12 01:15:00 +0000 UTC m=+0.000000001 }
}
# Contact me
If I can help you, you have an idea or you are using Mergo in your projects, don't hesitate to drop me a line (or a pull request): https://twitter.com/im_dario
# About
Written by Dario Castañé: https://da.rio.hn
# License
BSD 3-Clause license, as Go language.
*/
package mergo
================================================
FILE: vendor/dario.cat/mergo/map.go
================================================
// Copyright 2014 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"fmt"
"reflect"
"unicode"
"unicode/utf8"
)
func changeInitialCase(s string, mapper func(rune) rune) string {
if s == "" {
return s
}
r, n := utf8.DecodeRuneInString(s)
return string(mapper(r)) + s[n:]
}
func isExported(field reflect.StructField) bool {
r, _ := utf8.DecodeRuneInString(field.Name)
return r >= 'A' && r <= 'Z'
}
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
overwrite := config.Overwrite
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
seen := visited[h]
typ := dst.Type()
for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ {
return nil
}
}
// Remember, remember...
visited[h] = &visit{typ, seen, addr}
}
zeroValue := reflect.Value{}
switch dst.Kind() {
case reflect.Map:
dstMap := dst.Interface().(map[string]interface{})
for i, n := 0, src.NumField(); i < n; i++ {
srcType := src.Type()
field := srcType.Field(i)
if !isExported(field) {
continue
}
fieldName := field.Name
fieldName = changeInitialCase(fieldName, unicode.ToLower)
if _, ok := dstMap[fieldName]; !ok || (!isEmptyValue(reflect.ValueOf(src.Field(i).Interface()), !config.ShouldNotDereference) && overwrite) || config.overwriteWithEmptyValue {
dstMap[fieldName] = src.Field(i).Interface()
}
}
case reflect.Ptr:
if dst.IsNil() {
v := reflect.New(dst.Type().Elem())
dst.Set(v)
}
dst = dst.Elem()
fallthrough
case reflect.Struct:
srcMap := src.Interface().(map[string]interface{})
for key := range srcMap {
config.overwriteWithEmptyValue = true
srcValue := srcMap[key]
fieldName := changeInitialCase(key, unicode.ToUpper)
dstElement := dst.FieldByName(fieldName)
if dstElement == zeroValue {
// We discard it because the field doesn't exist.
continue
}
srcElement := reflect.ValueOf(srcValue)
dstKind := dstElement.Kind()
srcKind := srcElement.Kind()
if srcKind == reflect.Ptr && dstKind != reflect.Ptr {
srcElement = srcElement.Elem()
srcKind = reflect.TypeOf(srcElement.Interface()).Kind()
} else if dstKind == reflect.Ptr {
// Can this work? I guess it can't.
if srcKind != reflect.Ptr && srcElement.CanAddr() {
srcPtr := srcElement.Addr()
srcElement = reflect.ValueOf(srcPtr)
srcKind = reflect.Ptr
}
}
if !srcElement.IsValid() {
continue
}
if srcKind == dstKind {
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else if dstKind == reflect.Interface && dstElement.Kind() == reflect.Interface {
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else if srcKind == reflect.Map {
if err = deepMap(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
} else {
return fmt.Errorf("type mismatch on %s field: found %v, expected %v", fieldName, srcKind, dstKind)
}
}
}
return
}
// Map sets fields' values in dst from src.
// src can be a map with string keys or a struct. dst must be the opposite:
// if src is a map, dst must be a valid pointer to struct. If src is a struct,
// dst must be map[string]interface{}.
// It won't merge unexported (private) fields and will do recursively
// any exported field.
// If dst is a map, keys will be src fields' names in lower camel case.
// Missing key in src that doesn't match a field in dst will be skipped. This
// doesn't apply if dst is a map.
// This is separated method from Merge because it is cleaner and it keeps sane
// semantics: merging equal types, mapping different (restricted) types.
func Map(dst, src interface{}, opts ...func(*Config)) error {
return _map(dst, src, opts...)
}
// MapWithOverwrite will do the same as Map except that non-empty dst attributes will be overridden by
// non-empty src attribute values.
// Deprecated: Use Map(…) with WithOverride
func MapWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
return _map(dst, src, append(opts, WithOverride)...)
}
func _map(dst, src interface{}, opts ...func(*Config)) error {
if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr {
return ErrNonPointerArgument
}
var (
vDst, vSrc reflect.Value
err error
)
config := &Config{}
for _, opt := range opts {
opt(config)
}
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
// To be friction-less, we redirect equal-type arguments
// to deepMerge. Only because arguments can be anything.
if vSrc.Kind() == vDst.Kind() {
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
switch vSrc.Kind() {
case reflect.Struct:
if vDst.Kind() != reflect.Map {
return ErrExpectedMapAsDestination
}
case reflect.Map:
if vDst.Kind() != reflect.Struct {
return ErrExpectedStructAsDestination
}
default:
return ErrNotSupported
}
return deepMap(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
================================================
FILE: vendor/dario.cat/mergo/merge.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"fmt"
"reflect"
)
func hasMergeableFields(dst reflect.Value) (exported bool) {
for i, n := 0, dst.NumField(); i < n; i++ {
field := dst.Type().Field(i)
if field.Anonymous && dst.Field(i).Kind() == reflect.Struct {
exported = exported || hasMergeableFields(dst.Field(i))
} else if isExportedComponent(&field) {
exported = exported || len(field.PkgPath) == 0
}
}
return
}
func isExportedComponent(field *reflect.StructField) bool {
pkgPath := field.PkgPath
if len(pkgPath) > 0 {
return false
}
c := field.Name[0]
if 'a' <= c && c <= 'z' || c == '_' {
return false
}
return true
}
type Config struct {
Transformers Transformers
Overwrite bool
ShouldNotDereference bool
AppendSlice bool
TypeCheck bool
overwriteWithEmptyValue bool
overwriteSliceWithEmptyValue bool
sliceDeepCopy bool
debug bool
}
type Transformers interface {
Transformer(reflect.Type) func(dst, src reflect.Value) error
}
// Traverses recursively both values, assigning src's fields values to dst.
// The map argument tracks comparisons that have already been seen, which allows
// short circuiting on recursive types.
func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) {
overwrite := config.Overwrite
typeCheck := config.TypeCheck
overwriteWithEmptySrc := config.overwriteWithEmptyValue
overwriteSliceWithEmptySrc := config.overwriteSliceWithEmptyValue
sliceDeepCopy := config.sliceDeepCopy
if !src.IsValid() {
return
}
if dst.CanAddr() {
addr := dst.UnsafeAddr()
h := 17 * addr
seen := visited[h]
typ := dst.Type()
for p := seen; p != nil; p = p.next {
if p.ptr == addr && p.typ == typ {
return nil
}
}
// Remember, remember...
visited[h] = &visit{typ, seen, addr}
}
if config.Transformers != nil && !isReflectNil(dst) && dst.IsValid() {
if fn := config.Transformers.Transformer(dst.Type()); fn != nil {
err = fn(dst, src)
return
}
}
switch dst.Kind() {
case reflect.Struct:
if hasMergeableFields(dst) {
for i, n := 0, dst.NumField(); i < n; i++ {
if err = deepMerge(dst.Field(i), src.Field(i), visited, depth+1, config); err != nil {
return
}
}
} else {
if dst.CanSet() && (isReflectNil(dst) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc) {
dst.Set(src)
}
}
case reflect.Map:
if dst.IsNil() && !src.IsNil() {
if dst.CanSet() {
dst.Set(reflect.MakeMap(dst.Type()))
} else {
dst = src
return
}
}
if src.Kind() != reflect.Map {
if overwrite && dst.CanSet() {
dst.Set(src)
}
return
}
for _, key := range src.MapKeys() {
srcElement := src.MapIndex(key)
if !srcElement.IsValid() {
continue
}
dstElement := dst.MapIndex(key)
switch srcElement.Kind() {
case reflect.Chan, reflect.Func, reflect.Map, reflect.Interface, reflect.Slice:
if srcElement.IsNil() {
if overwrite {
dst.SetMapIndex(key, srcElement)
}
continue
}
fallthrough
default:
if !srcElement.CanInterface() {
continue
}
switch reflect.TypeOf(srcElement.Interface()).Kind() {
case reflect.Struct:
fallthrough
case reflect.Ptr:
fallthrough
case reflect.Map:
srcMapElm := srcElement
dstMapElm := dstElement
if srcMapElm.CanInterface() {
srcMapElm = reflect.ValueOf(srcMapElm.Interface())
if dstMapElm.IsValid() {
dstMapElm = reflect.ValueOf(dstMapElm.Interface())
}
}
if err = deepMerge(dstMapElm, srcMapElm, visited, depth+1, config); err != nil {
return
}
case reflect.Slice:
srcSlice := reflect.ValueOf(srcElement.Interface())
var dstSlice reflect.Value
if !dstElement.IsValid() || dstElement.IsNil() {
dstSlice = reflect.MakeSlice(srcSlice.Type(), 0, srcSlice.Len())
} else {
dstSlice = reflect.ValueOf(dstElement.Interface())
}
if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy {
if typeCheck && srcSlice.Type() != dstSlice.Type() {
return fmt.Errorf("cannot override two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
}
dstSlice = srcSlice
} else if config.AppendSlice {
if srcSlice.Type() != dstSlice.Type() {
return fmt.Errorf("cannot append two slices with different type (%s, %s)", srcSlice.Type(), dstSlice.Type())
}
dstSlice = reflect.AppendSlice(dstSlice, srcSlice)
} else if sliceDeepCopy {
i := 0
for ; i < srcSlice.Len() && i < dstSlice.Len(); i++ {
srcElement := srcSlice.Index(i)
dstElement := dstSlice.Index(i)
if srcElement.CanInterface() {
srcElement = reflect.ValueOf(srcElement.Interface())
}
if dstElement.CanInterface() {
dstElement = reflect.ValueOf(dstElement.Interface())
}
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
}
}
dst.SetMapIndex(key, dstSlice)
}
}
if dstElement.IsValid() && !isEmptyValue(dstElement, !config.ShouldNotDereference) {
if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice {
continue
}
if reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map && reflect.TypeOf(dstElement.Interface()).Kind() == reflect.Map {
continue
}
}
if srcElement.IsValid() && ((srcElement.Kind() != reflect.Ptr && overwrite) || !dstElement.IsValid() || isEmptyValue(dstElement, !config.ShouldNotDereference)) {
if dst.IsNil() {
dst.Set(reflect.MakeMap(dst.Type()))
}
dst.SetMapIndex(key, srcElement)
}
}
// Ensure that all keys in dst are deleted if they are not in src.
if overwriteWithEmptySrc {
for _, key := range dst.MapKeys() {
srcElement := src.MapIndex(key)
if !srcElement.IsValid() {
dst.SetMapIndex(key, reflect.Value{})
}
}
}
case reflect.Slice:
if !dst.CanSet() {
break
}
if (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc || overwriteSliceWithEmptySrc) && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) && !config.AppendSlice && !sliceDeepCopy {
dst.Set(src)
} else if config.AppendSlice {
if src.Type() != dst.Type() {
return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type())
}
dst.Set(reflect.AppendSlice(dst, src))
} else if sliceDeepCopy {
for i := 0; i < src.Len() && i < dst.Len(); i++ {
srcElement := src.Index(i)
dstElement := dst.Index(i)
if srcElement.CanInterface() {
srcElement = reflect.ValueOf(srcElement.Interface())
}
if dstElement.CanInterface() {
dstElement = reflect.ValueOf(dstElement.Interface())
}
if err = deepMerge(dstElement, srcElement, visited, depth+1, config); err != nil {
return
}
}
}
case reflect.Ptr:
fallthrough
case reflect.Interface:
if isReflectNil(src) {
if overwriteWithEmptySrc && dst.CanSet() && src.Type().AssignableTo(dst.Type()) {
dst.Set(src)
}
break
}
if src.Kind() != reflect.Interface {
if dst.IsNil() || (src.Kind() != reflect.Ptr && overwrite) {
if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) {
dst.Set(src)
}
} else if src.Kind() == reflect.Ptr {
if !config.ShouldNotDereference {
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
} else if src.Elem().Kind() != reflect.Struct {
if overwriteWithEmptySrc || (overwrite && !src.IsNil()) || dst.IsNil() {
dst.Set(src)
}
}
} else if dst.Elem().Type() == src.Type() {
if err = deepMerge(dst.Elem(), src, visited, depth+1, config); err != nil {
return
}
} else {
return ErrDifferentArgumentsTypes
}
break
}
if dst.IsNil() || overwrite {
if dst.CanSet() && (overwrite || isEmptyValue(dst, !config.ShouldNotDereference)) {
dst.Set(src)
}
break
}
if dst.Elem().Kind() == src.Elem().Kind() {
if err = deepMerge(dst.Elem(), src.Elem(), visited, depth+1, config); err != nil {
return
}
break
}
default:
mustSet := (isEmptyValue(dst, !config.ShouldNotDereference) || overwrite) && (!isEmptyValue(src, !config.ShouldNotDereference) || overwriteWithEmptySrc)
if mustSet {
if dst.CanSet() {
dst.Set(src)
} else {
dst = src
}
}
}
return
}
// Merge will fill any empty for value type attributes on the dst struct using corresponding
// src attributes if they themselves are not empty. dst and src must be valid same-type structs
// and dst must be a pointer to struct.
// It won't merge unexported (private) fields and will do recursively any exported field.
func Merge(dst, src interface{}, opts ...func(*Config)) error {
return merge(dst, src, opts...)
}
// MergeWithOverwrite will do the same as Merge except that non-empty dst attributes will be overridden by
// non-empty src attribute values.
// Deprecated: use Merge(…) with WithOverride
func MergeWithOverwrite(dst, src interface{}, opts ...func(*Config)) error {
return merge(dst, src, append(opts, WithOverride)...)
}
// WithTransformers adds transformers to merge, allowing to customize the merging of some types.
func WithTransformers(transformers Transformers) func(*Config) {
return func(config *Config) {
config.Transformers = transformers
}
}
// WithOverride will make merge override non-empty dst attributes with non-empty src attributes values.
func WithOverride(config *Config) {
config.Overwrite = true
}
// WithOverwriteWithEmptyValue will make merge override non empty dst attributes with empty src attributes values.
func WithOverwriteWithEmptyValue(config *Config) {
config.Overwrite = true
config.overwriteWithEmptyValue = true
}
// WithOverrideEmptySlice will make merge override empty dst slice with empty src slice.
func WithOverrideEmptySlice(config *Config) {
config.overwriteSliceWithEmptyValue = true
}
// WithoutDereference prevents dereferencing pointers when evaluating whether they are empty
// (i.e. a non-nil pointer is never considered empty).
func WithoutDereference(config *Config) {
config.ShouldNotDereference = true
}
// WithAppendSlice will make merge append slices instead of overwriting it.
func WithAppendSlice(config *Config) {
config.AppendSlice = true
}
// WithTypeCheck will make merge check types while overwriting it (must be used with WithOverride).
func WithTypeCheck(config *Config) {
config.TypeCheck = true
}
// WithSliceDeepCopy will merge slice element one by one with Overwrite flag.
func WithSliceDeepCopy(config *Config) {
config.sliceDeepCopy = true
config.Overwrite = true
}
func merge(dst, src interface{}, opts ...func(*Config)) error {
if dst != nil && reflect.ValueOf(dst).Kind() != reflect.Ptr {
return ErrNonPointerArgument
}
var (
vDst, vSrc reflect.Value
err error
)
config := &Config{}
for _, opt := range opts {
opt(config)
}
if vDst, vSrc, err = resolveValues(dst, src); err != nil {
return err
}
if vDst.Type() != vSrc.Type() {
return ErrDifferentArgumentsTypes
}
return deepMerge(vDst, vSrc, make(map[uintptr]*visit), 0, config)
}
// IsReflectNil is the reflect value provided nil
func isReflectNil(v reflect.Value) bool {
k := v.Kind()
switch k {
case reflect.Interface, reflect.Slice, reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr:
// Both interface and slice are nil if first word is 0.
// Both are always bigger than a word; assume flagIndir.
return v.IsNil()
default:
return false
}
}
================================================
FILE: vendor/dario.cat/mergo/mergo.go
================================================
// Copyright 2013 Dario Castañé. All rights reserved.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Based on src/pkg/reflect/deepequal.go from official
// golang's stdlib.
package mergo
import (
"errors"
"reflect"
)
// Errors reported by Mergo when it finds invalid arguments.
var (
ErrNilArguments = errors.New("src and dst must not be nil")
ErrDifferentArgumentsTypes = errors.New("src and dst must be of same type")
ErrNotSupported = errors.New("only structs, maps, and slices are supported")
ErrExpectedMapAsDestination = errors.New("dst was expected to be a map")
ErrExpectedStructAsDestination = errors.New("dst was expected to be a struct")
ErrNonPointerArgument = errors.New("dst must be a pointer")
)
// During deepMerge, must keep track of checks that are
// in progress. The comparison algorithm assumes that all
// checks in progress are true when it reencounters them.
// Visited are stored in a map indexed by 17 * a1 + a2;
type visit struct {
typ reflect.Type
next *visit
ptr uintptr
}
// From src/pkg/encoding/json/encode.go.
func isEmptyValue(v reflect.Value, shouldDereference bool) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr:
if v.IsNil() {
return true
}
if shouldDereference {
return isEmptyValue(v.Elem(), shouldDereference)
}
return false
case reflect.Func:
return v.IsNil()
case reflect.Invalid:
return true
}
return false
}
func resolveValues(dst, src interface{}) (vDst, vSrc reflect.Value, err error) {
if dst == nil || src == nil {
err = ErrNilArguments
return
}
vDst = reflect.ValueOf(dst).Elem()
if vDst.Kind() != reflect.Struct && vDst.Kind() != reflect.Map && vDst.Kind() != reflect.Slice {
err = ErrNotSupported
return
}
vSrc = reflect.ValueOf(src)
// We check if vSrc is a pointer to dereference it.
if vSrc.Kind() == reflect.Ptr {
vSrc = vSrc.Elem()
}
return
}
================================================
FILE: vendor/filippo.io/age/.gitattributes
================================================
*.age binary
testdata/testkit/* binary
================================================
FILE: vendor/filippo.io/age/AUTHORS
================================================
# This is the official list of age authors for copyright purposes.
# To be included, send a change adding the individual or company
# who owns a contribution's copyright.
Google LLC
Filippo Valsorda
================================================
FILE: vendor/filippo.io/age/LICENSE
================================================
Copyright 2019 The age Authors
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of the age project nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/filippo.io/age/README.md
================================================
[](https://pkg.go.dev/filippo.io/age)
[![man page]()](https://filippo.io/age/age.1)
[](https://age-encryption.org/v1)
age is a simple, modern and secure file encryption tool, format, and Go library.
It features small explicit keys, no config options, and UNIX-style composability.
```
$ age-keygen -o key.txt
Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
$ tar cvz ~/data | age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p > data.tar.gz.age
$ age --decrypt -i key.txt data.tar.gz.age > data.tar.gz
```
📜 The format specification is at [age-encryption.org/v1](https://age-encryption.org/v1). age was designed by [@Benjojo12](https://twitter.com/Benjojo12) and [@FiloSottile](https://twitter.com/FiloSottile).
📬 Follow the maintenance of this project by subscribing to [Maintainer Dispatches](https://filippo.io/newsletter)!
🦀 An alternative interoperable Rust implementation is available at [github.com/str4d/rage](https://github.com/str4d/rage).
🔑 Hardware PIV tokens such as YubiKeys are supported through the [age-plugin-yubikey](https://github.com/str4d/age-plugin-yubikey) plugin.
✨ For more plugins, implementations, tools, and integrations, check out the [awesome age](https://github.com/FiloSottile/awesome-age) list.
💬 The author pronounces it `[aɡe̞]` [with a hard *g*](https://translate.google.com/?sl=it&text=aghe), like GIF, and is always spelled lowercase.
## Installation
Homebrew (macOS or Linux)
brew install age
MacPorts
port install age
Alpine Linux v3.15+
apk add age
Arch Linux
pacman -S age
Debian 12+ (Bookworm)
apt install age
Debian 11 (Bullseye)
apt install age/bullseye-backports
(enable backports for age v1.0.0+)
Fedora 33+
dnf install age
Gentoo Linux
emerge app-crypt/age
NixOS / Nix
nix-env -i age
openSUSE Tumbleweed
zypper install age
Ubuntu 22.04+
apt install age
Void Linux
xbps-install age
FreeBSD
pkg install age (security/age)
OpenBSD 6.7+
pkg_add age (security/age)
Chocolatey (Windows)
choco install age.portable
Scoop (Windows)
scoop bucket add extras && scoop install age
pkgx
pkgx install age
On Windows, Linux, macOS, and FreeBSD you can use the pre-built binaries.
```
https://dl.filippo.io/age/latest?for=linux/amd64
https://dl.filippo.io/age/v1.1.1?for=darwin/arm64
...
```
If your system has [a supported version of Go](https://go.dev/dl/), you can build from source.
```
go install filippo.io/age/cmd/...@latest
```
Help from new packagers is very welcome.
### Verifying the release signatures
If you download the pre-built binaries, you can check their
[Sigsum](https://www.sigsum.org) proofs, which are like signatures with extra
transparency: you can cryptographically verify that every proof is logged in a
public append-only log, so you can hold the age project accountable for every
binary release we ever produced. This is similar to what the [Go Checksum
Database](https://go.dev/blog/module-mirror-launch) provides.
```
cat << EOF > age-sigsum-key.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM1WpnEswJLPzvXJDiswowy48U+G+G1kmgwUE2eaRHZG
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAz2WM5CyPLqiNjk7CLl4roDXwKhQ0QExXLebukZEZFS
EOF
cat << EOF > sigsum-trust-policy.txt
log 154f49976b59ff09a123675f58cb3e346e0455753c3c3b15d465dcb4f6512b0b https://poc.sigsum.org/jellyfish
witness poc.sigsum.org/nisse 1c25f8a44c635457e2e391d1efbca7d4c2951a0aef06225a881e46b98962ac6c
witness rgdd.se/poc-witness 28c92a5a3a054d317c86fc2eeb6a7ab2054d6217100d0be67ded5b74323c5806
group demo-quorum-rule all poc.sigsum.org/nisse rgdd.se/poc-witness
quorum demo-quorum-rule
EOF
curl -JLO "https://dl.filippo.io/age/v1.2.0?for=darwin/arm64"
curl -JLO "https://dl.filippo.io/age/v1.2.0?for=darwin/arm64&proof"
go install sigsum.org/sigsum-go/cmd/sigsum-verify@v0.8.0
sigsum-verify -k age-sigsum-key.pub -p sigsum-trust-policy.txt \
age-v1.2.0-darwin-arm64.tar.gz.proof < age-v1.2.0-darwin-arm64.tar.gz
```
You can learn more about what's happening above in the [Sigsum
docs](https://www.sigsum.org/getting-started/).
## Usage
For the full documentation, read [the age(1) man page](https://filippo.io/age/age.1).
```
Usage:
age [--encrypt] (-r RECIPIENT | -R PATH)... [--armor] [-o OUTPUT] [INPUT]
age [--encrypt] --passphrase [--armor] [-o OUTPUT] [INPUT]
age --decrypt [-i PATH]... [-o OUTPUT] [INPUT]
Options:
-e, --encrypt Encrypt the input to the output. Default if omitted.
-d, --decrypt Decrypt the input to the output.
-o, --output OUTPUT Write the result to the file at path OUTPUT.
-a, --armor Encrypt to a PEM encoded format.
-p, --passphrase Encrypt with a passphrase.
-r, --recipient RECIPIENT Encrypt to the specified RECIPIENT. Can be repeated.
-R, --recipients-file PATH Encrypt to recipients listed at PATH. Can be repeated.
-i, --identity PATH Use the identity file at PATH. Can be repeated.
INPUT defaults to standard input, and OUTPUT defaults to standard output.
If OUTPUT exists, it will be overwritten.
RECIPIENT can be an age public key generated by age-keygen ("age1...")
or an SSH public key ("ssh-ed25519 AAAA...", "ssh-rsa AAAA...").
Recipient files contain one or more recipients, one per line. Empty lines
and lines starting with "#" are ignored as comments. "-" may be used to
read recipients from standard input.
Identity files contain one or more secret keys ("AGE-SECRET-KEY-1..."),
one per line, or an SSH key. Empty lines and lines starting with "#" are
ignored as comments. Passphrase encrypted age files can be used as
identity files. Multiple key files can be provided, and any unused ones
will be ignored. "-" may be used to read identities from standard input.
When --encrypt is specified explicitly, -i can also be used to encrypt to an
identity file symmetrically, instead or in addition to normal recipients.
```
### Multiple recipients
Files can be encrypted to multiple recipients by repeating `-r/--recipient`. Every recipient will be able to decrypt the file.
```
$ age -o example.jpg.age -r age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p \
-r age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg example.jpg
```
#### Recipient files
Multiple recipients can also be listed one per line in one or more files passed with the `-R/--recipients-file` flag.
```
$ cat recipients.txt
# Alice
age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
# Bob
age1lggyhqrw2nlhcxprm67z43rta597azn8gknawjehu9d9dl0jq3yqqvfafg
$ age -R recipients.txt example.jpg > example.jpg.age
```
If the argument to `-R` (or `-i`) is `-`, the file is read from standard input.
### Passphrases
Files can be encrypted with a passphrase by using `-p/--passphrase`. By default age will automatically generate a secure passphrase. Passphrase protected files are automatically detected at decrypt time.
```
$ age -p secrets.txt > secrets.txt.age
Enter passphrase (leave empty to autogenerate a secure one):
Using the autogenerated passphrase "release-response-step-brand-wrap-ankle-pair-unusual-sword-train".
$ age -d secrets.txt.age > secrets.txt
Enter passphrase:
```
### Passphrase-protected key files
If an identity file passed to `-i` is a passphrase encrypted age file, it will be automatically decrypted.
```
$ age-keygen | age -p > key.age
Public key: age1yhm4gctwfmrpz87tdslm550wrx6m79y9f2hdzt0lndjnehwj0ukqrjpyx5
Enter passphrase (leave empty to autogenerate a secure one):
Using the autogenerated passphrase "hip-roast-boring-snake-mention-east-wasp-honey-input-actress".
$ age -r age1yhm4gctwfmrpz87tdslm550wrx6m79y9f2hdzt0lndjnehwj0ukqrjpyx5 secrets.txt > secrets.txt.age
$ age -d -i key.age secrets.txt.age > secrets.txt
Enter passphrase for identity file "key.age":
```
Passphrase-protected identity files are not necessary for most use cases, where access to the encrypted identity file implies access to the whole system. However, they can be useful if the identity file is stored remotely.
### SSH keys
As a convenience feature, age also supports encrypting to `ssh-rsa` and `ssh-ed25519` SSH public keys, and decrypting with the respective private key file. (`ssh-agent` is not supported.)
```
$ age -R ~/.ssh/id_ed25519.pub example.jpg > example.jpg.age
$ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg
```
Note that SSH key support employs more complex cryptography, and embeds a public key tag in the encrypted file, making it possible to track files that are encrypted to a specific public key.
#### Encrypting to a GitHub user
Combining SSH key support and `-R`, you can easily encrypt a file to the SSH keys listed on a GitHub profile.
```
$ curl https://github.com/benjojo.keys | age -R - example.jpg > example.jpg.age
```
Keep in mind that people might not protect SSH keys long-term, since they are revokable when used only for authentication, and that SSH keys held on YubiKeys can't be used to decrypt files.
================================================
FILE: vendor/filippo.io/age/age.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package age implements file encryption according to the age-encryption.org/v1
// specification.
//
// For most use cases, use the Encrypt and Decrypt functions with
// X25519Recipient and X25519Identity. If passphrase encryption is required, use
// ScryptRecipient and ScryptIdentity. For compatibility with existing SSH keys
// use the filippo.io/age/agessh package.
//
// age encrypted files are binary and not malleable. For encoding them as text,
// use the filippo.io/age/armor package.
//
// # Key management
//
// age does not have a global keyring. Instead, since age keys are small,
// textual, and cheap, you are encouraged to generate dedicated keys for each
// task and application.
//
// Recipient public keys can be passed around as command line flags and in
// config files, while secret keys should be stored in dedicated files, through
// secret management systems, or as environment variables.
//
// There is no default path for age keys. Instead, they should be stored at
// application-specific paths. The CLI supports files where private keys are
// listed one per line, ignoring empty lines and lines starting with "#". These
// files can be parsed with ParseIdentities.
//
// When integrating age into a new system, it's recommended that you only
// support X25519 keys, and not SSH keys. The latter are supported for manual
// encryption operations. If you need to tie into existing key management
// infrastructure, you might want to consider implementing your own Recipient
// and Identity.
//
// # Backwards compatibility
//
// Files encrypted with a stable version (not alpha, beta, or release candidate)
// of age, or with any v1.0.0 beta or release candidate, will decrypt with any
// later versions of the v1 API. This might change in v2, in which case v1 will
// be maintained with security fixes for compatibility with older files.
//
// If decrypting an older file poses a security risk, doing so might require an
// explicit opt-in in the API.
package age
import (
"crypto/hmac"
"crypto/rand"
"errors"
"fmt"
"io"
"sort"
"filippo.io/age/internal/format"
"filippo.io/age/internal/stream"
)
// An Identity is passed to Decrypt to unwrap an opaque file key from a
// recipient stanza. It can be for example a secret key like X25519Identity, a
// plugin, or a custom implementation.
//
// Unwrap must return an error wrapping ErrIncorrectIdentity if none of the
// recipient stanzas match the identity, any other error will be considered
// fatal.
//
// Most age API users won't need to interact with this directly, and should
// instead pass Recipient implementations to Encrypt and Identity
// implementations to Decrypt.
type Identity interface {
Unwrap(stanzas []*Stanza) (fileKey []byte, err error)
}
var ErrIncorrectIdentity = errors.New("incorrect identity for recipient block")
// A Recipient is passed to Encrypt to wrap an opaque file key to one or more
// recipient stanza(s). It can be for example a public key like X25519Recipient,
// a plugin, or a custom implementation.
//
// Most age API users won't need to interact with this directly, and should
// instead pass Recipient implementations to Encrypt and Identity
// implementations to Decrypt.
type Recipient interface {
Wrap(fileKey []byte) ([]*Stanza, error)
}
// RecipientWithLabels can be optionally implemented by a Recipient, in which
// case Encrypt will use WrapWithLabels instead of Wrap.
//
// Encrypt will succeed only if the labels returned by all the recipients
// (assuming the empty set for those that don't implement RecipientWithLabels)
// are the same.
//
// This can be used to ensure a recipient is only used with other recipients
// with equivalent properties (for example by setting a "postquantum" label) or
// to ensure a recipient is always used alone (by returning a random label, for
// example to preserve its authentication properties).
type RecipientWithLabels interface {
WrapWithLabels(fileKey []byte) (s []*Stanza, labels []string, err error)
}
// A Stanza is a section of the age header that encapsulates the file key as
// encrypted to a specific recipient.
//
// Most age API users won't need to interact with this directly, and should
// instead pass Recipient implementations to Encrypt and Identity
// implementations to Decrypt.
type Stanza struct {
Type string
Args []string
Body []byte
}
const fileKeySize = 16
const streamNonceSize = 16
// Encrypt encrypts a file to one or more recipients.
//
// Writes to the returned WriteCloser are encrypted and written to dst as an age
// file. Every recipient will be able to decrypt the file.
//
// The caller must call Close on the WriteCloser when done for the last chunk to
// be encrypted and flushed to dst.
func Encrypt(dst io.Writer, recipients ...Recipient) (io.WriteCloser, error) {
if len(recipients) == 0 {
return nil, errors.New("no recipients specified")
}
fileKey := make([]byte, fileKeySize)
if _, err := rand.Read(fileKey); err != nil {
return nil, err
}
hdr := &format.Header{}
var labels []string
for i, r := range recipients {
stanzas, l, err := wrapWithLabels(r, fileKey)
if err != nil {
return nil, fmt.Errorf("failed to wrap key for recipient #%d: %v", i, err)
}
sort.Strings(l)
if i == 0 {
labels = l
} else if !slicesEqual(labels, l) {
return nil, fmt.Errorf("incompatible recipients")
}
for _, s := range stanzas {
hdr.Recipients = append(hdr.Recipients, (*format.Stanza)(s))
}
}
if mac, err := headerMAC(fileKey, hdr); err != nil {
return nil, fmt.Errorf("failed to compute header MAC: %v", err)
} else {
hdr.MAC = mac
}
if err := hdr.Marshal(dst); err != nil {
return nil, fmt.Errorf("failed to write header: %v", err)
}
nonce := make([]byte, streamNonceSize)
if _, err := rand.Read(nonce); err != nil {
return nil, err
}
if _, err := dst.Write(nonce); err != nil {
return nil, fmt.Errorf("failed to write nonce: %v", err)
}
return stream.NewWriter(streamKey(fileKey, nonce), dst)
}
func wrapWithLabels(r Recipient, fileKey []byte) (s []*Stanza, labels []string, err error) {
if r, ok := r.(RecipientWithLabels); ok {
return r.WrapWithLabels(fileKey)
}
s, err = r.Wrap(fileKey)
return
}
func slicesEqual(s1, s2 []string) bool {
if len(s1) != len(s2) {
return false
}
for i := range s1 {
if s1[i] != s2[i] {
return false
}
}
return true
}
// NoIdentityMatchError is returned by Decrypt when none of the supplied
// identities match the encrypted file.
type NoIdentityMatchError struct {
// Errors is a slice of all the errors returned to Decrypt by the Unwrap
// calls it made. They all wrap ErrIncorrectIdentity.
Errors []error
}
func (*NoIdentityMatchError) Error() string {
return "no identity matched any of the recipients"
}
// Decrypt decrypts a file encrypted to one or more identities.
//
// It returns a Reader reading the decrypted plaintext of the age file read
// from src. All identities will be tried until one successfully decrypts the file.
func Decrypt(src io.Reader, identities ...Identity) (io.Reader, error) {
if len(identities) == 0 {
return nil, errors.New("no identities specified")
}
hdr, payload, err := format.Parse(src)
if err != nil {
return nil, fmt.Errorf("failed to read header: %w", err)
}
stanzas := make([]*Stanza, 0, len(hdr.Recipients))
for _, s := range hdr.Recipients {
stanzas = append(stanzas, (*Stanza)(s))
}
errNoMatch := &NoIdentityMatchError{}
var fileKey []byte
for _, id := range identities {
fileKey, err = id.Unwrap(stanzas)
if errors.Is(err, ErrIncorrectIdentity) {
errNoMatch.Errors = append(errNoMatch.Errors, err)
continue
}
if err != nil {
return nil, err
}
break
}
if fileKey == nil {
return nil, errNoMatch
}
if mac, err := headerMAC(fileKey, hdr); err != nil {
return nil, fmt.Errorf("failed to compute header MAC: %v", err)
} else if !hmac.Equal(mac, hdr.MAC) {
return nil, errors.New("bad header MAC")
}
nonce := make([]byte, streamNonceSize)
if _, err := io.ReadFull(payload, nonce); err != nil {
return nil, fmt.Errorf("failed to read nonce: %w", err)
}
return stream.NewReader(streamKey(fileKey, nonce), payload)
}
// multiUnwrap is a helper that implements Identity.Unwrap in terms of a
// function that unwraps a single recipient stanza.
func multiUnwrap(unwrap func(*Stanza) ([]byte, error), stanzas []*Stanza) ([]byte, error) {
for _, s := range stanzas {
fileKey, err := unwrap(s)
if errors.Is(err, ErrIncorrectIdentity) {
// If we ever start returning something interesting wrapping
// ErrIncorrectIdentity, we should let it make its way up through
// Decrypt into NoIdentityMatchError.Errors.
continue
}
if err != nil {
return nil, err
}
return fileKey, nil
}
return nil, ErrIncorrectIdentity
}
================================================
FILE: vendor/filippo.io/age/armor/armor.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package armor provides a strict, streaming implementation of the ASCII
// armoring format for age files.
//
// It's PEM with type "AGE ENCRYPTED FILE", 64 character columns, no headers,
// and strict base64 decoding.
package armor
import (
"bufio"
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"filippo.io/age/internal/format"
)
const (
Header = "-----BEGIN AGE ENCRYPTED FILE-----"
Footer = "-----END AGE ENCRYPTED FILE-----"
)
type armoredWriter struct {
started, closed bool
encoder *format.WrappedBase64Encoder
dst io.Writer
}
func (a *armoredWriter) Write(p []byte) (int, error) {
if !a.started {
if _, err := io.WriteString(a.dst, Header+"\n"); err != nil {
return 0, err
}
}
a.started = true
return a.encoder.Write(p)
}
func (a *armoredWriter) Close() error {
if a.closed {
return errors.New("ArmoredWriter already closed")
}
a.closed = true
if err := a.encoder.Close(); err != nil {
return err
}
footer := Footer + "\n"
if !a.encoder.LastLineIsEmpty() {
footer = "\n" + footer
}
_, err := io.WriteString(a.dst, footer)
return err
}
func NewWriter(dst io.Writer) io.WriteCloser {
// TODO: write a test with aligned and misaligned sizes, and 8 and 10 steps.
return &armoredWriter{
dst: dst,
encoder: format.NewWrappedBase64Encoder(base64.StdEncoding, dst),
}
}
type armoredReader struct {
r *bufio.Reader
started bool
unread []byte // backed by buf
buf [format.BytesPerLine]byte
err error
}
func NewReader(r io.Reader) io.Reader {
return &armoredReader{r: bufio.NewReader(r)}
}
func (r *armoredReader) Read(p []byte) (int, error) {
if len(r.unread) > 0 {
n := copy(p, r.unread)
r.unread = r.unread[n:]
return n, nil
}
if r.err != nil {
return 0, r.err
}
getLine := func() ([]byte, error) {
line, err := r.r.ReadBytes('\n')
if err == io.EOF && len(line) == 0 {
return nil, io.ErrUnexpectedEOF
} else if err != nil && err != io.EOF {
return nil, err
}
line = bytes.TrimSuffix(line, []byte("\n"))
line = bytes.TrimSuffix(line, []byte("\r"))
return line, nil
}
const maxWhitespace = 1024
drainTrailing := func() error {
buf, err := io.ReadAll(io.LimitReader(r.r, maxWhitespace))
if err != nil {
return err
}
if len(bytes.TrimSpace(buf)) != 0 {
return errors.New("trailing data after armored file")
}
if len(buf) == maxWhitespace {
return errors.New("too much trailing whitespace")
}
return io.EOF
}
var removedWhitespace int
for !r.started {
line, err := getLine()
if err != nil {
return 0, r.setErr(err)
}
// Ignore leading whitespace.
if len(bytes.TrimSpace(line)) == 0 {
removedWhitespace += len(line) + 1
if removedWhitespace > maxWhitespace {
return 0, r.setErr(errors.New("too much leading whitespace"))
}
continue
}
if string(line) != Header {
return 0, r.setErr(fmt.Errorf("invalid first line: %q", line))
}
r.started = true
}
line, err := getLine()
if err != nil {
return 0, r.setErr(err)
}
if string(line) == Footer {
return 0, r.setErr(drainTrailing())
}
if len(line) > format.ColumnsPerLine {
return 0, r.setErr(errors.New("column limit exceeded"))
}
r.unread = r.buf[:]
n, err := base64.StdEncoding.Strict().Decode(r.unread, line)
if err != nil {
return 0, r.setErr(err)
}
r.unread = r.unread[:n]
if n < format.BytesPerLine {
line, err := getLine()
if err != nil {
return 0, r.setErr(err)
}
if string(line) != Footer {
return 0, r.setErr(fmt.Errorf("invalid closing line: %q", line))
}
r.setErr(drainTrailing())
}
nn := copy(p, r.unread)
r.unread = r.unread[nn:]
return nn, nil
}
type Error struct {
err error
}
func (e *Error) Error() string {
return "invalid armor: " + e.err.Error()
}
func (e *Error) Unwrap() error {
return e.err
}
func (r *armoredReader) setErr(err error) error {
if err != io.EOF {
err = &Error{err}
}
r.err = err
return err
}
================================================
FILE: vendor/filippo.io/age/internal/bech32/bech32.go
================================================
// Copyright (c) 2017 Takatoshi Nakagawa
// Copyright (c) 2019 The age Authors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
// Package bech32 is a modified version of the reference implementation of BIP173.
package bech32
import (
"fmt"
"strings"
)
var charset = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
var generator = []uint32{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
func polymod(values []byte) uint32 {
chk := uint32(1)
for _, v := range values {
top := chk >> 25
chk = (chk & 0x1ffffff) << 5
chk = chk ^ uint32(v)
for i := 0; i < 5; i++ {
bit := top >> i & 1
if bit == 1 {
chk ^= generator[i]
}
}
}
return chk
}
func hrpExpand(hrp string) []byte {
h := []byte(strings.ToLower(hrp))
var ret []byte
for _, c := range h {
ret = append(ret, c>>5)
}
ret = append(ret, 0)
for _, c := range h {
ret = append(ret, c&31)
}
return ret
}
func verifyChecksum(hrp string, data []byte) bool {
return polymod(append(hrpExpand(hrp), data...)) == 1
}
func createChecksum(hrp string, data []byte) []byte {
values := append(hrpExpand(hrp), data...)
values = append(values, []byte{0, 0, 0, 0, 0, 0}...)
mod := polymod(values) ^ 1
ret := make([]byte, 6)
for p := range ret {
shift := 5 * (5 - p)
ret[p] = byte(mod>>shift) & 31
}
return ret
}
func convertBits(data []byte, frombits, tobits byte, pad bool) ([]byte, error) {
var ret []byte
acc := uint32(0)
bits := byte(0)
maxv := byte(1<>frombits != 0 {
return nil, fmt.Errorf("invalid data range: data[%d]=%d (frombits=%d)", idx, value, frombits)
}
acc = acc<= tobits {
bits -= tobits
ret = append(ret, byte(acc>>bits)&maxv)
}
}
if pad {
if bits > 0 {
ret = append(ret, byte(acc<<(tobits-bits))&maxv)
}
} else if bits >= frombits {
return nil, fmt.Errorf("illegal zero padding")
} else if byte(acc<<(tobits-bits))&maxv != 0 {
return nil, fmt.Errorf("non-zero padding")
}
return ret, nil
}
// Encode encodes the HRP and a bytes slice to Bech32. If the HRP is uppercase,
// the output will be uppercase.
func Encode(hrp string, data []byte) (string, error) {
values, err := convertBits(data, 8, 5, true)
if err != nil {
return "", err
}
if len(hrp) < 1 {
return "", fmt.Errorf("invalid HRP: %q", hrp)
}
for p, c := range hrp {
if c < 33 || c > 126 {
return "", fmt.Errorf("invalid HRP character: hrp[%d]=%d", p, c)
}
}
if strings.ToUpper(hrp) != hrp && strings.ToLower(hrp) != hrp {
return "", fmt.Errorf("mixed case HRP: %q", hrp)
}
lower := strings.ToLower(hrp) == hrp
hrp = strings.ToLower(hrp)
var ret strings.Builder
ret.WriteString(hrp)
ret.WriteString("1")
for _, p := range values {
ret.WriteByte(charset[p])
}
for _, p := range createChecksum(hrp, values) {
ret.WriteByte(charset[p])
}
if lower {
return ret.String(), nil
}
return strings.ToUpper(ret.String()), nil
}
// Decode decodes a Bech32 string. If the string is uppercase, the HRP will be uppercase.
func Decode(s string) (hrp string, data []byte, err error) {
if strings.ToLower(s) != s && strings.ToUpper(s) != s {
return "", nil, fmt.Errorf("mixed case")
}
pos := strings.LastIndex(s, "1")
if pos < 1 || pos+7 > len(s) {
return "", nil, fmt.Errorf("separator '1' at invalid position: pos=%d, len=%d", pos, len(s))
}
hrp = s[:pos]
for p, c := range hrp {
if c < 33 || c > 126 {
return "", nil, fmt.Errorf("invalid character human-readable part: s[%d]=%d", p, c)
}
}
s = strings.ToLower(s)
for p, c := range s[pos+1:] {
d := strings.IndexRune(charset, c)
if d == -1 {
return "", nil, fmt.Errorf("invalid character data part: s[%d]=%v", p, c)
}
data = append(data, byte(d))
}
if !verifyChecksum(hrp, data) {
return "", nil, fmt.Errorf("invalid checksum")
}
data, err = convertBits(data[:len(data)-6], 5, 8, false)
if err != nil {
return "", nil, err
}
return hrp, data, nil
}
================================================
FILE: vendor/filippo.io/age/internal/format/format.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package format implements the age file format.
package format
import (
"bufio"
"bytes"
"encoding/base64"
"errors"
"fmt"
"io"
"strings"
)
type Header struct {
Recipients []*Stanza
MAC []byte
}
// Stanza is assignable to age.Stanza, and if this package is made public,
// age.Stanza can be made a type alias of this type.
type Stanza struct {
Type string
Args []string
Body []byte
}
var b64 = base64.RawStdEncoding.Strict()
func DecodeString(s string) ([]byte, error) {
// CR and LF are ignored by DecodeString, but we don't want any malleability.
if strings.ContainsAny(s, "\n\r") {
return nil, errors.New(`unexpected newline character`)
}
return b64.DecodeString(s)
}
var EncodeToString = b64.EncodeToString
const ColumnsPerLine = 64
const BytesPerLine = ColumnsPerLine / 4 * 3
// NewWrappedBase64Encoder returns a WrappedBase64Encoder that writes to dst.
func NewWrappedBase64Encoder(enc *base64.Encoding, dst io.Writer) *WrappedBase64Encoder {
w := &WrappedBase64Encoder{dst: dst}
w.enc = base64.NewEncoder(enc, WriterFunc(w.writeWrapped))
return w
}
type WriterFunc func(p []byte) (int, error)
func (f WriterFunc) Write(p []byte) (int, error) { return f(p) }
// WrappedBase64Encoder is a standard base64 encoder that inserts an LF
// character every ColumnsPerLine bytes. It does not insert a newline neither at
// the beginning nor at the end of the stream, but it ensures the last line is
// shorter than ColumnsPerLine, which means it might be empty.
type WrappedBase64Encoder struct {
enc io.WriteCloser
dst io.Writer
written int
buf bytes.Buffer
}
func (w *WrappedBase64Encoder) Write(p []byte) (int, error) { return w.enc.Write(p) }
func (w *WrappedBase64Encoder) Close() error {
return w.enc.Close()
}
func (w *WrappedBase64Encoder) writeWrapped(p []byte) (int, error) {
if w.buf.Len() != 0 {
panic("age: internal error: non-empty WrappedBase64Encoder.buf")
}
for len(p) > 0 {
toWrite := ColumnsPerLine - (w.written % ColumnsPerLine)
if toWrite > len(p) {
toWrite = len(p)
}
n, _ := w.buf.Write(p[:toWrite])
w.written += n
p = p[n:]
if w.written%ColumnsPerLine == 0 {
w.buf.Write([]byte("\n"))
}
}
if _, err := w.buf.WriteTo(w.dst); err != nil {
// We always return n = 0 on error because it's hard to work back to the
// input length that ended up written out. Not ideal, but Write errors
// are not recoverable anyway.
return 0, err
}
return len(p), nil
}
// LastLineIsEmpty returns whether the last output line was empty, either
// because no input was written, or because a multiple of BytesPerLine was.
//
// Calling LastLineIsEmpty before Close is meaningless.
func (w *WrappedBase64Encoder) LastLineIsEmpty() bool {
return w.written%ColumnsPerLine == 0
}
const intro = "age-encryption.org/v1\n"
var stanzaPrefix = []byte("->")
var footerPrefix = []byte("---")
func (r *Stanza) Marshal(w io.Writer) error {
if _, err := w.Write(stanzaPrefix); err != nil {
return err
}
for _, a := range append([]string{r.Type}, r.Args...) {
if _, err := io.WriteString(w, " "+a); err != nil {
return err
}
}
if _, err := io.WriteString(w, "\n"); err != nil {
return err
}
ww := NewWrappedBase64Encoder(b64, w)
if _, err := ww.Write(r.Body); err != nil {
return err
}
if err := ww.Close(); err != nil {
return err
}
_, err := io.WriteString(w, "\n")
return err
}
func (h *Header) MarshalWithoutMAC(w io.Writer) error {
if _, err := io.WriteString(w, intro); err != nil {
return err
}
for _, r := range h.Recipients {
if err := r.Marshal(w); err != nil {
return err
}
}
_, err := fmt.Fprintf(w, "%s", footerPrefix)
return err
}
func (h *Header) Marshal(w io.Writer) error {
if err := h.MarshalWithoutMAC(w); err != nil {
return err
}
mac := b64.EncodeToString(h.MAC)
_, err := fmt.Fprintf(w, " %s\n", mac)
return err
}
type StanzaReader struct {
r *bufio.Reader
err error
}
func NewStanzaReader(r *bufio.Reader) *StanzaReader {
return &StanzaReader{r: r}
}
func (r *StanzaReader) ReadStanza() (s *Stanza, err error) {
// Read errors are unrecoverable.
if r.err != nil {
return nil, r.err
}
defer func() { r.err = err }()
s = &Stanza{}
line, err := r.r.ReadBytes('\n')
if err != nil {
return nil, fmt.Errorf("failed to read line: %w", err)
}
if !bytes.HasPrefix(line, stanzaPrefix) {
return nil, fmt.Errorf("malformed stanza opening line: %q", line)
}
prefix, args := splitArgs(line)
if prefix != string(stanzaPrefix) || len(args) < 1 {
return nil, fmt.Errorf("malformed stanza: %q", line)
}
for _, a := range args {
if !isValidString(a) {
return nil, fmt.Errorf("malformed stanza: %q", line)
}
}
s.Type = args[0]
s.Args = args[1:]
for {
line, err := r.r.ReadBytes('\n')
if err != nil {
return nil, fmt.Errorf("failed to read line: %w", err)
}
b, err := DecodeString(strings.TrimSuffix(string(line), "\n"))
if err != nil {
if bytes.HasPrefix(line, footerPrefix) || bytes.HasPrefix(line, stanzaPrefix) {
return nil, fmt.Errorf("malformed body line %q: stanza ended without a short line\nnote: this might be a file encrypted with an old beta version of age or rage; use age v1.0.0-beta6 or rage to decrypt it", line)
}
return nil, errorf("malformed body line %q: %v", line, err)
}
if len(b) > BytesPerLine {
return nil, errorf("malformed body line %q: too long", line)
}
s.Body = append(s.Body, b...)
if len(b) < BytesPerLine {
// A stanza body always ends with a short line.
return s, nil
}
}
}
type ParseError struct {
err error
}
func (e *ParseError) Error() string {
return "parsing age header: " + e.err.Error()
}
func (e *ParseError) Unwrap() error {
return e.err
}
func errorf(format string, a ...interface{}) error {
return &ParseError{fmt.Errorf(format, a...)}
}
// Parse returns the header and a Reader that begins at the start of the
// payload.
func Parse(input io.Reader) (*Header, io.Reader, error) {
h := &Header{}
rr := bufio.NewReader(input)
line, err := rr.ReadString('\n')
if err != nil {
return nil, nil, errorf("failed to read intro: %w", err)
}
if line != intro {
return nil, nil, errorf("unexpected intro: %q", line)
}
sr := NewStanzaReader(rr)
for {
peek, err := rr.Peek(len(footerPrefix))
if err != nil {
return nil, nil, errorf("failed to read header: %w", err)
}
if bytes.Equal(peek, footerPrefix) {
line, err := rr.ReadBytes('\n')
if err != nil {
return nil, nil, fmt.Errorf("failed to read header: %w", err)
}
prefix, args := splitArgs(line)
if prefix != string(footerPrefix) || len(args) != 1 {
return nil, nil, errorf("malformed closing line: %q", line)
}
h.MAC, err = DecodeString(args[0])
if err != nil || len(h.MAC) != 32 {
return nil, nil, errorf("malformed closing line %q: %v", line, err)
}
break
}
s, err := sr.ReadStanza()
if err != nil {
return nil, nil, fmt.Errorf("failed to parse header: %w", err)
}
h.Recipients = append(h.Recipients, s)
}
// If input is a bufio.Reader, rr might be equal to input because
// bufio.NewReader short-circuits. In this case we can just return it (and
// we would end up reading the buffer twice if we prepended the peek below).
if rr == input {
return h, rr, nil
}
// Otherwise, unwind the bufio overread and return the unbuffered input.
buf, err := rr.Peek(rr.Buffered())
if err != nil {
return nil, nil, errorf("internal error: %v", err)
}
payload := io.MultiReader(bytes.NewReader(buf), input)
return h, payload, nil
}
func splitArgs(line []byte) (string, []string) {
l := strings.TrimSuffix(string(line), "\n")
parts := strings.Split(l, " ")
return parts[0], parts[1:]
}
func isValidString(s string) bool {
if len(s) == 0 {
return false
}
for _, c := range s {
if c < 33 || c > 126 {
return false
}
}
return true
}
================================================
FILE: vendor/filippo.io/age/internal/stream/stream.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package stream implements a variant of the STREAM chunked encryption scheme.
package stream
import (
"crypto/cipher"
"errors"
"fmt"
"io"
"golang.org/x/crypto/chacha20poly1305"
)
const ChunkSize = 64 * 1024
type Reader struct {
a cipher.AEAD
src io.Reader
unread []byte // decrypted but unread data, backed by buf
buf [encChunkSize]byte
err error
nonce [chacha20poly1305.NonceSize]byte
}
const (
encChunkSize = ChunkSize + chacha20poly1305.Overhead
lastChunkFlag = 0x01
)
func NewReader(key []byte, src io.Reader) (*Reader, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
return &Reader{
a: aead,
src: src,
}, nil
}
func (r *Reader) Read(p []byte) (int, error) {
if len(r.unread) > 0 {
n := copy(p, r.unread)
r.unread = r.unread[n:]
return n, nil
}
if r.err != nil {
return 0, r.err
}
if len(p) == 0 {
return 0, nil
}
last, err := r.readChunk()
if err != nil {
r.err = err
return 0, err
}
n := copy(p, r.unread)
r.unread = r.unread[n:]
if last {
// Ensure there is an EOF after the last chunk as expected. In other
// words, check for trailing data after a full-length final chunk.
// Hopefully, the underlying reader supports returning EOF even if it
// had previously returned an EOF to ReadFull.
if _, err := r.src.Read(make([]byte, 1)); err == nil {
r.err = errors.New("trailing data after end of encrypted file")
} else if err != io.EOF {
r.err = fmt.Errorf("non-EOF error reading after end of encrypted file: %w", err)
} else {
r.err = io.EOF
}
}
return n, nil
}
// readChunk reads the next chunk of ciphertext from r.src and makes it available
// in r.unread. last is true if the chunk was marked as the end of the message.
// readChunk must not be called again after returning a last chunk or an error.
func (r *Reader) readChunk() (last bool, err error) {
if len(r.unread) != 0 {
panic("stream: internal error: readChunk called with dirty buffer")
}
in := r.buf[:]
n, err := io.ReadFull(r.src, in)
switch {
case err == io.EOF:
// A message can't end without a marked chunk. This message is truncated.
return false, io.ErrUnexpectedEOF
case err == io.ErrUnexpectedEOF:
// The last chunk can be short, but not empty unless it's the first and
// only chunk.
if !nonceIsZero(&r.nonce) && n == r.a.Overhead() {
return false, errors.New("last chunk is empty, try age v1.0.0, and please consider reporting this")
}
in = in[:n]
last = true
setLastChunkFlag(&r.nonce)
case err != nil:
return false, err
}
outBuf := make([]byte, 0, ChunkSize)
out, err := r.a.Open(outBuf, r.nonce[:], in, nil)
if err != nil && !last {
// Check if this was a full-length final chunk.
last = true
setLastChunkFlag(&r.nonce)
out, err = r.a.Open(outBuf, r.nonce[:], in, nil)
}
if err != nil {
return false, errors.New("failed to decrypt and authenticate payload chunk")
}
incNonce(&r.nonce)
r.unread = r.buf[:copy(r.buf[:], out)]
return last, nil
}
func incNonce(nonce *[chacha20poly1305.NonceSize]byte) {
for i := len(nonce) - 2; i >= 0; i-- {
nonce[i]++
if nonce[i] != 0 {
break
} else if i == 0 {
// The counter is 88 bits, this is unreachable.
panic("stream: chunk counter wrapped around")
}
}
}
func setLastChunkFlag(nonce *[chacha20poly1305.NonceSize]byte) {
nonce[len(nonce)-1] = lastChunkFlag
}
func nonceIsZero(nonce *[chacha20poly1305.NonceSize]byte) bool {
return *nonce == [chacha20poly1305.NonceSize]byte{}
}
type Writer struct {
a cipher.AEAD
dst io.Writer
unwritten []byte // backed by buf
buf [encChunkSize]byte
nonce [chacha20poly1305.NonceSize]byte
err error
}
func NewWriter(key []byte, dst io.Writer) (*Writer, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
w := &Writer{
a: aead,
dst: dst,
}
w.unwritten = w.buf[:0]
return w, nil
}
func (w *Writer) Write(p []byte) (n int, err error) {
// TODO: consider refactoring with a bytes.Buffer.
if w.err != nil {
return 0, w.err
}
if len(p) == 0 {
return 0, nil
}
total := len(p)
for len(p) > 0 {
freeBuf := w.buf[len(w.unwritten):ChunkSize]
n := copy(freeBuf, p)
p = p[n:]
w.unwritten = w.unwritten[:len(w.unwritten)+n]
if len(w.unwritten) == ChunkSize && len(p) > 0 {
if err := w.flushChunk(notLastChunk); err != nil {
w.err = err
return 0, err
}
}
}
return total, nil
}
// Close flushes the last chunk. It does not close the underlying Writer.
func (w *Writer) Close() error {
if w.err != nil {
return w.err
}
w.err = w.flushChunk(lastChunk)
if w.err != nil {
return w.err
}
w.err = errors.New("stream.Writer is already closed")
return nil
}
const (
lastChunk = true
notLastChunk = false
)
func (w *Writer) flushChunk(last bool) error {
if !last && len(w.unwritten) != ChunkSize {
panic("stream: internal error: flush called with partial chunk")
}
if last {
setLastChunkFlag(&w.nonce)
}
buf := w.a.Seal(w.buf[:0], w.nonce[:], w.unwritten, nil)
_, err := w.dst.Write(buf)
w.unwritten = w.buf[:0]
incNonce(&w.nonce)
return err
}
================================================
FILE: vendor/filippo.io/age/parse.go
================================================
// Copyright 2021 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package age
import (
"bufio"
"fmt"
"io"
"strings"
)
// ParseIdentities parses a file with one or more private key encodings, one per
// line. Empty lines and lines starting with "#" are ignored.
//
// This is the same syntax as the private key files accepted by the CLI, except
// the CLI also accepts SSH private keys, which are not recommended for the
// average application.
//
// Currently, all returned values are of type *X25519Identity, but different
// types might be returned in the future.
func ParseIdentities(f io.Reader) ([]Identity, error) {
const privateKeySizeLimit = 1 << 24 // 16 MiB
var ids []Identity
scanner := bufio.NewScanner(io.LimitReader(f, privateKeySizeLimit))
var n int
for scanner.Scan() {
n++
line := scanner.Text()
if strings.HasPrefix(line, "#") || line == "" {
continue
}
i, err := ParseX25519Identity(line)
if err != nil {
return nil, fmt.Errorf("error at line %d: %v", n, err)
}
ids = append(ids, i)
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to read secret keys file: %v", err)
}
if len(ids) == 0 {
return nil, fmt.Errorf("no secret keys found")
}
return ids, nil
}
// ParseRecipients parses a file with one or more public key encodings, one per
// line. Empty lines and lines starting with "#" are ignored.
//
// This is the same syntax as the recipients files accepted by the CLI, except
// the CLI also accepts SSH recipients, which are not recommended for the
// average application.
//
// Currently, all returned values are of type *X25519Recipient, but different
// types might be returned in the future.
func ParseRecipients(f io.Reader) ([]Recipient, error) {
const recipientFileSizeLimit = 1 << 24 // 16 MiB
var recs []Recipient
scanner := bufio.NewScanner(io.LimitReader(f, recipientFileSizeLimit))
var n int
for scanner.Scan() {
n++
line := scanner.Text()
if strings.HasPrefix(line, "#") || line == "" {
continue
}
r, err := ParseX25519Recipient(line)
if err != nil {
// Hide the error since it might unintentionally leak the contents
// of confidential files.
return nil, fmt.Errorf("malformed recipient at line %d", n)
}
recs = append(recs, r)
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to read recipients file: %v", err)
}
if len(recs) == 0 {
return nil, fmt.Errorf("no recipients found")
}
return recs, nil
}
================================================
FILE: vendor/filippo.io/age/primitives.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package age
import (
"crypto/hmac"
"crypto/sha256"
"errors"
"io"
"filippo.io/age/internal/format"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/hkdf"
)
// aeadEncrypt encrypts a message with a one-time key.
func aeadEncrypt(key, plaintext []byte) ([]byte, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
// The nonce is fixed because this function is only used in places where the
// spec guarantees each key is only used once (by deriving it from values
// that include fresh randomness), allowing us to save the overhead.
// For the code that encrypts the actual payload, look at the
// filippo.io/age/internal/stream package.
nonce := make([]byte, chacha20poly1305.NonceSize)
return aead.Seal(nil, nonce, plaintext, nil), nil
}
var errIncorrectCiphertextSize = errors.New("encrypted value has unexpected length")
// aeadDecrypt decrypts a message of an expected fixed size.
//
// The message size is limited to mitigate multi-key attacks, where a ciphertext
// can be crafted that decrypts successfully under multiple keys. Short
// ciphertexts can only target two keys, which has limited impact.
func aeadDecrypt(key []byte, size int, ciphertext []byte) ([]byte, error) {
aead, err := chacha20poly1305.New(key)
if err != nil {
return nil, err
}
if len(ciphertext) != size+aead.Overhead() {
return nil, errIncorrectCiphertextSize
}
nonce := make([]byte, chacha20poly1305.NonceSize)
return aead.Open(nil, nonce, ciphertext, nil)
}
func headerMAC(fileKey []byte, hdr *format.Header) ([]byte, error) {
h := hkdf.New(sha256.New, fileKey, nil, []byte("header"))
hmacKey := make([]byte, 32)
if _, err := io.ReadFull(h, hmacKey); err != nil {
return nil, err
}
hh := hmac.New(sha256.New, hmacKey)
if err := hdr.MarshalWithoutMAC(hh); err != nil {
return nil, err
}
return hh.Sum(nil), nil
}
func streamKey(fileKey, nonce []byte) []byte {
h := hkdf.New(sha256.New, fileKey, nonce, []byte("payload"))
streamKey := make([]byte, chacha20poly1305.KeySize)
if _, err := io.ReadFull(h, streamKey); err != nil {
panic("age: internal error: failed to read from HKDF: " + err.Error())
}
return streamKey
}
================================================
FILE: vendor/filippo.io/age/scrypt.go
================================================
// Copyright 2019 The age Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package age
import (
"crypto/rand"
"encoding/hex"
"errors"
"fmt"
"regexp"
"strconv"
"filippo.io/age/internal/format"
"golang.org/x/crypto/chacha20poly1305"
"golang.org/x/crypto/scrypt"
)
const scryptLabel = "age-encryption.org/v1/scrypt"
// ScryptRecipient is a password-based recipient. Anyone with the password can
// decrypt the message.
//
// If a ScryptRecipient is used, it must be the only recipient for the file: it
// can't be mixed with other recipient types and can't be used multiple times
// for the same file.
//
// Its use is not recommended for automated systems, which should prefer
// X25519Recipient.
type ScryptRecipient struct {
password []byte
workFactor int
}
var _ Recipient = &ScryptRecipient{}
// NewScryptRecipient returns a new ScryptRecipient with the provided password.
func NewScryptRecipient(password string) (*ScryptRecipient, error) {
if len(password) == 0 {
return nil, errors.New("passphrase can't be empty")
}
r := &ScryptRecipient{
password: []byte(password),
// TODO: automatically scale this to 1s (with a min) in the CLI.
workFactor: 18, // 1s on a modern machine
}
return r, nil
}
// SetWorkFactor sets the scrypt work factor to 2^logN.
// It must be called before Wrap.
//
// If SetWorkFactor is not called, a reasonable default is used.
func (r *ScryptRecipient) SetWorkFactor(logN int) {
if logN > 30 || logN < 1 {
panic("age: SetWorkFactor called with illegal value")
}
r.workFactor = logN
}
const scryptSaltSize = 16
func (r *ScryptRecipient) Wrap(fileKey []byte) ([]*Stanza, error) {
salt := make([]byte, scryptSaltSize)
if _, err := rand.Read(salt[:]); err != nil {
return nil, err
}
logN := r.workFactor
l := &Stanza{
Type: "scrypt",
Args: []string{format.EncodeToString(salt), strconv.Itoa(logN)},
}
salt = append([]byte(scryptLabel), salt...)
k, err := scrypt.Key(r.password, salt, 1< 30 || logN < 1 {
panic("age: SetMaxWorkFactor called with illegal value")
}
i.maxWorkFactor = logN
}
func (i *ScryptIdentity) Unwrap(stanzas []*Stanza) ([]byte, error) {
for _, s := range stanzas {
if s.Type == "scrypt" && len(stanzas) != 1 {
return nil, errors.New("an scrypt recipient must be the only one")
}
}
return multiUnwrap(i.unwrap, stanzas)
}
var digitsRe = regexp.MustCompile(`^[1-9][0-9]*$`)
func (i *ScryptIdentity) unwrap(block *Stanza) ([]byte, error) {
if block.Type != "scrypt" {
return nil, ErrIncorrectIdentity
}
if len(block.Args) != 2 {
return nil, errors.New("invalid scrypt recipient block")
}
salt, err := format.DecodeString(block.Args[0])
if err != nil {
return nil, fmt.Errorf("failed to parse scrypt salt: %v", err)
}
if len(salt) != scryptSaltSize {
return nil, errors.New("invalid scrypt recipient block")
}
if w := block.Args[1]; !digitsRe.MatchString(w) {
return nil, fmt.Errorf("scrypt work factor encoding invalid: %q", w)
}
logN, err := strconv.Atoi(block.Args[1])
if err != nil {
return nil, fmt.Errorf("failed to parse scrypt work factor: %v", err)
}
if logN > i.maxWorkFactor {
return nil, fmt.Errorf("scrypt work factor too large: %v", logN)
}
if logN <= 0 { // unreachable
return nil, fmt.Errorf("invalid scrypt work factor: %v", logN)
}
salt = append([]byte(scryptLabel), salt...)
k, err := scrypt.Key(i.password, salt, 1< len(chars)
*/
func CryptoRandom(count int, start int, end int, letters bool, numbers bool, chars ...rune) (string, error) {
if count == 0 {
return "", nil
} else if count < 0 {
err := fmt.Errorf("randomstringutils illegal argument: Requested random string length %v is less than 0.", count) // equiv to err := errors.New("...")
return "", err
}
if chars != nil && len(chars) == 0 {
err := fmt.Errorf("randomstringutils illegal argument: The chars array must not be empty")
return "", err
}
if start == 0 && end == 0 {
if chars != nil {
end = len(chars)
} else {
if !letters && !numbers {
end = math.MaxInt32
} else {
end = 'z' + 1
start = ' '
}
}
} else {
if end <= start {
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) must be greater than start (%v)", end, start)
return "", err
}
if chars != nil && end > len(chars) {
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) cannot be greater than len(chars) (%v)", end, len(chars))
return "", err
}
}
buffer := make([]rune, count)
gap := end - start
// high-surrogates range, (\uD800-\uDBFF) = 55296 - 56319
// low-surrogates range, (\uDC00-\uDFFF) = 56320 - 57343
for count != 0 {
count--
var ch rune
if chars == nil {
ch = rune(getCryptoRandomInt(gap) + int64(start))
} else {
ch = chars[getCryptoRandomInt(gap)+int64(start)]
}
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
if ch >= 56320 && ch <= 57343 { // low surrogate range
if count == 0 {
count++
} else {
// Insert low surrogate
buffer[count] = ch
count--
// Insert high surrogate
buffer[count] = rune(55296 + getCryptoRandomInt(128))
}
} else if ch >= 55296 && ch <= 56191 { // High surrogates range (Partial)
if count == 0 {
count++
} else {
// Insert low surrogate
buffer[count] = rune(56320 + getCryptoRandomInt(128))
count--
// Insert high surrogate
buffer[count] = ch
}
} else if ch >= 56192 && ch <= 56319 {
// private high surrogate, skip it
count++
} else {
// not one of the surrogates*
buffer[count] = ch
}
} else {
count++
}
}
return string(buffer), nil
}
func getCryptoRandomInt(count int) int64 {
nBig, err := rand.Int(rand.Reader, big.NewInt(int64(count)))
if err != nil {
panic(err)
}
return nBig.Int64()
}
================================================
FILE: vendor/github.com/Masterminds/goutils/randomstringutils.go
================================================
/*
Copyright 2014 Alexander Okoli
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package goutils
import (
"fmt"
"math"
"math/rand"
"time"
"unicode"
)
// RANDOM provides the time-based seed used to generate random numbers
var RANDOM = rand.New(rand.NewSource(time.Now().UnixNano()))
/*
RandomNonAlphaNumeric creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of all characters (ASCII/Unicode values between 0 to 2,147,483,647 (math.MaxInt32)).
Parameter:
count - the length of random string to create
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomNonAlphaNumeric(count int) (string, error) {
return RandomAlphaNumericCustom(count, false, false)
}
/*
RandomAscii creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of characters whose ASCII value is between 32 and 126 (inclusive).
Parameter:
count - the length of random string to create
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomAscii(count int) (string, error) {
return Random(count, 32, 127, false, false)
}
/*
RandomNumeric creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of numeric characters.
Parameter:
count - the length of random string to create
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomNumeric(count int) (string, error) {
return Random(count, 0, 0, false, true)
}
/*
RandomAlphabetic creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of alphabetic characters.
Parameters:
count - the length of random string to create
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomAlphabetic(count int) (string, error) {
return Random(count, 0, 0, true, false)
}
/*
RandomAlphaNumeric creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of alpha-numeric characters.
Parameter:
count - the length of random string to create
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomAlphaNumeric(count int) (string, error) {
return Random(count, 0, 0, true, true)
}
/*
RandomAlphaNumericCustom creates a random string whose length is the number of characters specified.
Characters will be chosen from the set of alpha-numeric characters as indicated by the arguments.
Parameters:
count - the length of random string to create
letters - if true, generated string may include alphabetic characters
numbers - if true, generated string may include numeric characters
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func RandomAlphaNumericCustom(count int, letters bool, numbers bool) (string, error) {
return Random(count, 0, 0, letters, numbers)
}
/*
Random creates a random string based on a variety of options, using default source of randomness.
This method has exactly the same semantics as RandomSeed(int, int, int, bool, bool, []char, *rand.Rand), but
instead of using an externally supplied source of randomness, it uses the internal *rand.Rand instance.
Parameters:
count - the length of random string to create
start - the position in set of chars (ASCII/Unicode int) to start at
end - the position in set of chars (ASCII/Unicode int) to end before
letters - if true, generated string may include alphabetic characters
numbers - if true, generated string may include numeric characters
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
Returns:
string - the random string
error - an error stemming from an invalid parameter within underlying function, RandomSeed(...)
*/
func Random(count int, start int, end int, letters bool, numbers bool, chars ...rune) (string, error) {
return RandomSeed(count, start, end, letters, numbers, chars, RANDOM)
}
/*
RandomSeed creates a random string based on a variety of options, using supplied source of randomness.
If the parameters start and end are both 0, start and end are set to ' ' and 'z', the ASCII printable characters, will be used,
unless letters and numbers are both false, in which case, start and end are set to 0 and math.MaxInt32, respectively.
If chars is not nil, characters stored in chars that are between start and end are chosen.
This method accepts a user-supplied *rand.Rand instance to use as a source of randomness. By seeding a single *rand.Rand instance
with a fixed seed and using it for each call, the same random sequence of strings can be generated repeatedly and predictably.
Parameters:
count - the length of random string to create
start - the position in set of chars (ASCII/Unicode decimals) to start at
end - the position in set of chars (ASCII/Unicode decimals) to end before
letters - if true, generated string may include alphabetic characters
numbers - if true, generated string may include numeric characters
chars - the set of chars to choose randoms from. If nil, then it will use the set of all chars.
random - a source of randomness.
Returns:
string - the random string
error - an error stemming from invalid parameters: if count < 0; or the provided chars array is empty; or end <= start; or end > len(chars)
*/
func RandomSeed(count int, start int, end int, letters bool, numbers bool, chars []rune, random *rand.Rand) (string, error) {
if count == 0 {
return "", nil
} else if count < 0 {
err := fmt.Errorf("randomstringutils illegal argument: Requested random string length %v is less than 0.", count) // equiv to err := errors.New("...")
return "", err
}
if chars != nil && len(chars) == 0 {
err := fmt.Errorf("randomstringutils illegal argument: The chars array must not be empty")
return "", err
}
if start == 0 && end == 0 {
if chars != nil {
end = len(chars)
} else {
if !letters && !numbers {
end = math.MaxInt32
} else {
end = 'z' + 1
start = ' '
}
}
} else {
if end <= start {
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) must be greater than start (%v)", end, start)
return "", err
}
if chars != nil && end > len(chars) {
err := fmt.Errorf("randomstringutils illegal argument: Parameter end (%v) cannot be greater than len(chars) (%v)", end, len(chars))
return "", err
}
}
buffer := make([]rune, count)
gap := end - start
// high-surrogates range, (\uD800-\uDBFF) = 55296 - 56319
// low-surrogates range, (\uDC00-\uDFFF) = 56320 - 57343
for count != 0 {
count--
var ch rune
if chars == nil {
ch = rune(random.Intn(gap) + start)
} else {
ch = chars[random.Intn(gap)+start]
}
if letters && unicode.IsLetter(ch) || numbers && unicode.IsDigit(ch) || !letters && !numbers {
if ch >= 56320 && ch <= 57343 { // low surrogate range
if count == 0 {
count++
} else {
// Insert low surrogate
buffer[count] = ch
count--
// Insert high surrogate
buffer[count] = rune(55296 + random.Intn(128))
}
} else if ch >= 55296 && ch <= 56191 { // High surrogates range (Partial)
if count == 0 {
count++
} else {
// Insert low surrogate
buffer[count] = rune(56320 + random.Intn(128))
count--
// Insert high surrogate
buffer[count] = ch
}
} else if ch >= 56192 && ch <= 56319 {
// private high surrogate, skip it
count++
} else {
// not one of the surrogates*
buffer[count] = ch
}
} else {
count++
}
}
return string(buffer), nil
}
================================================
FILE: vendor/github.com/Masterminds/goutils/stringutils.go
================================================
/*
Copyright 2014 Alexander Okoli
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package goutils
import (
"bytes"
"fmt"
"strings"
"unicode"
)
// Typically returned by functions where a searched item cannot be found
const INDEX_NOT_FOUND = -1
/*
Abbreviate abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "Now is the time for..."
Specifically, the algorithm is as follows:
- If str is less than maxWidth characters long, return it.
- Else abbreviate it to (str[0:maxWidth - 3] + "...").
- If maxWidth is less than 4, return an illegal argument error.
- In no case will it return a string of length greater than maxWidth.
Parameters:
str - the string to check
maxWidth - maximum length of result string, must be at least 4
Returns:
string - abbreviated string
error - if the width is too small
*/
func Abbreviate(str string, maxWidth int) (string, error) {
return AbbreviateFull(str, 0, maxWidth)
}
/*
AbbreviateFull abbreviates a string using ellipses. This will turn the string "Now is the time for all good men" into "...is the time for..."
This function works like Abbreviate(string, int), but allows you to specify a "left edge" offset. Note that this left edge is not
necessarily going to be the leftmost character in the result, or the first character following the ellipses, but it will appear
somewhere in the result.
In no case will it return a string of length greater than maxWidth.
Parameters:
str - the string to check
offset - left edge of source string
maxWidth - maximum length of result string, must be at least 4
Returns:
string - abbreviated string
error - if the width is too small
*/
func AbbreviateFull(str string, offset int, maxWidth int) (string, error) {
if str == "" {
return "", nil
}
if maxWidth < 4 {
err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width is 4")
return "", err
}
if len(str) <= maxWidth {
return str, nil
}
if offset > len(str) {
offset = len(str)
}
if len(str)-offset < (maxWidth - 3) { // 15 - 5 < 10 - 3 = 10 < 7
offset = len(str) - (maxWidth - 3)
}
abrevMarker := "..."
if offset <= 4 {
return str[0:maxWidth-3] + abrevMarker, nil // str.substring(0, maxWidth - 3) + abrevMarker;
}
if maxWidth < 7 {
err := fmt.Errorf("stringutils illegal argument: Minimum abbreviation width with offset is 7")
return "", err
}
if (offset + maxWidth - 3) < len(str) { // 5 + (10-3) < 15 = 12 < 15
abrevStr, _ := Abbreviate(str[offset:len(str)], (maxWidth - 3))
return abrevMarker + abrevStr, nil // abrevMarker + abbreviate(str.substring(offset), maxWidth - 3);
}
return abrevMarker + str[(len(str)-(maxWidth-3)):len(str)], nil // abrevMarker + str.substring(str.length() - (maxWidth - 3));
}
/*
DeleteWhiteSpace deletes all whitespaces from a string as defined by unicode.IsSpace(rune).
It returns the string without whitespaces.
Parameter:
str - the string to delete whitespace from, may be nil
Returns:
the string without whitespaces
*/
func DeleteWhiteSpace(str string) string {
if str == "" {
return str
}
sz := len(str)
var chs bytes.Buffer
count := 0
for i := 0; i < sz; i++ {
ch := rune(str[i])
if !unicode.IsSpace(ch) {
chs.WriteRune(ch)
count++
}
}
if count == sz {
return str
}
return chs.String()
}
/*
IndexOfDifference compares two strings, and returns the index at which the strings begin to differ.
Parameters:
str1 - the first string
str2 - the second string
Returns:
the index where str1 and str2 begin to differ; -1 if they are equal
*/
func IndexOfDifference(str1 string, str2 string) int {
if str1 == str2 {
return INDEX_NOT_FOUND
}
if IsEmpty(str1) || IsEmpty(str2) {
return 0
}
var i int
for i = 0; i < len(str1) && i < len(str2); i++ {
if rune(str1[i]) != rune(str2[i]) {
break
}
}
if i < len(str2) || i < len(str1) {
return i
}
return INDEX_NOT_FOUND
}
/*
IsBlank checks if a string is whitespace or empty (""). Observe the following behavior:
goutils.IsBlank("") = true
goutils.IsBlank(" ") = true
goutils.IsBlank("bob") = false
goutils.IsBlank(" bob ") = false
Parameter:
str - the string to check
Returns:
true - if the string is whitespace or empty ("")
*/
func IsBlank(str string) bool {
strLen := len(str)
if str == "" || strLen == 0 {
return true
}
for i := 0; i < strLen; i++ {
if unicode.IsSpace(rune(str[i])) == false {
return false
}
}
return true
}
/*
IndexOf returns the index of the first instance of sub in str, with the search beginning from the
index start point specified. -1 is returned if sub is not present in str.
An empty string ("") will return -1 (INDEX_NOT_FOUND). A negative start position is treated as zero.
A start position greater than the string length returns -1.
Parameters:
str - the string to check
sub - the substring to find
start - the start position; negative treated as zero
Returns:
the first index where the sub string was found (always >= start)
*/
func IndexOf(str string, sub string, start int) int {
if start < 0 {
start = 0
}
if len(str) < start {
return INDEX_NOT_FOUND
}
if IsEmpty(str) || IsEmpty(sub) {
return INDEX_NOT_FOUND
}
partialIndex := strings.Index(str[start:len(str)], sub)
if partialIndex == -1 {
return INDEX_NOT_FOUND
}
return partialIndex + start
}
// IsEmpty checks if a string is empty (""). Returns true if empty, and false otherwise.
func IsEmpty(str string) bool {
return len(str) == 0
}
// Returns either the passed in string, or if the string is empty, the value of defaultStr.
func DefaultString(str string, defaultStr string) string {
if IsEmpty(str) {
return defaultStr
}
return str
}
// Returns either the passed in string, or if the string is whitespace, empty (""), the value of defaultStr.
func DefaultIfBlank(str string, defaultStr string) string {
if IsBlank(str) {
return defaultStr
}
return str
}
================================================
FILE: vendor/github.com/Masterminds/goutils/wordutils.go
================================================
/*
Copyright 2014 Alexander Okoli
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
Package goutils provides utility functions to manipulate strings in various ways.
The code snippets below show examples of how to use goutils. Some functions return
errors while others do not, so usage would vary as a result.
Example:
package main
import (
"fmt"
"github.com/aokoli/goutils"
)
func main() {
// EXAMPLE 1: A goutils function which returns no errors
fmt.Println (goutils.Initials("John Doe Foo")) // Prints out "JDF"
// EXAMPLE 2: A goutils function which returns an error
rand1, err1 := goutils.Random (-1, 0, 0, true, true)
if err1 != nil {
fmt.Println(err1) // Prints out error message because -1 was entered as the first parameter in goutils.Random(...)
} else {
fmt.Println(rand1)
}
}
*/
package goutils
import (
"bytes"
"strings"
"unicode"
)
// VERSION indicates the current version of goutils
const VERSION = "1.0.0"
/*
Wrap wraps a single line of text, identifying words by ' '.
New lines will be separated by '\n'. Very long words, such as URLs will not be wrapped.
Leading spaces on a new line are stripped. Trailing spaces are not stripped.
Parameters:
str - the string to be word wrapped
wrapLength - the column (a column can fit only one character) to wrap the words at, less than 1 is treated as 1
Returns:
a line with newlines inserted
*/
func Wrap(str string, wrapLength int) string {
return WrapCustom(str, wrapLength, "", false)
}
/*
WrapCustom wraps a single line of text, identifying words by ' '.
Leading spaces on a new line are stripped. Trailing spaces are not stripped.
Parameters:
str - the string to be word wrapped
wrapLength - the column number (a column can fit only one character) to wrap the words at, less than 1 is treated as 1
newLineStr - the string to insert for a new line, "" uses '\n'
wrapLongWords - true if long words (such as URLs) should be wrapped
Returns:
a line with newlines inserted
*/
func WrapCustom(str string, wrapLength int, newLineStr string, wrapLongWords bool) string {
if str == "" {
return ""
}
if newLineStr == "" {
newLineStr = "\n" // TODO Assumes "\n" is seperator. Explore SystemUtils.LINE_SEPARATOR from Apache Commons
}
if wrapLength < 1 {
wrapLength = 1
}
inputLineLength := len(str)
offset := 0
var wrappedLine bytes.Buffer
for inputLineLength-offset > wrapLength {
if rune(str[offset]) == ' ' {
offset++
continue
}
end := wrapLength + offset + 1
spaceToWrapAt := strings.LastIndex(str[offset:end], " ") + offset
if spaceToWrapAt >= offset {
// normal word (not longer than wrapLength)
wrappedLine.WriteString(str[offset:spaceToWrapAt])
wrappedLine.WriteString(newLineStr)
offset = spaceToWrapAt + 1
} else {
// long word or URL
if wrapLongWords {
end := wrapLength + offset
// long words are wrapped one line at a time
wrappedLine.WriteString(str[offset:end])
wrappedLine.WriteString(newLineStr)
offset += wrapLength
} else {
// long words aren't wrapped, just extended beyond limit
end := wrapLength + offset
index := strings.IndexRune(str[end:len(str)], ' ')
if index == -1 {
wrappedLine.WriteString(str[offset:len(str)])
offset = inputLineLength
} else {
spaceToWrapAt = index + end
wrappedLine.WriteString(str[offset:spaceToWrapAt])
wrappedLine.WriteString(newLineStr)
offset = spaceToWrapAt + 1
}
}
}
}
wrappedLine.WriteString(str[offset:len(str)])
return wrappedLine.String()
}
/*
Capitalize capitalizes all the delimiter separated words in a string. Only the first letter of each word is changed.
To convert the rest of each word to lowercase at the same time, use CapitalizeFully(str string, delimiters ...rune).
The delimiters represent a set of characters understood to separate words. The first string character
and the first non-delimiter character after a delimiter will be capitalized. A "" input string returns "".
Capitalization uses the Unicode title case, normally equivalent to upper case.
Parameters:
str - the string to capitalize
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
Returns:
capitalized string
*/
func Capitalize(str string, delimiters ...rune) string {
var delimLen int
if delimiters == nil {
delimLen = -1
} else {
delimLen = len(delimiters)
}
if str == "" || delimLen == 0 {
return str
}
buffer := []rune(str)
capitalizeNext := true
for i := 0; i < len(buffer); i++ {
ch := buffer[i]
if isDelimiter(ch, delimiters...) {
capitalizeNext = true
} else if capitalizeNext {
buffer[i] = unicode.ToTitle(ch)
capitalizeNext = false
}
}
return string(buffer)
}
/*
CapitalizeFully converts all the delimiter separated words in a string into capitalized words, that is each word is made up of a
titlecase character and then a series of lowercase characters. The delimiters represent a set of characters understood
to separate words. The first string character and the first non-delimiter character after a delimiter will be capitalized.
Capitalization uses the Unicode title case, normally equivalent to upper case.
Parameters:
str - the string to capitalize fully
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
Returns:
capitalized string
*/
func CapitalizeFully(str string, delimiters ...rune) string {
var delimLen int
if delimiters == nil {
delimLen = -1
} else {
delimLen = len(delimiters)
}
if str == "" || delimLen == 0 {
return str
}
str = strings.ToLower(str)
return Capitalize(str, delimiters...)
}
/*
Uncapitalize uncapitalizes all the whitespace separated words in a string. Only the first letter of each word is changed.
The delimiters represent a set of characters understood to separate words. The first string character and the first non-delimiter
character after a delimiter will be uncapitalized. Whitespace is defined by unicode.IsSpace(char).
Parameters:
str - the string to uncapitalize fully
delimiters - set of characters to determine capitalization, exclusion of this parameter means whitespace would be delimeter
Returns:
uncapitalized string
*/
func Uncapitalize(str string, delimiters ...rune) string {
var delimLen int
if delimiters == nil {
delimLen = -1
} else {
delimLen = len(delimiters)
}
if str == "" || delimLen == 0 {
return str
}
buffer := []rune(str)
uncapitalizeNext := true // TODO Always makes capitalize/un apply to first char.
for i := 0; i < len(buffer); i++ {
ch := buffer[i]
if isDelimiter(ch, delimiters...) {
uncapitalizeNext = true
} else if uncapitalizeNext {
buffer[i] = unicode.ToLower(ch)
uncapitalizeNext = false
}
}
return string(buffer)
}
/*
SwapCase swaps the case of a string using a word based algorithm.
Conversion algorithm:
Upper case character converts to Lower case
Title case character converts to Lower case
Lower case character after Whitespace or at start converts to Title case
Other Lower case character converts to Upper case
Whitespace is defined by unicode.IsSpace(char).
Parameters:
str - the string to swap case
Returns:
the changed string
*/
func SwapCase(str string) string {
if str == "" {
return str
}
buffer := []rune(str)
whitespace := true
for i := 0; i < len(buffer); i++ {
ch := buffer[i]
if unicode.IsUpper(ch) {
buffer[i] = unicode.ToLower(ch)
whitespace = false
} else if unicode.IsTitle(ch) {
buffer[i] = unicode.ToLower(ch)
whitespace = false
} else if unicode.IsLower(ch) {
if whitespace {
buffer[i] = unicode.ToTitle(ch)
whitespace = false
} else {
buffer[i] = unicode.ToUpper(ch)
}
} else {
whitespace = unicode.IsSpace(ch)
}
}
return string(buffer)
}
/*
Initials extracts the initial letters from each word in the string. The first letter of the string and all first
letters after the defined delimiters are returned as a new string. Their case is not changed. If the delimiters
parameter is excluded, then Whitespace is used. Whitespace is defined by unicode.IsSpacea(char). An empty delimiter array returns an empty string.
Parameters:
str - the string to get initials from
delimiters - set of characters to determine words, exclusion of this parameter means whitespace would be delimeter
Returns:
string of initial letters
*/
func Initials(str string, delimiters ...rune) string {
if str == "" {
return str
}
if delimiters != nil && len(delimiters) == 0 {
return ""
}
strLen := len(str)
var buf bytes.Buffer
lastWasGap := true
for i := 0; i < strLen; i++ {
ch := rune(str[i])
if isDelimiter(ch, delimiters...) {
lastWasGap = true
} else if lastWasGap {
buf.WriteRune(ch)
lastWasGap = false
}
}
return buf.String()
}
// private function (lower case func name)
func isDelimiter(ch rune, delimiters ...rune) bool {
if delimiters == nil {
return unicode.IsSpace(ch)
}
for _, delimiter := range delimiters {
if ch == delimiter {
return true
}
}
return false
}
================================================
FILE: vendor/github.com/Masterminds/semver/v3/.gitignore
================================================
_fuzz/
================================================
FILE: vendor/github.com/Masterminds/semver/v3/.golangci.yml
================================================
run:
deadline: 2m
linters:
disable-all: true
enable:
- misspell
- govet
- staticcheck
- errcheck
- unparam
- ineffassign
- nakedret
- gocyclo
- dupl
- goimports
- revive
- gosec
- gosimple
- typecheck
- unused
linters-settings:
gofmt:
simplify: true
dupl:
threshold: 600
================================================
FILE: vendor/github.com/Masterminds/semver/v3/CHANGELOG.md
================================================
# Changelog
## 3.3.0 (2024-08-27)
### Added
- #238: Add LessThanEqual and GreaterThanEqual functions (thanks @grosser)
- #213: nil version equality checking (thanks @KnutZuidema)
### Changed
- #241: Simplify StrictNewVersion parsing (thanks @grosser)
- Testing support up through Go 1.23
- Minimum version set to 1.21 as this is what's tested now
- Fuzz testing now supports caching
## 3.2.1 (2023-04-10)
### Changed
- #198: Improved testing around pre-release names
- #200: Improved code scanning with addition of CodeQL
- #201: Testing now includes Go 1.20. Go 1.17 has been dropped
- #202: Migrated Fuzz testing to Go built-in Fuzzing. CI runs daily
- #203: Docs updated for security details
### Fixed
- #199: Fixed issue with range transformations
## 3.2.0 (2022-11-28)
### Added
- #190: Added text marshaling and unmarshaling
- #167: Added JSON marshalling for constraints (thanks @SimonTheLeg)
- #173: Implement encoding.TextMarshaler and encoding.TextUnmarshaler on Version (thanks @MarkRosemaker)
- #179: Added New() version constructor (thanks @kazhuravlev)
### Changed
- #182/#183: Updated CI testing setup
### Fixed
- #186: Fixing issue where validation of constraint section gave false positives
- #176: Fix constraints check with *-0 (thanks @mtt0)
- #181: Fixed Caret operator (^) gives unexpected results when the minor version in constraint is 0 (thanks @arshchimni)
- #161: Fixed godoc (thanks @afirth)
## 3.1.1 (2020-11-23)
### Fixed
- #158: Fixed issue with generated regex operation order that could cause problem
## 3.1.0 (2020-04-15)
### Added
- #131: Add support for serializing/deserializing SQL (thanks @ryancurrah)
### Changed
- #148: More accurate validation messages on constraints
## 3.0.3 (2019-12-13)
### Fixed
- #141: Fixed issue with <= comparison
## 3.0.2 (2019-11-14)
### Fixed
- #134: Fixed broken constraint checking with ^0.0 (thanks @krmichelos)
## 3.0.1 (2019-09-13)
### Fixed
- #125: Fixes issue with module path for v3
## 3.0.0 (2019-09-12)
This is a major release of the semver package which includes API changes. The Go
API is compatible with ^1. The Go API was not changed because many people are using
`go get` without Go modules for their applications and API breaking changes cause
errors which we have or would need to support.
The changes in this release are the handling based on the data passed into the
functions. These are described in the added and changed sections below.
### Added
- StrictNewVersion function. This is similar to NewVersion but will return an
error if the version passed in is not a strict semantic version. For example,
1.2.3 would pass but v1.2.3 or 1.2 would fail because they are not strictly
speaking semantic versions. This function is faster, performs fewer operations,
and uses fewer allocations than NewVersion.
- Fuzzing has been performed on NewVersion, StrictNewVersion, and NewConstraint.
The Makefile contains the operations used. For more information on you can start
on Wikipedia at https://en.wikipedia.org/wiki/Fuzzing
- Now using Go modules
### Changed
- NewVersion has proper prerelease and metadata validation with error messages
to signal an issue with either of them
- ^ now operates using a similar set of rules to npm/js and Rust/Cargo. If the
version is >=1 the ^ ranges works the same as v1. For major versions of 0 the
rules have changed. The minor version is treated as the stable version unless
a patch is specified and then it is equivalent to =. One difference from npm/js
is that prereleases there are only to a specific version (e.g. 1.2.3).
Prereleases here look over multiple versions and follow semantic version
ordering rules. This pattern now follows along with the expected and requested
handling of this packaged by numerous users.
## 1.5.0 (2019-09-11)
### Added
- #103: Add basic fuzzing for `NewVersion()` (thanks @jesse-c)
### Changed
- #82: Clarify wildcard meaning in range constraints and update tests for it (thanks @greysteil)
- #83: Clarify caret operator range for pre-1.0.0 dependencies (thanks @greysteil)
- #72: Adding docs comment pointing to vert for a cli
- #71: Update the docs on pre-release comparator handling
- #89: Test with new go versions (thanks @thedevsaddam)
- #87: Added $ to ValidPrerelease for better validation (thanks @jeremycarroll)
### Fixed
- #78: Fix unchecked error in example code (thanks @ravron)
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
- #97: Fixed copyright file for proper display on GitHub
- #107: Fix handling prerelease when sorting alphanum and num
- #109: Fixed where Validate sometimes returns wrong message on error
## 1.4.2 (2018-04-10)
### Changed
- #72: Updated the docs to point to vert for a console appliaction
- #71: Update the docs on pre-release comparator handling
### Fixed
- #70: Fix the handling of pre-releases and the 0.0.0 release edge case
## 1.4.1 (2018-04-02)
### Fixed
- Fixed #64: Fix pre-release precedence issue (thanks @uudashr)
## 1.4.0 (2017-10-04)
### Changed
- #61: Update NewVersion to parse ints with a 64bit int size (thanks @zknill)
## 1.3.1 (2017-07-10)
### Fixed
- Fixed #57: number comparisons in prerelease sometimes inaccurate
## 1.3.0 (2017-05-02)
### Added
- #45: Added json (un)marshaling support (thanks @mh-cbon)
- Stability marker. See https://masterminds.github.io/stability/
### Fixed
- #51: Fix handling of single digit tilde constraint (thanks @dgodd)
### Changed
- #55: The godoc icon moved from png to svg
## 1.2.3 (2017-04-03)
### Fixed
- #46: Fixed 0.x.x and 0.0.x in constraints being treated as *
## Release 1.2.2 (2016-12-13)
### Fixed
- #34: Fixed issue where hyphen range was not working with pre-release parsing.
## Release 1.2.1 (2016-11-28)
### Fixed
- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha"
properly.
## Release 1.2.0 (2016-11-04)
### Added
- #20: Added MustParse function for versions (thanks @adamreese)
- #15: Added increment methods on versions (thanks @mh-cbon)
### Fixed
- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and
might not satisfy the intended compatibility. The change here ignores pre-releases
on constraint checks (e.g., ~ or ^) when a pre-release is not part of the
constraint. For example, `^1.2.3` will ignore pre-releases while
`^1.2.3-alpha` will include them.
## Release 1.1.1 (2016-06-30)
### Changed
- Issue #9: Speed up version comparison performance (thanks @sdboyer)
- Issue #8: Added benchmarks (thanks @sdboyer)
- Updated Go Report Card URL to new location
- Updated Readme to add code snippet formatting (thanks @mh-cbon)
- Updating tagging to v[SemVer] structure for compatibility with other tools.
## Release 1.1.0 (2016-03-11)
- Issue #2: Implemented validation to provide reasons a versions failed a
constraint.
## Release 1.0.1 (2015-12-31)
- Fixed #1: * constraint failing on valid versions.
## Release 1.0.0 (2015-10-20)
- Initial release
================================================
FILE: vendor/github.com/Masterminds/semver/v3/LICENSE.txt
================================================
Copyright (C) 2014-2019, Matt Butcher and Matt Farina
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: vendor/github.com/Masterminds/semver/v3/Makefile
================================================
GOPATH=$(shell go env GOPATH)
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
.PHONY: lint
lint: $(GOLANGCI_LINT)
@echo "==> Linting codebase"
@$(GOLANGCI_LINT) run
.PHONY: test
test:
@echo "==> Running tests"
GO111MODULE=on go test -v
.PHONY: test-cover
test-cover:
@echo "==> Running Tests with coverage"
GO111MODULE=on go test -cover .
.PHONY: fuzz
fuzz:
@echo "==> Running Fuzz Tests"
go env GOCACHE
go test -fuzz=FuzzNewVersion -fuzztime=15s .
go test -fuzz=FuzzStrictNewVersion -fuzztime=15s .
go test -fuzz=FuzzNewConstraint -fuzztime=15s .
$(GOLANGCI_LINT):
# Install golangci-lint. The configuration for it is in the .golangci.yml
# file in the root of the repository
echo ${GOPATH}
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.56.2
================================================
FILE: vendor/github.com/Masterminds/semver/v3/README.md
================================================
# SemVer
The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to:
* Parse semantic versions
* Sort semantic versions
* Check if a semantic version fits within a set of constraints
* Optionally work with a `v` prefix
[](https://masterminds.github.io/stability/active.html)
[](https://github.com/Masterminds/semver/actions)
[](https://pkg.go.dev/github.com/Masterminds/semver/v3)
[](https://goreportcard.com/report/github.com/Masterminds/semver)
## Package Versions
Note, import `github.com/Masterminds/semver/v3` to use the latest version.
There are three major versions fo the `semver` package.
* 3.x.x is the stable and active version. This version is focused on constraint
compatibility for range handling in other tools from other languages. It has
a similar API to the v1 releases. The development of this version is on the master
branch. The documentation for this version is below.
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
* 1.x.x is the original release. It is no longer maintained. You should use the
v3 release instead. You can read the documentation for the 1.x.x release
[here](https://github.com/Masterminds/semver/blob/release-1/README.md).
## Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
specification. The `NewVersion` function attempts to coerce a version into a
semantic version and parse it. For example, if there is a leading v or a version
listed without all 3 parts (e.g. `v1.2`) it will attempt to coerce it into a valid
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
that can be sorted, compared, and used in constraints.
When parsing a version an error is returned if there is an issue parsing the
version. For example,
v, err := semver.NewVersion("1.2.3-beta.1+build345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. Getting the original string is useful if the semantic version was coerced
into a valid form.
## Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
```go
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
```
## Checking Version Constraints
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other uses `Constraints`. There are some important
differences to notes between these two methods of comparison.
1. When two versions are compared using functions such as `Compare`, `LessThan`,
and others it will follow the specification and always include pre-releases
within the comparison. It will provide an answer that is valid with the
comparison section of the spec at https://semver.org/#spec-item-11
2. When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
and Rust/Cargo. This includes considering pre-releases to be invalid if the
ranges does not include one. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
3. Constraint ranges can have some complex rules including the shorthand use of
~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
are not part of the specification. Different packages and tools have taken it
upon themselves to come up with range rules. This has resulted in differences.
For example, npm/js and Cargo/Rust follow similar patterns while PHP has a
different pattern for ^. The comparison features in this package follow the
npm/js and Cargo/Rust lead because applications using it have followed similar
patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
```go
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parsable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
// Check if the version meets the constraints. The variable a will be true.
a := c.Check(v)
```
### Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of space or comma separated AND comparisons. These are then separated by || (OR)
comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3.
The basic comparisons are:
* `=`: equal (aliased to no operator)
* `!=`: not equal
* `>`: greater than
* `<`: less than
* `>=`: greater than or equal to
* `<=`: less than or equal to
### Working With Prerelease Versions
Pre-releases, for those not familiar with them, are used for software releases
prior to stable or generally available releases. Examples of pre-releases include
development, alpha, beta, and release candidate releases. A pre-release may be
a version such as `1.2.3-beta.1` while the stable release would be `1.2.3`. In the
order of precedence, pre-releases come before their associated releases. In this
example `1.2.3-beta.1 < 1.2.3`.
According to the Semantic Version specification, pre-releases may not be
API compliant with their release counterpart. It says,
> A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
SemVer's comparisons using constraints without a pre-release comparator will skip
pre-release versions. For example, `>=1.2.3` will skip pre-releases when looking
at a list of releases while `>=1.2.3-0` will evaluate and find pre-releases.
The reason for the `0` as a pre-release version in the example comparison is
because pre-releases can only contain ASCII alphanumerics and hyphens (along with
`.` separators), per the spec. Sorting happens in ASCII sort order, again per the
spec. The lowest character is a `0` in ASCII sort order
(see an [ASCII Table](http://www.asciitable.com/))
Understanding ASCII sort ordering is important because A-Z comes before a-z. That
means `>=1.2.3-BETA` will return `1.2.3-alpha`. What you might expect from case
sensitivity doesn't apply here. This is due to ASCII sort ordering which is what
the spec specifies.
### Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
* `1.2 - 1.4.5` which is equivalent to `>= 1.2 <= 1.4.5`
* `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
Note that `1.2-1.4.5` without whitespace is parsed completely differently; it's
parsed as a single constraint `1.2.0` with _prerelease_ `1.4.5`.
### Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the patch level comparison (see tilde below). For example,
* `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `>= 1.2.x` is equivalent to `>= 1.2.0`
* `<= 2.x` is equivalent to `< 3`
* `*` is equivalent to `>= 0.0.0`
### Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
* `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0`
* `~1` is equivalent to `>= 1, < 2`
* `~2.3` is equivalent to `>= 2.3, < 2.4`
* `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0`
* `~1.x` is equivalent to `>= 1, < 2`
### Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
* `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
* `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
* `^2.3` is equivalent to `>= 2.3, < 3`
* `^2.x` is equivalent to `>= 2.0.0, < 3`
* `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
* `^0.2` is equivalent to `>=0.2.0 <0.3.0`
* `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
* `^0.0` is equivalent to `>=0.0.0 <0.1.0`
* `^0` is equivalent to `>=0.0.0 <1.0.0`
## Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
```go
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
```
## Contribute
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
or [create a pull request](https://github.com/Masterminds/semver/pulls).
## Security
Security is an important consideration for this project. The project currently
uses the following tools to help discover security issues:
* [CodeQL](https://github.com/Masterminds/semver)
* [gosec](https://github.com/securego/gosec)
* Daily Fuzz testing
If you believe you have found a security vulnerability you can privately disclose
it through the [GitHub security page](https://github.com/Masterminds/semver/security).
================================================
FILE: vendor/github.com/Masterminds/semver/v3/SECURITY.md
================================================
# Security Policy
## Supported Versions
The following versions of semver are currently supported:
| Version | Supported |
| ------- | ------------------ |
| 3.x | :white_check_mark: |
| 2.x | :x: |
| 1.x | :x: |
Fixes are only released for the latest minor version in the form of a patch release.
## Reporting a Vulnerability
You can privately disclose a vulnerability through GitHubs
[private vulnerability reporting](https://github.com/Masterminds/semver/security/advisories)
mechanism.
================================================
FILE: vendor/github.com/Masterminds/semver/v3/collection.go
================================================
package semver
// Collection is a collection of Version instances and implements the sort
// interface. See the sort package for more details.
// https://golang.org/pkg/sort/
type Collection []*Version
// Len returns the length of a collection. The number of Version instances
// on the slice.
func (c Collection) Len() int {
return len(c)
}
// Less is needed for the sort interface to compare two Version objects on the
// slice. If checks if one is less than the other.
func (c Collection) Less(i, j int) bool {
return c[i].LessThan(c[j])
}
// Swap is needed for the sort interface to replace the Version objects
// at two different positions in the slice.
func (c Collection) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
================================================
FILE: vendor/github.com/Masterminds/semver/v3/constraints.go
================================================
package semver
import (
"bytes"
"errors"
"fmt"
"regexp"
"strings"
)
// Constraints is one or more constraint that a semantic version can be
// checked against.
type Constraints struct {
constraints [][]*constraint
}
// NewConstraint returns a Constraints instance that a Version instance can
// be checked against. If there is a parse error it will be returned.
func NewConstraint(c string) (*Constraints, error) {
// Rewrite - ranges into a comparison operation.
c = rewriteRange(c)
ors := strings.Split(c, "||")
or := make([][]*constraint, len(ors))
for k, v := range ors {
// TODO: Find a way to validate and fetch all the constraints in a simpler form
// Validate the segment
if !validConstraintRegex.MatchString(v) {
return nil, fmt.Errorf("improper constraint: %s", v)
}
cs := findConstraintRegex.FindAllString(v, -1)
if cs == nil {
cs = append(cs, v)
}
result := make([]*constraint, len(cs))
for i, s := range cs {
pc, err := parseConstraint(s)
if err != nil {
return nil, err
}
result[i] = pc
}
or[k] = result
}
o := &Constraints{constraints: or}
return o, nil
}
// Check tests if a version satisfies the constraints.
func (cs Constraints) Check(v *Version) bool {
// TODO(mattfarina): For v4 of this library consolidate the Check and Validate
// functions as the underlying functions make that possible now.
// loop over the ORs and check the inner ANDs
for _, o := range cs.constraints {
joy := true
for _, c := range o {
if check, _ := c.check(v); !check {
joy = false
break
}
}
if joy {
return true
}
}
return false
}
// Validate checks if a version satisfies a constraint. If not a slice of
// reasons for the failure are returned in addition to a bool.
func (cs Constraints) Validate(v *Version) (bool, []error) {
// loop over the ORs and check the inner ANDs
var e []error
// Capture the prerelease message only once. When it happens the first time
// this var is marked
var prerelesase bool
for _, o := range cs.constraints {
joy := true
for _, c := range o {
// Before running the check handle the case there the version is
// a prerelease and the check is not searching for prereleases.
if c.con.pre == "" && v.pre != "" {
if !prerelesase {
em := fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
e = append(e, em)
prerelesase = true
}
joy = false
} else {
if _, err := c.check(v); err != nil {
e = append(e, err)
joy = false
}
}
}
if joy {
return true, []error{}
}
}
return false, e
}
func (cs Constraints) String() string {
buf := make([]string, len(cs.constraints))
var tmp bytes.Buffer
for k, v := range cs.constraints {
tmp.Reset()
vlen := len(v)
for kk, c := range v {
tmp.WriteString(c.string())
// Space separate the AND conditions
if vlen > 1 && kk < vlen-1 {
tmp.WriteString(" ")
}
}
buf[k] = tmp.String()
}
return strings.Join(buf, " || ")
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (cs *Constraints) UnmarshalText(text []byte) error {
temp, err := NewConstraint(string(text))
if err != nil {
return err
}
*cs = *temp
return nil
}
// MarshalText implements the encoding.TextMarshaler interface.
func (cs Constraints) MarshalText() ([]byte, error) {
return []byte(cs.String()), nil
}
var constraintOps map[string]cfunc
var constraintRegex *regexp.Regexp
var constraintRangeRegex *regexp.Regexp
// Used to find individual constraints within a multi-constraint string
var findConstraintRegex *regexp.Regexp
// Used to validate an segment of ANDs is valid
var validConstraintRegex *regexp.Regexp
const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
func init() {
constraintOps = map[string]cfunc{
"": constraintTildeOrEqual,
"=": constraintTildeOrEqual,
"!=": constraintNotEqual,
">": constraintGreaterThan,
"<": constraintLessThan,
">=": constraintGreaterThanEqual,
"=>": constraintGreaterThanEqual,
"<=": constraintLessThanEqual,
"=<": constraintLessThanEqual,
"~": constraintTilde,
"~>": constraintTilde,
"^": constraintCaret,
}
ops := `=||!=|>|<|>=|=>|<=|=<|~|~>|\^`
constraintRegex = regexp.MustCompile(fmt.Sprintf(
`^\s*(%s)\s*(%s)\s*$`,
ops,
cvRegex))
constraintRangeRegex = regexp.MustCompile(fmt.Sprintf(
`\s*(%s)\s+-\s+(%s)\s*`,
cvRegex, cvRegex))
findConstraintRegex = regexp.MustCompile(fmt.Sprintf(
`(%s)\s*(%s)`,
ops,
cvRegex))
// The first time a constraint shows up will look slightly different from
// future times it shows up due to a leading space or comma in a given
// string.
validConstraintRegex = regexp.MustCompile(fmt.Sprintf(
`^(\s*(%s)\s*(%s)\s*)((?:\s+|,\s*)(%s)\s*(%s)\s*)*$`,
ops,
cvRegex,
ops,
cvRegex))
}
// An individual constraint
type constraint struct {
// The version used in the constraint check. For example, if a constraint
// is '<= 2.0.0' the con a version instance representing 2.0.0.
con *Version
// The original parsed version (e.g., 4.x from != 4.x)
orig string
// The original operator for the constraint
origfunc string
// When an x is used as part of the version (e.g., 1.x)
minorDirty bool
dirty bool
patchDirty bool
}
// Check if a version meets the constraint
func (c *constraint) check(v *Version) (bool, error) {
return constraintOps[c.origfunc](v, c)
}
// String prints an individual constraint into a string
func (c *constraint) string() string {
return c.origfunc + c.orig
}
type cfunc func(v *Version, c *constraint) (bool, error)
func parseConstraint(c string) (*constraint, error) {
if len(c) > 0 {
m := constraintRegex.FindStringSubmatch(c)
if m == nil {
return nil, fmt.Errorf("improper constraint: %s", c)
}
cs := &constraint{
orig: m[2],
origfunc: m[1],
}
ver := m[2]
minorDirty := false
patchDirty := false
dirty := false
if isX(m[3]) || m[3] == "" {
ver = fmt.Sprintf("0.0.0%s", m[6])
dirty = true
} else if isX(strings.TrimPrefix(m[4], ".")) || m[4] == "" {
minorDirty = true
dirty = true
ver = fmt.Sprintf("%s.0.0%s", m[3], m[6])
} else if isX(strings.TrimPrefix(m[5], ".")) || m[5] == "" {
dirty = true
patchDirty = true
ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6])
}
con, err := NewVersion(ver)
if err != nil {
// The constraintRegex should catch any regex parsing errors. So,
// we should never get here.
return nil, errors.New("constraint Parser Error")
}
cs.con = con
cs.minorDirty = minorDirty
cs.patchDirty = patchDirty
cs.dirty = dirty
return cs, nil
}
// The rest is the special case where an empty string was passed in which
// is equivalent to * or >=0.0.0
con, err := StrictNewVersion("0.0.0")
if err != nil {
// The constraintRegex should catch any regex parsing errors. So,
// we should never get here.
return nil, errors.New("constraint Parser Error")
}
cs := &constraint{
con: con,
orig: c,
origfunc: "",
minorDirty: false,
patchDirty: false,
dirty: true,
}
return cs, nil
}
// Constraint functions
func constraintNotEqual(v *Version, c *constraint) (bool, error) {
if c.dirty {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if c.con.Major() != v.Major() {
return true, nil
}
if c.con.Minor() != v.Minor() && !c.minorDirty {
return true, nil
} else if c.minorDirty {
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
} else if c.con.Patch() != v.Patch() && !c.patchDirty {
return true, nil
} else if c.patchDirty {
// Need to handle prereleases if present
if v.Prerelease() != "" || c.con.Prerelease() != "" {
eq := comparePrerelease(v.Prerelease(), c.con.Prerelease()) != 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
}
eq := v.Equal(c.con)
if eq {
return false, fmt.Errorf("%s is equal to %s", v, c.orig)
}
return true, nil
}
func constraintGreaterThan(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
if !c.dirty {
eq = v.Compare(c.con) == 1
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
if v.Major() > c.con.Major() {
return true, nil
} else if v.Major() < c.con.Major() {
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
} else if c.minorDirty {
// This is a range case such as >11. When the version is something like
// 11.1.0 is it not > 11. For that we would need 12 or higher
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
} else if c.patchDirty {
// This is for ranges such as >11.1. A version of 11.1.1 is not greater
// which one of 11.2.1 is greater
eq = v.Minor() > c.con.Minor()
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
// If we have gotten here we are not comparing pre-preleases and can use the
// Compare function to accomplish that.
eq = v.Compare(c.con) == 1
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than or equal to %s", v, c.orig)
}
func constraintLessThan(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) < 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is greater than or equal to %s", v, c.orig)
}
func constraintGreaterThanEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
eq := v.Compare(c.con) >= 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
func constraintLessThanEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
var eq bool
if !c.dirty {
eq = v.Compare(c.con) <= 0
if eq {
return true, nil
}
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
}
if v.Major() > c.con.Major() {
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
} else if v.Major() == c.con.Major() && v.Minor() > c.con.Minor() && !c.minorDirty {
return false, fmt.Errorf("%s is greater than %s", v, c.orig)
}
return true, nil
}
// ~*, ~>* --> >= 0.0.0 (any)
// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0
// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0
// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0
// ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0
// ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0
func constraintTilde(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if v.LessThan(c.con) {
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
// ~0.0.0 is a special case where all constraints are accepted. It's
// equivalent to >= 0.0.0.
if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 &&
!c.minorDirty && !c.patchDirty {
return true, nil
}
if v.Major() != c.con.Major() {
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
if v.Minor() != c.con.Minor() && !c.minorDirty {
return false, fmt.Errorf("%s does not have same major and minor version as %s", v, c.orig)
}
return true, nil
}
// When there is a .x (dirty) status it automatically opts in to ~. Otherwise
// it's a straight =
func constraintTildeOrEqual(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
if c.dirty {
return constraintTilde(v, c)
}
eq := v.Equal(c.con)
if eq {
return true, nil
}
return false, fmt.Errorf("%s is not equal to %s", v, c.orig)
}
// ^* --> (any)
// ^1.2.3 --> >=1.2.3 <2.0.0
// ^1.2 --> >=1.2.0 <2.0.0
// ^1 --> >=1.0.0 <2.0.0
// ^0.2.3 --> >=0.2.3 <0.3.0
// ^0.2 --> >=0.2.0 <0.3.0
// ^0.0.3 --> >=0.0.3 <0.0.4
// ^0.0 --> >=0.0.0 <0.1.0
// ^0 --> >=0.0.0 <1.0.0
func constraintCaret(v *Version, c *constraint) (bool, error) {
// If there is a pre-release on the version but the constraint isn't looking
// for them assume that pre-releases are not compatible. See issue 21 for
// more details.
if v.Prerelease() != "" && c.con.Prerelease() == "" {
return false, fmt.Errorf("%s is a prerelease version and the constraint is only looking for release versions", v)
}
// This less than handles prereleases
if v.LessThan(c.con) {
return false, fmt.Errorf("%s is less than %s", v, c.orig)
}
var eq bool
// ^ when the major > 0 is >=x.y.z < x+1
if c.con.Major() > 0 || c.minorDirty {
// ^ has to be within a major range for > 0. Everything less than was
// filtered out with the LessThan call above. This filters out those
// that greater but not within the same major range.
eq = v.Major() == c.con.Major()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
// ^ when the major is 0 and minor > 0 is >=0.y.z < 0.y+1
if c.con.Major() == 0 && v.Major() > 0 {
return false, fmt.Errorf("%s does not have same major version as %s", v, c.orig)
}
// If the con Minor is > 0 it is not dirty
if c.con.Minor() > 0 || c.patchDirty {
eq = v.Minor() == c.con.Minor()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not have same minor version as %s. Expected minor versions to match when constraint major version is 0", v, c.orig)
}
// ^ when the minor is 0 and minor > 0 is =0.0.z
if c.con.Minor() == 0 && v.Minor() > 0 {
return false, fmt.Errorf("%s does not have same minor version as %s", v, c.orig)
}
// At this point the major is 0 and the minor is 0 and not dirty. The patch
// is not dirty so we need to check if they are equal. If they are not equal
eq = c.con.Patch() == v.Patch()
if eq {
return true, nil
}
return false, fmt.Errorf("%s does not equal %s. Expect version and constraint to equal when major and minor versions are 0", v, c.orig)
}
func isX(x string) bool {
switch x {
case "x", "*", "X":
return true
default:
return false
}
}
func rewriteRange(i string) string {
m := constraintRangeRegex.FindAllStringSubmatch(i, -1)
if m == nil {
return i
}
o := i
for _, v := range m {
t := fmt.Sprintf(">= %s, <= %s ", v[1], v[11])
o = strings.Replace(o, v[0], t, 1)
}
return o
}
================================================
FILE: vendor/github.com/Masterminds/semver/v3/doc.go
================================================
/*
Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go.
Specifically it provides the ability to:
- Parse semantic versions
- Sort semantic versions
- Check if a semantic version fits within a set of constraints
- Optionally work with a `v` prefix
# Parsing Semantic Versions
There are two functions that can parse semantic versions. The `StrictNewVersion`
function only parses valid version 2 semantic versions as outlined in the
specification. The `NewVersion` function attempts to coerce a version into a
semantic version and parse it. For example, if there is a leading v or a version
listed without all 3 parts (e.g. 1.2) it will attempt to coerce it into a valid
semantic version (e.g., 1.2.0). In both cases a `Version` object is returned
that can be sorted, compared, and used in constraints.
When parsing a version an optional error can be returned if there is an issue
parsing the version. For example,
v, err := semver.NewVersion("1.2.3-beta.1+b345")
The version object has methods to get the parts of the version, compare it to
other versions, convert the version back into a string, and get the original
string. For more details please see the documentation
at https://godoc.org/github.com/Masterminds/semver.
# Sorting Semantic Versions
A set of versions can be sorted using the `sort` package from the standard library.
For example,
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
# Checking Version Constraints and Comparing Versions
There are two methods for comparing versions. One uses comparison methods on
`Version` instances and the other is using Constraints. There are some important
differences to notes between these two methods of comparison.
1. When two versions are compared using functions such as `Compare`, `LessThan`,
and others it will follow the specification and always include prereleases
within the comparison. It will provide an answer valid with the comparison
spec section at https://semver.org/#spec-item-11
2. When constraint checking is used for checks or validation it will follow a
different set of rules that are common for ranges with tools like npm/js
and Rust/Cargo. This includes considering prereleases to be invalid if the
ranges does not include on. If you want to have it include pre-releases a
simple solution is to include `-0` in your range.
3. Constraint ranges can have some complex rules including the shorthard use of
~ and ^. For more details on those see the options below.
There are differences between the two methods or checking versions because the
comparison methods on `Version` follow the specification while comparison ranges
are not part of the specification. Different packages and tools have taken it
upon themselves to come up with range rules. This has resulted in differences.
For example, npm/js and Cargo/Rust follow similar patterns which PHP has a
different pattern for ^. The comparison features in this package follow the
npm/js and Cargo/Rust lead because applications using it have followed similar
patters with their versions.
Checking a version against version constraints is one of the most featureful
parts of the package.
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// Handle constraint not being parsable.
}
v, err := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parsable.
}
// Check if the version meets the constraints. The a variable will be true.
a := c.Check(v)
# Basic Comparisons
There are two elements to the comparisons. First, a comparison string is a list
of comma or space separated AND comparisons. These are then separated by || (OR)
comparisons. For example, `">= 1.2 < 3.0.0 || >= 4.2.3"` is looking for a
comparison that's greater than or equal to 1.2 and less than 3.0.0 or is
greater than or equal to 4.2.3. This can also be written as
`">= 1.2, < 3.0.0 || >= 4.2.3"`
The basic comparisons are:
- `=`: equal (aliased to no operator)
- `!=`: not equal
- `>`: greater than
- `<`: less than
- `>=`: greater than or equal to
- `<=`: less than or equal to
# Hyphen Range Comparisons
There are multiple methods to handle ranges and the first is hyphens ranges.
These look like:
- `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5`
- `2.3.4 - 4.5` which is equivalent to `>= 2.3.4 <= 4.5`
# Wildcards In Comparisons
The `x`, `X`, and `*` characters can be used as a wildcard character. This works
for all comparison operators. When used on the `=` operator it falls
back to the tilde operation. For example,
- `1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- `>= 1.2.x` is equivalent to `>= 1.2.0`
- `<= 2.x` is equivalent to `<= 3`
- `*` is equivalent to `>= 0.0.0`
Tilde Range Comparisons (Patch)
The tilde (`~`) comparison operator is for patch level ranges when a minor
version is specified and major level changes when the minor number is missing.
For example,
- `~1.2.3` is equivalent to `>= 1.2.3 < 1.3.0`
- `~1` is equivalent to `>= 1, < 2`
- `~2.3` is equivalent to `>= 2.3 < 2.4`
- `~1.2.x` is equivalent to `>= 1.2.0 < 1.3.0`
- `~1.x` is equivalent to `>= 1 < 2`
Caret Range Comparisons (Major)
The caret (`^`) comparison operator is for major level changes once a stable
(1.0.0) release has occurred. Prior to a 1.0.0 release the minor versions acts
as the API stability level. This is useful when comparisons of API versions as a
major change is API breaking. For example,
- `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0`
- `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0`
- `^2.3` is equivalent to `>= 2.3, < 3`
- `^2.x` is equivalent to `>= 2.0.0, < 3`
- `^0.2.3` is equivalent to `>=0.2.3 <0.3.0`
- `^0.2` is equivalent to `>=0.2.0 <0.3.0`
- `^0.0.3` is equivalent to `>=0.0.3 <0.0.4`
- `^0.0` is equivalent to `>=0.0.0 <0.1.0`
- `^0` is equivalent to `>=0.0.0 <1.0.0`
# Validation
In addition to testing a version against a constraint, a version can be validated
against a constraint. When validation fails a slice of errors containing why a
version didn't meet the constraint is returned. For example,
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// Handle constraint not being parseable.
}
v, _ := semver.NewVersion("1.3")
if err != nil {
// Handle version not being parseable.
}
// Validate a version against a constraint.
a, msgs := c.Validate(v)
// a is false
for _, m := range msgs {
fmt.Println(m)
// Loops over the errors which would read
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
*/
package semver
================================================
FILE: vendor/github.com/Masterminds/semver/v3/version.go
================================================
package semver
import (
"bytes"
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
// The compiled version of the regex created at init() is cached here so it
// only needs to be created once.
var versionRegex *regexp.Regexp
var (
// ErrInvalidSemVer is returned a version is found to be invalid when
// being parsed.
ErrInvalidSemVer = errors.New("Invalid Semantic Version")
// ErrEmptyString is returned when an empty string is passed in for parsing.
ErrEmptyString = errors.New("Version string empty")
// ErrInvalidCharacters is returned when invalid characters are found as
// part of a version
ErrInvalidCharacters = errors.New("Invalid characters in version")
// ErrSegmentStartsZero is returned when a version segment starts with 0.
// This is invalid in SemVer.
ErrSegmentStartsZero = errors.New("Version segment starts with 0")
// ErrInvalidMetadata is returned when the metadata is an invalid format
ErrInvalidMetadata = errors.New("Invalid Metadata string")
// ErrInvalidPrerelease is returned when the pre-release is an invalid format
ErrInvalidPrerelease = errors.New("Invalid Prerelease string")
)
// semVerRegex is the regular expression used to parse a semantic version.
const semVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` +
`(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +
`(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?`
// Version represents a single semantic version.
type Version struct {
major, minor, patch uint64
pre string
metadata string
original string
}
func init() {
versionRegex = regexp.MustCompile("^" + semVerRegex + "$")
}
const (
num string = "0123456789"
allowed string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-" + num
)
// StrictNewVersion parses a given version and returns an instance of Version or
// an error if unable to parse the version. Only parses valid semantic versions.
// Performs checking that can find errors within the version.
// If you want to coerce a version such as 1 or 1.2 and parse it as the 1.x
// releases of semver did, use the NewVersion() function.
func StrictNewVersion(v string) (*Version, error) {
// Parsing here does not use RegEx in order to increase performance and reduce
// allocations.
if len(v) == 0 {
return nil, ErrEmptyString
}
// Split the parts into [0]major, [1]minor, and [2]patch,prerelease,build
parts := strings.SplitN(v, ".", 3)
if len(parts) != 3 {
return nil, ErrInvalidSemVer
}
sv := &Version{
original: v,
}
// Extract build metadata
if strings.Contains(parts[2], "+") {
extra := strings.SplitN(parts[2], "+", 2)
sv.metadata = extra[1]
parts[2] = extra[0]
if err := validateMetadata(sv.metadata); err != nil {
return nil, err
}
}
// Extract build prerelease
if strings.Contains(parts[2], "-") {
extra := strings.SplitN(parts[2], "-", 2)
sv.pre = extra[1]
parts[2] = extra[0]
if err := validatePrerelease(sv.pre); err != nil {
return nil, err
}
}
// Validate the number segments are valid. This includes only having positive
// numbers and no leading 0's.
for _, p := range parts {
if !containsOnly(p, num) {
return nil, ErrInvalidCharacters
}
if len(p) > 1 && p[0] == '0' {
return nil, ErrSegmentStartsZero
}
}
// Extract major, minor, and patch
var err error
sv.major, err = strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return nil, err
}
sv.minor, err = strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return nil, err
}
sv.patch, err = strconv.ParseUint(parts[2], 10, 64)
if err != nil {
return nil, err
}
return sv, nil
}
// NewVersion parses a given version and returns an instance of Version or
// an error if unable to parse the version. If the version is SemVer-ish it
// attempts to convert it to SemVer. If you want to validate it was a strict
// semantic version at parse time see StrictNewVersion().
func NewVersion(v string) (*Version, error) {
m := versionRegex.FindStringSubmatch(v)
if m == nil {
return nil, ErrInvalidSemVer
}
sv := &Version{
metadata: m[8],
pre: m[5],
original: v,
}
var err error
sv.major, err = strconv.ParseUint(m[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
if m[2] != "" {
sv.minor, err = strconv.ParseUint(strings.TrimPrefix(m[2], "."), 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
} else {
sv.minor = 0
}
if m[3] != "" {
sv.patch, err = strconv.ParseUint(strings.TrimPrefix(m[3], "."), 10, 64)
if err != nil {
return nil, fmt.Errorf("Error parsing version segment: %s", err)
}
} else {
sv.patch = 0
}
// Perform some basic due diligence on the extra parts to ensure they are
// valid.
if sv.pre != "" {
if err = validatePrerelease(sv.pre); err != nil {
return nil, err
}
}
if sv.metadata != "" {
if err = validateMetadata(sv.metadata); err != nil {
return nil, err
}
}
return sv, nil
}
// New creates a new instance of Version with each of the parts passed in as
// arguments instead of parsing a version string.
func New(major, minor, patch uint64, pre, metadata string) *Version {
v := Version{
major: major,
minor: minor,
patch: patch,
pre: pre,
metadata: metadata,
original: "",
}
v.original = v.String()
return &v
}
// MustParse parses a given version and panics on error.
func MustParse(v string) *Version {
sv, err := NewVersion(v)
if err != nil {
panic(err)
}
return sv
}
// String converts a Version object to a string.
// Note, if the original version contained a leading v this version will not.
// See the Original() method to retrieve the original value. Semantic Versions
// don't contain a leading v per the spec. Instead it's optional on
// implementation.
func (v Version) String() string {
var buf bytes.Buffer
fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch)
if v.pre != "" {
fmt.Fprintf(&buf, "-%s", v.pre)
}
if v.metadata != "" {
fmt.Fprintf(&buf, "+%s", v.metadata)
}
return buf.String()
}
// Original returns the original value passed in to be parsed.
func (v *Version) Original() string {
return v.original
}
// Major returns the major version.
func (v Version) Major() uint64 {
return v.major
}
// Minor returns the minor version.
func (v Version) Minor() uint64 {
return v.minor
}
// Patch returns the patch version.
func (v Version) Patch() uint64 {
return v.patch
}
// Prerelease returns the pre-release version.
func (v Version) Prerelease() string {
return v.pre
}
// Metadata returns the metadata on the version.
func (v Version) Metadata() string {
return v.metadata
}
// originalVPrefix returns the original 'v' prefix if any.
func (v Version) originalVPrefix() string {
// Note, only lowercase v is supported as a prefix by the parser.
if v.original != "" && v.original[:1] == "v" {
return v.original[:1]
}
return ""
}
// IncPatch produces the next patch version.
// If the current version does not have prerelease/metadata information,
// it unsets metadata and prerelease values, increments patch number.
// If the current version has any of prerelease or metadata information,
// it unsets both values and keeps current patch value
func (v Version) IncPatch() Version {
vNext := v
// according to http://semver.org/#spec-item-9
// Pre-release versions have a lower precedence than the associated normal version.
// according to http://semver.org/#spec-item-10
// Build metadata SHOULD be ignored when determining version precedence.
if v.pre != "" {
vNext.metadata = ""
vNext.pre = ""
} else {
vNext.metadata = ""
vNext.pre = ""
vNext.patch = v.patch + 1
}
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
}
// IncMinor produces the next minor version.
// Sets patch to 0.
// Increments minor number.
// Unsets metadata.
// Unsets prerelease status.
func (v Version) IncMinor() Version {
vNext := v
vNext.metadata = ""
vNext.pre = ""
vNext.patch = 0
vNext.minor = v.minor + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
}
// IncMajor produces the next major version.
// Sets patch to 0.
// Sets minor to 0.
// Increments major number.
// Unsets metadata.
// Unsets prerelease status.
func (v Version) IncMajor() Version {
vNext := v
vNext.metadata = ""
vNext.pre = ""
vNext.patch = 0
vNext.minor = 0
vNext.major = v.major + 1
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext
}
// SetPrerelease defines the prerelease value.
// Value must not include the required 'hyphen' prefix.
func (v Version) SetPrerelease(prerelease string) (Version, error) {
vNext := v
if len(prerelease) > 0 {
if err := validatePrerelease(prerelease); err != nil {
return vNext, err
}
}
vNext.pre = prerelease
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext, nil
}
// SetMetadata defines metadata value.
// Value must not include the required 'plus' prefix.
func (v Version) SetMetadata(metadata string) (Version, error) {
vNext := v
if len(metadata) > 0 {
if err := validateMetadata(metadata); err != nil {
return vNext, err
}
}
vNext.metadata = metadata
vNext.original = v.originalVPrefix() + "" + vNext.String()
return vNext, nil
}
// LessThan tests if one version is less than another one.
func (v *Version) LessThan(o *Version) bool {
return v.Compare(o) < 0
}
// LessThanEqual tests if one version is less or equal than another one.
func (v *Version) LessThanEqual(o *Version) bool {
return v.Compare(o) <= 0
}
// GreaterThan tests if one version is greater than another one.
func (v *Version) GreaterThan(o *Version) bool {
return v.Compare(o) > 0
}
// GreaterThanEqual tests if one version is greater or equal than another one.
func (v *Version) GreaterThanEqual(o *Version) bool {
return v.Compare(o) >= 0
}
// Equal tests if two versions are equal to each other.
// Note, versions can be equal with different metadata since metadata
// is not considered part of the comparable version.
func (v *Version) Equal(o *Version) bool {
if v == o {
return true
}
if v == nil || o == nil {
return false
}
return v.Compare(o) == 0
}
// Compare compares this version to another one. It returns -1, 0, or 1 if
// the version smaller, equal, or larger than the other version.
//
// Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is
// lower than the version without a prerelease. Compare always takes into account
// prereleases. If you want to work with ranges using typical range syntaxes that
// skip prereleases if the range is not looking for them use constraints.
func (v *Version) Compare(o *Version) int {
// Compare the major, minor, and patch version for differences. If a
// difference is found return the comparison.
if d := compareSegment(v.Major(), o.Major()); d != 0 {
return d
}
if d := compareSegment(v.Minor(), o.Minor()); d != 0 {
return d
}
if d := compareSegment(v.Patch(), o.Patch()); d != 0 {
return d
}
// At this point the major, minor, and patch versions are the same.
ps := v.pre
po := o.Prerelease()
if ps == "" && po == "" {
return 0
}
if ps == "" {
return 1
}
if po == "" {
return -1
}
return comparePrerelease(ps, po)
}
// UnmarshalJSON implements JSON.Unmarshaler interface.
func (v *Version) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
temp, err := NewVersion(s)
if err != nil {
return err
}
v.major = temp.major
v.minor = temp.minor
v.patch = temp.patch
v.pre = temp.pre
v.metadata = temp.metadata
v.original = temp.original
return nil
}
// MarshalJSON implements JSON.Marshaler interface.
func (v Version) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (v *Version) UnmarshalText(text []byte) error {
temp, err := NewVersion(string(text))
if err != nil {
return err
}
*v = *temp
return nil
}
// MarshalText implements the encoding.TextMarshaler interface.
func (v Version) MarshalText() ([]byte, error) {
return []byte(v.String()), nil
}
// Scan implements the SQL.Scanner interface.
func (v *Version) Scan(value interface{}) error {
var s string
s, _ = value.(string)
temp, err := NewVersion(s)
if err != nil {
return err
}
v.major = temp.major
v.minor = temp.minor
v.patch = temp.patch
v.pre = temp.pre
v.metadata = temp.metadata
v.original = temp.original
return nil
}
// Value implements the Driver.Valuer interface.
func (v Version) Value() (driver.Value, error) {
return v.String(), nil
}
func compareSegment(v, o uint64) int {
if v < o {
return -1
}
if v > o {
return 1
}
return 0
}
func comparePrerelease(v, o string) int {
// split the prelease versions by their part. The separator, per the spec,
// is a .
sparts := strings.Split(v, ".")
oparts := strings.Split(o, ".")
// Find the longer length of the parts to know how many loop iterations to
// go through.
slen := len(sparts)
olen := len(oparts)
l := slen
if olen > slen {
l = olen
}
// Iterate over each part of the prereleases to compare the differences.
for i := 0; i < l; i++ {
// Since the lentgh of the parts can be different we need to create
// a placeholder. This is to avoid out of bounds issues.
stemp := ""
if i < slen {
stemp = sparts[i]
}
otemp := ""
if i < olen {
otemp = oparts[i]
}
d := comparePrePart(stemp, otemp)
if d != 0 {
return d
}
}
// Reaching here means two versions are of equal value but have different
// metadata (the part following a +). They are not identical in string form
// but the version comparison finds them to be equal.
return 0
}
func comparePrePart(s, o string) int {
// Fastpath if they are equal
if s == o {
return 0
}
// When s or o are empty we can use the other in an attempt to determine
// the response.
if s == "" {
if o != "" {
return -1
}
return 1
}
if o == "" {
if s != "" {
return 1
}
return -1
}
// When comparing strings "99" is greater than "103". To handle
// cases like this we need to detect numbers and compare them. According
// to the semver spec, numbers are always positive. If there is a - at the
// start like -99 this is to be evaluated as an alphanum. numbers always
// have precedence over alphanum. Parsing as Uints because negative numbers
// are ignored.
oi, n1 := strconv.ParseUint(o, 10, 64)
si, n2 := strconv.ParseUint(s, 10, 64)
// The case where both are strings compare the strings
if n1 != nil && n2 != nil {
if s > o {
return 1
}
return -1
} else if n1 != nil {
// o is a string and s is a number
return -1
} else if n2 != nil {
// s is a string and o is a number
return 1
}
// Both are numbers
if si > oi {
return 1
}
return -1
}
// Like strings.ContainsAny but does an only instead of any.
func containsOnly(s string, comp string) bool {
return strings.IndexFunc(s, func(r rune) bool {
return !strings.ContainsRune(comp, r)
}) == -1
}
// From the spec, "Identifiers MUST comprise only
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty.
// Numeric identifiers MUST NOT include leading zeroes.". These segments can
// be dot separated.
func validatePrerelease(p string) error {
eparts := strings.Split(p, ".")
for _, p := range eparts {
if containsOnly(p, num) {
if len(p) > 1 && p[0] == '0' {
return ErrSegmentStartsZero
}
} else if !containsOnly(p, allowed) {
return ErrInvalidPrerelease
}
}
return nil
}
// From the spec, "Build metadata MAY be denoted by
// appending a plus sign and a series of dot separated identifiers immediately
// following the patch or pre-release version. Identifiers MUST comprise only
// ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty."
func validateMetadata(m string) error {
eparts := strings.Split(m, ".")
for _, p := range eparts {
if !containsOnly(p, allowed) {
return ErrInvalidMetadata
}
}
return nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/.gitattributes
================================================
* text=auto eol=lf
================================================
FILE: vendor/github.com/Microsoft/go-winio/.gitignore
================================================
.vscode/
*.exe
# testing
testdata
# go workspaces
go.work
go.work.sum
================================================
FILE: vendor/github.com/Microsoft/go-winio/.golangci.yml
================================================
run:
skip-dirs:
- pkg/etw/sample
linters:
enable:
# style
- containedctx # struct contains a context
- dupl # duplicate code
- errname # erorrs are named correctly
- nolintlint # "//nolint" directives are properly explained
- revive # golint replacement
- unconvert # unnecessary conversions
- wastedassign
# bugs, performance, unused, etc ...
- contextcheck # function uses a non-inherited context
- errorlint # errors not wrapped for 1.13
- exhaustive # check exhaustiveness of enum switch statements
- gofmt # files are gofmt'ed
- gosec # security
- nilerr # returns nil even with non-nil error
- unparam # unused function params
issues:
exclude-rules:
# err is very often shadowed in nested scopes
- linters:
- govet
text: '^shadow: declaration of "err" shadows declaration'
# ignore long lines for skip autogen directives
- linters:
- revive
text: "^line-length-limit: "
source: "^//(go:generate|sys) "
#TODO: remove after upgrading to go1.18
# ignore comment spacing for nolint and sys directives
- linters:
- revive
text: "^comment-spacings: no space between comment delimiter and comment text"
source: "//(cspell:|nolint:|sys |todo)"
# not on go 1.18 yet, so no any
- linters:
- revive
text: "^use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
# allow unjustified ignores of error checks in defer statements
- linters:
- nolintlint
text: "^directive `//nolint:errcheck` should provide explanation"
source: '^\s*defer '
# allow unjustified ignores of error lints for io.EOF
- linters:
- nolintlint
text: "^directive `//nolint:errorlint` should provide explanation"
source: '[=|!]= io.EOF'
linters-settings:
exhaustive:
default-signifies-exhaustive: true
govet:
enable-all: true
disable:
# struct order is often for Win32 compat
# also, ignore pointer bytes/GC issues for now until performance becomes an issue
- fieldalignment
check-shadowing: true
nolintlint:
allow-leading-space: false
require-explanation: true
require-specific: true
revive:
# revive is more configurable than static check, so likely the preferred alternative to static-check
# (once the perf issue is solved: https://github.com/golangci/golangci-lint/issues/2997)
enable-all-rules:
true
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
rules:
# rules with required arguments
- name: argument-limit
disabled: true
- name: banned-characters
disabled: true
- name: cognitive-complexity
disabled: true
- name: cyclomatic
disabled: true
- name: file-header
disabled: true
- name: function-length
disabled: true
- name: function-result-limit
disabled: true
- name: max-public-structs
disabled: true
# geneally annoying rules
- name: add-constant # complains about any and all strings and integers
disabled: true
- name: confusing-naming # we frequently use "Foo()" and "foo()" together
disabled: true
- name: flag-parameter # excessive, and a common idiom we use
disabled: true
- name: unhandled-error # warns over common fmt.Print* and io.Close; rely on errcheck instead
disabled: true
# general config
- name: line-length-limit
arguments:
- 140
- name: var-naming
arguments:
- []
- - CID
- CRI
- CTRD
- DACL
- DLL
- DOS
- ETW
- FSCTL
- GCS
- GMSA
- HCS
- HV
- IO
- LCOW
- LDAP
- LPAC
- LTSC
- MMIO
- NT
- OCI
- PMEM
- PWSH
- RX
- SACl
- SID
- SMB
- TX
- VHD
- VHDX
- VMID
- VPCI
- WCOW
- WIM
================================================
FILE: vendor/github.com/Microsoft/go-winio/CODEOWNERS
================================================
* @microsoft/containerplat
================================================
FILE: vendor/github.com/Microsoft/go-winio/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2015 Microsoft
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: vendor/github.com/Microsoft/go-winio/README.md
================================================
# go-winio [](https://github.com/microsoft/go-winio/actions/workflows/ci.yml)
This repository contains utilities for efficiently performing Win32 IO operations in
Go. Currently, this is focused on accessing named pipes and other file handles, and
for using named pipes as a net transport.
This code relies on IO completion ports to avoid blocking IO on system threads, allowing Go
to reuse the thread to schedule another goroutine. This limits support to Windows Vista and
newer operating systems. This is similar to the implementation of network sockets in Go's net
package.
Please see the LICENSE file for licensing information.
## Contributing
This project welcomes contributions and suggestions.
Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that
you have the right to, and actually do, grant us the rights to use your contribution.
For details, visit [Microsoft CLA](https://cla.microsoft.com).
When you submit a pull request, a CLA-bot will automatically determine whether you need to
provide a CLA and decorate the PR appropriately (e.g., label, comment).
Simply follow the instructions provided by the bot.
You will only need to do this once across all repos using our CLA.
Additionally, the pull request pipeline requires the following steps to be performed before
mergining.
### Code Sign-Off
We require that contributors sign their commits using [`git commit --signoff`][git-commit-s]
to certify they either authored the work themselves or otherwise have permission to use it in this project.
A range of commits can be signed off using [`git rebase --signoff`][git-rebase-s].
Please see [the developer certificate](https://developercertificate.org) for more info,
as well as to make sure that you can attest to the rules listed.
Our CI uses the DCO Github app to ensure that all commits in a given PR are signed-off.
### Linting
Code must pass a linting stage, which uses [`golangci-lint`][lint].
The linting settings are stored in [`.golangci.yaml`](./.golangci.yaml), and can be run
automatically with VSCode by adding the following to your workspace or folder settings:
```json
"go.lintTool": "golangci-lint",
"go.lintOnSave": "package",
```
Additional editor [integrations options are also available][lint-ide].
Alternatively, `golangci-lint` can be [installed locally][lint-install] and run from the repo root:
```shell
# use . or specify a path to only lint a package
# to show all lint errors, use flags "--max-issues-per-linter=0 --max-same-issues=0"
> golangci-lint run ./...
```
### Go Generate
The pipeline checks that auto-generated code, via `go generate`, are up to date.
This can be done for the entire repo:
```shell
> go generate ./...
```
## Code of Conduct
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Special Thanks
Thanks to [natefinch][natefinch] for the inspiration for this library.
See [npipe](https://github.com/natefinch/npipe) for another named pipe implementation.
[lint]: https://golangci-lint.run/
[lint-ide]: https://golangci-lint.run/usage/integrations/#editor-integration
[lint-install]: https://golangci-lint.run/usage/install/#local-installation
[git-commit-s]: https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s
[git-rebase-s]: https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---signoff
[natefinch]: https://github.com/natefinch
================================================
FILE: vendor/github.com/Microsoft/go-winio/SECURITY.md
================================================
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
================================================
FILE: vendor/github.com/Microsoft/go-winio/backup.go
================================================
//go:build windows
// +build windows
package winio
import (
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"runtime"
"syscall"
"unicode/utf16"
"golang.org/x/sys/windows"
)
//sys backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupRead
//sys backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) = BackupWrite
const (
BackupData = uint32(iota + 1)
BackupEaData
BackupSecurity
BackupAlternateData
BackupLink
BackupPropertyData
BackupObjectId //revive:disable-line:var-naming ID, not Id
BackupReparseData
BackupSparseBlock
BackupTxfsData
)
const (
StreamSparseAttributes = uint32(8)
)
//nolint:revive // var-naming: ALL_CAPS
const (
WRITE_DAC = windows.WRITE_DAC
WRITE_OWNER = windows.WRITE_OWNER
ACCESS_SYSTEM_SECURITY = windows.ACCESS_SYSTEM_SECURITY
)
// BackupHeader represents a backup stream of a file.
type BackupHeader struct {
//revive:disable-next-line:var-naming ID, not Id
Id uint32 // The backup stream ID
Attributes uint32 // Stream attributes
Size int64 // The size of the stream in bytes
Name string // The name of the stream (for BackupAlternateData only).
Offset int64 // The offset of the stream in the file (for BackupSparseBlock only).
}
type win32StreamID struct {
StreamID uint32
Attributes uint32
Size uint64
NameSize uint32
}
// BackupStreamReader reads from a stream produced by the BackupRead Win32 API and produces a series
// of BackupHeader values.
type BackupStreamReader struct {
r io.Reader
bytesLeft int64
}
// NewBackupStreamReader produces a BackupStreamReader from any io.Reader.
func NewBackupStreamReader(r io.Reader) *BackupStreamReader {
return &BackupStreamReader{r, 0}
}
// Next returns the next backup stream and prepares for calls to Read(). It skips the remainder of the current stream if
// it was not completely read.
func (r *BackupStreamReader) Next() (*BackupHeader, error) {
if r.bytesLeft > 0 { //nolint:nestif // todo: flatten this
if s, ok := r.r.(io.Seeker); ok {
// Make sure Seek on io.SeekCurrent sometimes succeeds
// before trying the actual seek.
if _, err := s.Seek(0, io.SeekCurrent); err == nil {
if _, err = s.Seek(r.bytesLeft, io.SeekCurrent); err != nil {
return nil, err
}
r.bytesLeft = 0
}
}
if _, err := io.Copy(io.Discard, r); err != nil {
return nil, err
}
}
var wsi win32StreamID
if err := binary.Read(r.r, binary.LittleEndian, &wsi); err != nil {
return nil, err
}
hdr := &BackupHeader{
Id: wsi.StreamID,
Attributes: wsi.Attributes,
Size: int64(wsi.Size),
}
if wsi.NameSize != 0 {
name := make([]uint16, int(wsi.NameSize/2))
if err := binary.Read(r.r, binary.LittleEndian, name); err != nil {
return nil, err
}
hdr.Name = syscall.UTF16ToString(name)
}
if wsi.StreamID == BackupSparseBlock {
if err := binary.Read(r.r, binary.LittleEndian, &hdr.Offset); err != nil {
return nil, err
}
hdr.Size -= 8
}
r.bytesLeft = hdr.Size
return hdr, nil
}
// Read reads from the current backup stream.
func (r *BackupStreamReader) Read(b []byte) (int, error) {
if r.bytesLeft == 0 {
return 0, io.EOF
}
if int64(len(b)) > r.bytesLeft {
b = b[:r.bytesLeft]
}
n, err := r.r.Read(b)
r.bytesLeft -= int64(n)
if err == io.EOF {
err = io.ErrUnexpectedEOF
} else if r.bytesLeft == 0 && err == nil {
err = io.EOF
}
return n, err
}
// BackupStreamWriter writes a stream compatible with the BackupWrite Win32 API.
type BackupStreamWriter struct {
w io.Writer
bytesLeft int64
}
// NewBackupStreamWriter produces a BackupStreamWriter on top of an io.Writer.
func NewBackupStreamWriter(w io.Writer) *BackupStreamWriter {
return &BackupStreamWriter{w, 0}
}
// WriteHeader writes the next backup stream header and prepares for calls to Write().
func (w *BackupStreamWriter) WriteHeader(hdr *BackupHeader) error {
if w.bytesLeft != 0 {
return fmt.Errorf("missing %d bytes", w.bytesLeft)
}
name := utf16.Encode([]rune(hdr.Name))
wsi := win32StreamID{
StreamID: hdr.Id,
Attributes: hdr.Attributes,
Size: uint64(hdr.Size),
NameSize: uint32(len(name) * 2),
}
if hdr.Id == BackupSparseBlock {
// Include space for the int64 block offset
wsi.Size += 8
}
if err := binary.Write(w.w, binary.LittleEndian, &wsi); err != nil {
return err
}
if len(name) != 0 {
if err := binary.Write(w.w, binary.LittleEndian, name); err != nil {
return err
}
}
if hdr.Id == BackupSparseBlock {
if err := binary.Write(w.w, binary.LittleEndian, hdr.Offset); err != nil {
return err
}
}
w.bytesLeft = hdr.Size
return nil
}
// Write writes to the current backup stream.
func (w *BackupStreamWriter) Write(b []byte) (int, error) {
if w.bytesLeft < int64(len(b)) {
return 0, fmt.Errorf("too many bytes by %d", int64(len(b))-w.bytesLeft)
}
n, err := w.w.Write(b)
w.bytesLeft -= int64(n)
return n, err
}
// BackupFileReader provides an io.ReadCloser interface on top of the BackupRead Win32 API.
type BackupFileReader struct {
f *os.File
includeSecurity bool
ctx uintptr
}
// NewBackupFileReader returns a new BackupFileReader from a file handle. If includeSecurity is true,
// Read will attempt to read the security descriptor of the file.
func NewBackupFileReader(f *os.File, includeSecurity bool) *BackupFileReader {
r := &BackupFileReader{f, includeSecurity, 0}
return r
}
// Read reads a backup stream from the file by calling the Win32 API BackupRead().
func (r *BackupFileReader) Read(b []byte) (int, error) {
var bytesRead uint32
err := backupRead(syscall.Handle(r.f.Fd()), b, &bytesRead, false, r.includeSecurity, &r.ctx)
if err != nil {
return 0, &os.PathError{Op: "BackupRead", Path: r.f.Name(), Err: err}
}
runtime.KeepAlive(r.f)
if bytesRead == 0 {
return 0, io.EOF
}
return int(bytesRead), nil
}
// Close frees Win32 resources associated with the BackupFileReader. It does not close
// the underlying file.
func (r *BackupFileReader) Close() error {
if r.ctx != 0 {
_ = backupRead(syscall.Handle(r.f.Fd()), nil, nil, true, false, &r.ctx)
runtime.KeepAlive(r.f)
r.ctx = 0
}
return nil
}
// BackupFileWriter provides an io.WriteCloser interface on top of the BackupWrite Win32 API.
type BackupFileWriter struct {
f *os.File
includeSecurity bool
ctx uintptr
}
// NewBackupFileWriter returns a new BackupFileWriter from a file handle. If includeSecurity is true,
// Write() will attempt to restore the security descriptor from the stream.
func NewBackupFileWriter(f *os.File, includeSecurity bool) *BackupFileWriter {
w := &BackupFileWriter{f, includeSecurity, 0}
return w
}
// Write restores a portion of the file using the provided backup stream.
func (w *BackupFileWriter) Write(b []byte) (int, error) {
var bytesWritten uint32
err := backupWrite(syscall.Handle(w.f.Fd()), b, &bytesWritten, false, w.includeSecurity, &w.ctx)
if err != nil {
return 0, &os.PathError{Op: "BackupWrite", Path: w.f.Name(), Err: err}
}
runtime.KeepAlive(w.f)
if int(bytesWritten) != len(b) {
return int(bytesWritten), errors.New("not all bytes could be written")
}
return len(b), nil
}
// Close frees Win32 resources associated with the BackupFileWriter. It does not
// close the underlying file.
func (w *BackupFileWriter) Close() error {
if w.ctx != 0 {
_ = backupWrite(syscall.Handle(w.f.Fd()), nil, nil, true, false, &w.ctx)
runtime.KeepAlive(w.f)
w.ctx = 0
}
return nil
}
// OpenForBackup opens a file or directory, potentially skipping access checks if the backup
// or restore privileges have been acquired.
//
// If the file opened was a directory, it cannot be used with Readdir().
func OpenForBackup(path string, access uint32, share uint32, createmode uint32) (*os.File, error) {
winPath, err := syscall.UTF16FromString(path)
if err != nil {
return nil, err
}
h, err := syscall.CreateFile(&winPath[0],
access,
share,
nil,
createmode,
syscall.FILE_FLAG_BACKUP_SEMANTICS|syscall.FILE_FLAG_OPEN_REPARSE_POINT,
0)
if err != nil {
err = &os.PathError{Op: "open", Path: path, Err: err}
return nil, err
}
return os.NewFile(uintptr(h), path), nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/doc.go
================================================
// This package provides utilities for efficiently performing Win32 IO operations in Go.
// Currently, this package is provides support for genreal IO and management of
// - named pipes
// - files
// - [Hyper-V sockets]
//
// This code is similar to Go's [net] package, and uses IO completion ports to avoid
// blocking IO on system threads, allowing Go to reuse the thread to schedule other goroutines.
//
// This limits support to Windows Vista and newer operating systems.
//
// Additionally, this package provides support for:
// - creating and managing GUIDs
// - writing to [ETW]
// - opening and manageing VHDs
// - parsing [Windows Image files]
// - auto-generating Win32 API code
//
// [Hyper-V sockets]: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service
// [ETW]: https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-
// [Windows Image files]: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/work-with-windows-images
package winio
================================================
FILE: vendor/github.com/Microsoft/go-winio/ea.go
================================================
package winio
import (
"bytes"
"encoding/binary"
"errors"
)
type fileFullEaInformation struct {
NextEntryOffset uint32
Flags uint8
NameLength uint8
ValueLength uint16
}
var (
fileFullEaInformationSize = binary.Size(&fileFullEaInformation{})
errInvalidEaBuffer = errors.New("invalid extended attribute buffer")
errEaNameTooLarge = errors.New("extended attribute name too large")
errEaValueTooLarge = errors.New("extended attribute value too large")
)
// ExtendedAttribute represents a single Windows EA.
type ExtendedAttribute struct {
Name string
Value []byte
Flags uint8
}
func parseEa(b []byte) (ea ExtendedAttribute, nb []byte, err error) {
var info fileFullEaInformation
err = binary.Read(bytes.NewReader(b), binary.LittleEndian, &info)
if err != nil {
err = errInvalidEaBuffer
return ea, nb, err
}
nameOffset := fileFullEaInformationSize
nameLen := int(info.NameLength)
valueOffset := nameOffset + int(info.NameLength) + 1
valueLen := int(info.ValueLength)
nextOffset := int(info.NextEntryOffset)
if valueLen+valueOffset > len(b) || nextOffset < 0 || nextOffset > len(b) {
err = errInvalidEaBuffer
return ea, nb, err
}
ea.Name = string(b[nameOffset : nameOffset+nameLen])
ea.Value = b[valueOffset : valueOffset+valueLen]
ea.Flags = info.Flags
if info.NextEntryOffset != 0 {
nb = b[info.NextEntryOffset:]
}
return ea, nb, err
}
// DecodeExtendedAttributes decodes a list of EAs from a FILE_FULL_EA_INFORMATION
// buffer retrieved from BackupRead, ZwQueryEaFile, etc.
func DecodeExtendedAttributes(b []byte) (eas []ExtendedAttribute, err error) {
for len(b) != 0 {
ea, nb, err := parseEa(b)
if err != nil {
return nil, err
}
eas = append(eas, ea)
b = nb
}
return eas, err
}
func writeEa(buf *bytes.Buffer, ea *ExtendedAttribute, last bool) error {
if int(uint8(len(ea.Name))) != len(ea.Name) {
return errEaNameTooLarge
}
if int(uint16(len(ea.Value))) != len(ea.Value) {
return errEaValueTooLarge
}
entrySize := uint32(fileFullEaInformationSize + len(ea.Name) + 1 + len(ea.Value))
withPadding := (entrySize + 3) &^ 3
nextOffset := uint32(0)
if !last {
nextOffset = withPadding
}
info := fileFullEaInformation{
NextEntryOffset: nextOffset,
Flags: ea.Flags,
NameLength: uint8(len(ea.Name)),
ValueLength: uint16(len(ea.Value)),
}
err := binary.Write(buf, binary.LittleEndian, &info)
if err != nil {
return err
}
_, err = buf.Write([]byte(ea.Name))
if err != nil {
return err
}
err = buf.WriteByte(0)
if err != nil {
return err
}
_, err = buf.Write(ea.Value)
if err != nil {
return err
}
_, err = buf.Write([]byte{0, 0, 0}[0 : withPadding-entrySize])
if err != nil {
return err
}
return nil
}
// EncodeExtendedAttributes encodes a list of EAs into a FILE_FULL_EA_INFORMATION
// buffer for use with BackupWrite, ZwSetEaFile, etc.
func EncodeExtendedAttributes(eas []ExtendedAttribute) ([]byte, error) {
var buf bytes.Buffer
for i := range eas {
last := false
if i == len(eas)-1 {
last = true
}
err := writeEa(&buf, &eas[i], last)
if err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/file.go
================================================
//go:build windows
// +build windows
package winio
import (
"errors"
"io"
"runtime"
"sync"
"sync/atomic"
"syscall"
"time"
"golang.org/x/sys/windows"
)
//sys cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) = CancelIoEx
//sys createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) = CreateIoCompletionPort
//sys getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) = GetQueuedCompletionStatus
//sys setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) = SetFileCompletionNotificationModes
//sys wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) = ws2_32.WSAGetOverlappedResult
type atomicBool int32
func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
func (b *atomicBool) setFalse() { atomic.StoreInt32((*int32)(b), 0) }
func (b *atomicBool) setTrue() { atomic.StoreInt32((*int32)(b), 1) }
//revive:disable-next-line:predeclared Keep "new" to maintain consistency with "atomic" pkg
func (b *atomicBool) swap(new bool) bool {
var newInt int32
if new {
newInt = 1
}
return atomic.SwapInt32((*int32)(b), newInt) == 1
}
var (
ErrFileClosed = errors.New("file has already been closed")
ErrTimeout = &timeoutError{}
)
type timeoutError struct{}
func (*timeoutError) Error() string { return "i/o timeout" }
func (*timeoutError) Timeout() bool { return true }
func (*timeoutError) Temporary() bool { return true }
type timeoutChan chan struct{}
var ioInitOnce sync.Once
var ioCompletionPort syscall.Handle
// ioResult contains the result of an asynchronous IO operation.
type ioResult struct {
bytes uint32
err error
}
// ioOperation represents an outstanding asynchronous Win32 IO.
type ioOperation struct {
o syscall.Overlapped
ch chan ioResult
}
func initIO() {
h, err := createIoCompletionPort(syscall.InvalidHandle, 0, 0, 0xffffffff)
if err != nil {
panic(err)
}
ioCompletionPort = h
go ioCompletionProcessor(h)
}
// win32File implements Reader, Writer, and Closer on a Win32 handle without blocking in a syscall.
// It takes ownership of this handle and will close it if it is garbage collected.
type win32File struct {
handle syscall.Handle
wg sync.WaitGroup
wgLock sync.RWMutex
closing atomicBool
socket bool
readDeadline deadlineHandler
writeDeadline deadlineHandler
}
type deadlineHandler struct {
setLock sync.Mutex
channel timeoutChan
channelLock sync.RWMutex
timer *time.Timer
timedout atomicBool
}
// makeWin32File makes a new win32File from an existing file handle.
func makeWin32File(h syscall.Handle) (*win32File, error) {
f := &win32File{handle: h}
ioInitOnce.Do(initIO)
_, err := createIoCompletionPort(h, ioCompletionPort, 0, 0xffffffff)
if err != nil {
return nil, err
}
err = setFileCompletionNotificationModes(h, windows.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS|windows.FILE_SKIP_SET_EVENT_ON_HANDLE)
if err != nil {
return nil, err
}
f.readDeadline.channel = make(timeoutChan)
f.writeDeadline.channel = make(timeoutChan)
return f, nil
}
func MakeOpenFile(h syscall.Handle) (io.ReadWriteCloser, error) {
// If we return the result of makeWin32File directly, it can result in an
// interface-wrapped nil, rather than a nil interface value.
f, err := makeWin32File(h)
if err != nil {
return nil, err
}
return f, nil
}
// closeHandle closes the resources associated with a Win32 handle.
func (f *win32File) closeHandle() {
f.wgLock.Lock()
// Atomically set that we are closing, releasing the resources only once.
if !f.closing.swap(true) {
f.wgLock.Unlock()
// cancel all IO and wait for it to complete
_ = cancelIoEx(f.handle, nil)
f.wg.Wait()
// at this point, no new IO can start
syscall.Close(f.handle)
f.handle = 0
} else {
f.wgLock.Unlock()
}
}
// Close closes a win32File.
func (f *win32File) Close() error {
f.closeHandle()
return nil
}
// IsClosed checks if the file has been closed.
func (f *win32File) IsClosed() bool {
return f.closing.isSet()
}
// prepareIO prepares for a new IO operation.
// The caller must call f.wg.Done() when the IO is finished, prior to Close() returning.
func (f *win32File) prepareIO() (*ioOperation, error) {
f.wgLock.RLock()
if f.closing.isSet() {
f.wgLock.RUnlock()
return nil, ErrFileClosed
}
f.wg.Add(1)
f.wgLock.RUnlock()
c := &ioOperation{}
c.ch = make(chan ioResult)
return c, nil
}
// ioCompletionProcessor processes completed async IOs forever.
func ioCompletionProcessor(h syscall.Handle) {
for {
var bytes uint32
var key uintptr
var op *ioOperation
err := getQueuedCompletionStatus(h, &bytes, &key, &op, syscall.INFINITE)
if op == nil {
panic(err)
}
op.ch <- ioResult{bytes, err}
}
}
// todo: helsaawy - create an asyncIO version that takes a context
// asyncIO processes the return value from ReadFile or WriteFile, blocking until
// the operation has actually completed.
func (f *win32File) asyncIO(c *ioOperation, d *deadlineHandler, bytes uint32, err error) (int, error) {
if err != syscall.ERROR_IO_PENDING { //nolint:errorlint // err is Errno
return int(bytes), err
}
if f.closing.isSet() {
_ = cancelIoEx(f.handle, &c.o)
}
var timeout timeoutChan
if d != nil {
d.channelLock.Lock()
timeout = d.channel
d.channelLock.Unlock()
}
var r ioResult
select {
case r = <-c.ch:
err = r.err
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
if f.closing.isSet() {
err = ErrFileClosed
}
} else if err != nil && f.socket {
// err is from Win32. Query the overlapped structure to get the winsock error.
var bytes, flags uint32
err = wsaGetOverlappedResult(f.handle, &c.o, &bytes, false, &flags)
}
case <-timeout:
_ = cancelIoEx(f.handle, &c.o)
r = <-c.ch
err = r.err
if err == syscall.ERROR_OPERATION_ABORTED { //nolint:errorlint // err is Errno
err = ErrTimeout
}
}
// runtime.KeepAlive is needed, as c is passed via native
// code to ioCompletionProcessor, c must remain alive
// until the channel read is complete.
// todo: (de)allocate *ioOperation via win32 heap functions, instead of needing to KeepAlive?
runtime.KeepAlive(c)
return int(r.bytes), err
}
// Read reads from a file handle.
func (f *win32File) Read(b []byte) (int, error) {
c, err := f.prepareIO()
if err != nil {
return 0, err
}
defer f.wg.Done()
if f.readDeadline.timedout.isSet() {
return 0, ErrTimeout
}
var bytes uint32
err = syscall.ReadFile(f.handle, b, &bytes, &c.o)
n, err := f.asyncIO(c, &f.readDeadline, bytes, err)
runtime.KeepAlive(b)
// Handle EOF conditions.
if err == nil && n == 0 && len(b) != 0 {
return 0, io.EOF
} else if err == syscall.ERROR_BROKEN_PIPE { //nolint:errorlint // err is Errno
return 0, io.EOF
} else {
return n, err
}
}
// Write writes to a file handle.
func (f *win32File) Write(b []byte) (int, error) {
c, err := f.prepareIO()
if err != nil {
return 0, err
}
defer f.wg.Done()
if f.writeDeadline.timedout.isSet() {
return 0, ErrTimeout
}
var bytes uint32
err = syscall.WriteFile(f.handle, b, &bytes, &c.o)
n, err := f.asyncIO(c, &f.writeDeadline, bytes, err)
runtime.KeepAlive(b)
return n, err
}
func (f *win32File) SetReadDeadline(deadline time.Time) error {
return f.readDeadline.set(deadline)
}
func (f *win32File) SetWriteDeadline(deadline time.Time) error {
return f.writeDeadline.set(deadline)
}
func (f *win32File) Flush() error {
return syscall.FlushFileBuffers(f.handle)
}
func (f *win32File) Fd() uintptr {
return uintptr(f.handle)
}
func (d *deadlineHandler) set(deadline time.Time) error {
d.setLock.Lock()
defer d.setLock.Unlock()
if d.timer != nil {
if !d.timer.Stop() {
<-d.channel
}
d.timer = nil
}
d.timedout.setFalse()
select {
case <-d.channel:
d.channelLock.Lock()
d.channel = make(chan struct{})
d.channelLock.Unlock()
default:
}
if deadline.IsZero() {
return nil
}
timeoutIO := func() {
d.timedout.setTrue()
close(d.channel)
}
now := time.Now()
duration := deadline.Sub(now)
if deadline.After(now) {
// Deadline is in the future, set a timer to wait
d.timer = time.AfterFunc(duration, timeoutIO)
} else {
// Deadline is in the past. Cancel all pending IO now.
timeoutIO()
}
return nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/fileinfo.go
================================================
//go:build windows
// +build windows
package winio
import (
"os"
"runtime"
"unsafe"
"golang.org/x/sys/windows"
)
// FileBasicInfo contains file access time and file attributes information.
type FileBasicInfo struct {
CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
FileAttributes uint32
_ uint32 // padding
}
// GetFileBasicInfo retrieves times and attributes for a file.
func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
bi := &FileBasicInfo{}
if err := windows.GetFileInformationByHandleEx(
windows.Handle(f.Fd()),
windows.FileBasicInfo,
(*byte)(unsafe.Pointer(bi)),
uint32(unsafe.Sizeof(*bi)),
); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return bi, nil
}
// SetFileBasicInfo sets times and attributes for a file.
func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
if err := windows.SetFileInformationByHandle(
windows.Handle(f.Fd()),
windows.FileBasicInfo,
(*byte)(unsafe.Pointer(bi)),
uint32(unsafe.Sizeof(*bi)),
); err != nil {
return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return nil
}
// FileStandardInfo contains extended information for the file.
// FILE_STANDARD_INFO in WinBase.h
// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
type FileStandardInfo struct {
AllocationSize, EndOfFile int64
NumberOfLinks uint32
DeletePending, Directory bool
}
// GetFileStandardInfo retrieves ended information for the file.
func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
si := &FileStandardInfo{}
if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()),
windows.FileStandardInfo,
(*byte)(unsafe.Pointer(si)),
uint32(unsafe.Sizeof(*si))); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return si, nil
}
// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
// unique on a system.
type FileIDInfo struct {
VolumeSerialNumber uint64
FileID [16]byte
}
// GetFileID retrieves the unique (volume, file ID) pair for a file.
func GetFileID(f *os.File) (*FileIDInfo, error) {
fileID := &FileIDInfo{}
if err := windows.GetFileInformationByHandleEx(
windows.Handle(f.Fd()),
windows.FileIdInfo,
(*byte)(unsafe.Pointer(fileID)),
uint32(unsafe.Sizeof(*fileID)),
); err != nil {
return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
}
runtime.KeepAlive(f)
return fileID, nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/hvsock.go
================================================
//go:build windows
// +build windows
package winio
import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
"github.com/Microsoft/go-winio/internal/socket"
"github.com/Microsoft/go-winio/pkg/guid"
)
const afHVSock = 34 // AF_HYPERV
// Well known Service and VM IDs
// https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/make-integration-service#vmid-wildcards
// HvsockGUIDWildcard is the wildcard VmId for accepting connections from all partitions.
func HvsockGUIDWildcard() guid.GUID { // 00000000-0000-0000-0000-000000000000
return guid.GUID{}
}
// HvsockGUIDBroadcast is the wildcard VmId for broadcasting sends to all partitions.
func HvsockGUIDBroadcast() guid.GUID { // ffffffff-ffff-ffff-ffff-ffffffffffff
return guid.GUID{
Data1: 0xffffffff,
Data2: 0xffff,
Data3: 0xffff,
Data4: [8]uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
}
}
// HvsockGUIDLoopback is the Loopback VmId for accepting connections to the same partition as the connector.
func HvsockGUIDLoopback() guid.GUID { // e0e16197-dd56-4a10-9195-5ee7a155a838
return guid.GUID{
Data1: 0xe0e16197,
Data2: 0xdd56,
Data3: 0x4a10,
Data4: [8]uint8{0x91, 0x95, 0x5e, 0xe7, 0xa1, 0x55, 0xa8, 0x38},
}
}
// HvsockGUIDSiloHost is the address of a silo's host partition:
// - The silo host of a hosted silo is the utility VM.
// - The silo host of a silo on a physical host is the physical host.
func HvsockGUIDSiloHost() guid.GUID { // 36bd0c5c-7276-4223-88ba-7d03b654c568
return guid.GUID{
Data1: 0x36bd0c5c,
Data2: 0x7276,
Data3: 0x4223,
Data4: [8]byte{0x88, 0xba, 0x7d, 0x03, 0xb6, 0x54, 0xc5, 0x68},
}
}
// HvsockGUIDChildren is the wildcard VmId for accepting connections from the connector's child partitions.
func HvsockGUIDChildren() guid.GUID { // 90db8b89-0d35-4f79-8ce9-49ea0ac8b7cd
return guid.GUID{
Data1: 0x90db8b89,
Data2: 0xd35,
Data3: 0x4f79,
Data4: [8]uint8{0x8c, 0xe9, 0x49, 0xea, 0xa, 0xc8, 0xb7, 0xcd},
}
}
// HvsockGUIDParent is the wildcard VmId for accepting connections from the connector's parent partition.
// Listening on this VmId accepts connection from:
// - Inside silos: silo host partition.
// - Inside hosted silo: host of the VM.
// - Inside VM: VM host.
// - Physical host: Not supported.
func HvsockGUIDParent() guid.GUID { // a42e7cda-d03f-480c-9cc2-a4de20abb878
return guid.GUID{
Data1: 0xa42e7cda,
Data2: 0xd03f,
Data3: 0x480c,
Data4: [8]uint8{0x9c, 0xc2, 0xa4, 0xde, 0x20, 0xab, 0xb8, 0x78},
}
}
// hvsockVsockServiceTemplate is the Service GUID used for the VSOCK protocol.
func hvsockVsockServiceTemplate() guid.GUID { // 00000000-facb-11e6-bd58-64006a7986d3
return guid.GUID{
Data2: 0xfacb,
Data3: 0x11e6,
Data4: [8]uint8{0xbd, 0x58, 0x64, 0x00, 0x6a, 0x79, 0x86, 0xd3},
}
}
// An HvsockAddr is an address for a AF_HYPERV socket.
type HvsockAddr struct {
VMID guid.GUID
ServiceID guid.GUID
}
type rawHvsockAddr struct {
Family uint16
_ uint16
VMID guid.GUID
ServiceID guid.GUID
}
var _ socket.RawSockaddr = &rawHvsockAddr{}
// Network returns the address's network name, "hvsock".
func (*HvsockAddr) Network() string {
return "hvsock"
}
func (addr *HvsockAddr) String() string {
return fmt.Sprintf("%s:%s", &addr.VMID, &addr.ServiceID)
}
// VsockServiceID returns an hvsock service ID corresponding to the specified AF_VSOCK port.
func VsockServiceID(port uint32) guid.GUID {
g := hvsockVsockServiceTemplate() // make a copy
g.Data1 = port
return g
}
func (addr *HvsockAddr) raw() rawHvsockAddr {
return rawHvsockAddr{
Family: afHVSock,
VMID: addr.VMID,
ServiceID: addr.ServiceID,
}
}
func (addr *HvsockAddr) fromRaw(raw *rawHvsockAddr) {
addr.VMID = raw.VMID
addr.ServiceID = raw.ServiceID
}
// Sockaddr returns a pointer to and the size of this struct.
//
// Implements the [socket.RawSockaddr] interface, and allows use in
// [socket.Bind] and [socket.ConnectEx].
func (r *rawHvsockAddr) Sockaddr() (unsafe.Pointer, int32, error) {
return unsafe.Pointer(r), int32(unsafe.Sizeof(rawHvsockAddr{})), nil
}
// Sockaddr interface allows use with `sockets.Bind()` and `.ConnectEx()`.
func (r *rawHvsockAddr) FromBytes(b []byte) error {
n := int(unsafe.Sizeof(rawHvsockAddr{}))
if len(b) < n {
return fmt.Errorf("got %d, want %d: %w", len(b), n, socket.ErrBufferSize)
}
copy(unsafe.Slice((*byte)(unsafe.Pointer(r)), n), b[:n])
if r.Family != afHVSock {
return fmt.Errorf("got %d, want %d: %w", r.Family, afHVSock, socket.ErrAddrFamily)
}
return nil
}
// HvsockListener is a socket listener for the AF_HYPERV address family.
type HvsockListener struct {
sock *win32File
addr HvsockAddr
}
var _ net.Listener = &HvsockListener{}
// HvsockConn is a connected socket of the AF_HYPERV address family.
type HvsockConn struct {
sock *win32File
local, remote HvsockAddr
}
var _ net.Conn = &HvsockConn{}
func newHVSocket() (*win32File, error) {
fd, err := syscall.Socket(afHVSock, syscall.SOCK_STREAM, 1)
if err != nil {
return nil, os.NewSyscallError("socket", err)
}
f, err := makeWin32File(fd)
if err != nil {
syscall.Close(fd)
return nil, err
}
f.socket = true
return f, nil
}
// ListenHvsock listens for connections on the specified hvsock address.
func ListenHvsock(addr *HvsockAddr) (_ *HvsockListener, err error) {
l := &HvsockListener{addr: *addr}
sock, err := newHVSocket()
if err != nil {
return nil, l.opErr("listen", err)
}
sa := addr.raw()
err = socket.Bind(windows.Handle(sock.handle), &sa)
if err != nil {
return nil, l.opErr("listen", os.NewSyscallError("socket", err))
}
err = syscall.Listen(sock.handle, 16)
if err != nil {
return nil, l.opErr("listen", os.NewSyscallError("listen", err))
}
return &HvsockListener{sock: sock, addr: *addr}, nil
}
func (l *HvsockListener) opErr(op string, err error) error {
return &net.OpError{Op: op, Net: "hvsock", Addr: &l.addr, Err: err}
}
// Addr returns the listener's network address.
func (l *HvsockListener) Addr() net.Addr {
return &l.addr
}
// Accept waits for the next connection and returns it.
func (l *HvsockListener) Accept() (_ net.Conn, err error) {
sock, err := newHVSocket()
if err != nil {
return nil, l.opErr("accept", err)
}
defer func() {
if sock != nil {
sock.Close()
}
}()
c, err := l.sock.prepareIO()
if err != nil {
return nil, l.opErr("accept", err)
}
defer l.sock.wg.Done()
// AcceptEx, per documentation, requires an extra 16 bytes per address.
//
// https://docs.microsoft.com/en-us/windows/win32/api/mswsock/nf-mswsock-acceptex
const addrlen = uint32(16 + unsafe.Sizeof(rawHvsockAddr{}))
var addrbuf [addrlen * 2]byte
var bytes uint32
err = syscall.AcceptEx(l.sock.handle, sock.handle, &addrbuf[0], 0 /* rxdatalen */, addrlen, addrlen, &bytes, &c.o)
if _, err = l.sock.asyncIO(c, nil, bytes, err); err != nil {
return nil, l.opErr("accept", os.NewSyscallError("acceptex", err))
}
conn := &HvsockConn{
sock: sock,
}
// The local address returned in the AcceptEx buffer is the same as the Listener socket's
// address. However, the service GUID reported by GetSockName is different from the Listeners
// socket, and is sometimes the same as the local address of the socket that dialed the
// address, with the service GUID.Data1 incremented, but othertimes is different.
// todo: does the local address matter? is the listener's address or the actual address appropriate?
conn.local.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[0])))
conn.remote.fromRaw((*rawHvsockAddr)(unsafe.Pointer(&addrbuf[addrlen])))
// initialize the accepted socket and update its properties with those of the listening socket
if err = windows.Setsockopt(windows.Handle(sock.handle),
windows.SOL_SOCKET, windows.SO_UPDATE_ACCEPT_CONTEXT,
(*byte)(unsafe.Pointer(&l.sock.handle)), int32(unsafe.Sizeof(l.sock.handle))); err != nil {
return nil, conn.opErr("accept", os.NewSyscallError("setsockopt", err))
}
sock = nil
return conn, nil
}
// Close closes the listener, causing any pending Accept calls to fail.
func (l *HvsockListener) Close() error {
return l.sock.Close()
}
// HvsockDialer configures and dials a Hyper-V Socket (ie, [HvsockConn]).
type HvsockDialer struct {
// Deadline is the time the Dial operation must connect before erroring.
Deadline time.Time
// Retries is the number of additional connects to try if the connection times out, is refused,
// or the host is unreachable
Retries uint
// RetryWait is the time to wait after a connection error to retry
RetryWait time.Duration
rt *time.Timer // redial wait timer
}
// Dial the Hyper-V socket at addr.
//
// See [HvsockDialer.Dial] for more information.
func Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
return (&HvsockDialer{}).Dial(ctx, addr)
}
// Dial attempts to connect to the Hyper-V socket at addr, and returns a connection if successful.
// Will attempt (HvsockDialer).Retries if dialing fails, waiting (HvsockDialer).RetryWait between
// retries.
//
// Dialing can be cancelled either by providing (HvsockDialer).Deadline, or cancelling ctx.
func (d *HvsockDialer) Dial(ctx context.Context, addr *HvsockAddr) (conn *HvsockConn, err error) {
op := "dial"
// create the conn early to use opErr()
conn = &HvsockConn{
remote: *addr,
}
if !d.Deadline.IsZero() {
var cancel context.CancelFunc
ctx, cancel = context.WithDeadline(ctx, d.Deadline)
defer cancel()
}
// preemptive timeout/cancellation check
if err = ctx.Err(); err != nil {
return nil, conn.opErr(op, err)
}
sock, err := newHVSocket()
if err != nil {
return nil, conn.opErr(op, err)
}
defer func() {
if sock != nil {
sock.Close()
}
}()
sa := addr.raw()
err = socket.Bind(windows.Handle(sock.handle), &sa)
if err != nil {
return nil, conn.opErr(op, os.NewSyscallError("bind", err))
}
c, err := sock.prepareIO()
if err != nil {
return nil, conn.opErr(op, err)
}
defer sock.wg.Done()
var bytes uint32
for i := uint(0); i <= d.Retries; i++ {
err = socket.ConnectEx(
windows.Handle(sock.handle),
&sa,
nil, // sendBuf
0, // sendDataLen
&bytes,
(*windows.Overlapped)(unsafe.Pointer(&c.o)))
_, err = sock.asyncIO(c, nil, bytes, err)
if i < d.Retries && canRedial(err) {
if err = d.redialWait(ctx); err == nil {
continue
}
}
break
}
if err != nil {
return nil, conn.opErr(op, os.NewSyscallError("connectex", err))
}
// update the connection properties, so shutdown can be used
if err = windows.Setsockopt(
windows.Handle(sock.handle),
windows.SOL_SOCKET,
windows.SO_UPDATE_CONNECT_CONTEXT,
nil, // optvalue
0, // optlen
); err != nil {
return nil, conn.opErr(op, os.NewSyscallError("setsockopt", err))
}
// get the local name
var sal rawHvsockAddr
err = socket.GetSockName(windows.Handle(sock.handle), &sal)
if err != nil {
return nil, conn.opErr(op, os.NewSyscallError("getsockname", err))
}
conn.local.fromRaw(&sal)
// one last check for timeout, since asyncIO doesn't check the context
if err = ctx.Err(); err != nil {
return nil, conn.opErr(op, err)
}
conn.sock = sock
sock = nil
return conn, nil
}
// redialWait waits before attempting to redial, resetting the timer as appropriate.
func (d *HvsockDialer) redialWait(ctx context.Context) (err error) {
if d.RetryWait == 0 {
return nil
}
if d.rt == nil {
d.rt = time.NewTimer(d.RetryWait)
} else {
// should already be stopped and drained
d.rt.Reset(d.RetryWait)
}
select {
case <-ctx.Done():
case <-d.rt.C:
return nil
}
// stop and drain the timer
if !d.rt.Stop() {
<-d.rt.C
}
return ctx.Err()
}
// assumes error is a plain, unwrapped syscall.Errno provided by direct syscall.
func canRedial(err error) bool {
//nolint:errorlint // guaranteed to be an Errno
switch err {
case windows.WSAECONNREFUSED, windows.WSAENETUNREACH, windows.WSAETIMEDOUT,
windows.ERROR_CONNECTION_REFUSED, windows.ERROR_CONNECTION_UNAVAIL:
return true
default:
return false
}
}
func (conn *HvsockConn) opErr(op string, err error) error {
// translate from "file closed" to "socket closed"
if errors.Is(err, ErrFileClosed) {
err = socket.ErrSocketClosed
}
return &net.OpError{Op: op, Net: "hvsock", Source: &conn.local, Addr: &conn.remote, Err: err}
}
func (conn *HvsockConn) Read(b []byte) (int, error) {
c, err := conn.sock.prepareIO()
if err != nil {
return 0, conn.opErr("read", err)
}
defer conn.sock.wg.Done()
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
var flags, bytes uint32
err = syscall.WSARecv(conn.sock.handle, &buf, 1, &bytes, &flags, &c.o, nil)
n, err := conn.sock.asyncIO(c, &conn.sock.readDeadline, bytes, err)
if err != nil {
var eno windows.Errno
if errors.As(err, &eno) {
err = os.NewSyscallError("wsarecv", eno)
}
return 0, conn.opErr("read", err)
} else if n == 0 {
err = io.EOF
}
return n, err
}
func (conn *HvsockConn) Write(b []byte) (int, error) {
t := 0
for len(b) != 0 {
n, err := conn.write(b)
if err != nil {
return t + n, err
}
t += n
b = b[n:]
}
return t, nil
}
func (conn *HvsockConn) write(b []byte) (int, error) {
c, err := conn.sock.prepareIO()
if err != nil {
return 0, conn.opErr("write", err)
}
defer conn.sock.wg.Done()
buf := syscall.WSABuf{Buf: &b[0], Len: uint32(len(b))}
var bytes uint32
err = syscall.WSASend(conn.sock.handle, &buf, 1, &bytes, 0, &c.o, nil)
n, err := conn.sock.asyncIO(c, &conn.sock.writeDeadline, bytes, err)
if err != nil {
var eno windows.Errno
if errors.As(err, &eno) {
err = os.NewSyscallError("wsasend", eno)
}
return 0, conn.opErr("write", err)
}
return n, err
}
// Close closes the socket connection, failing any pending read or write calls.
func (conn *HvsockConn) Close() error {
return conn.sock.Close()
}
func (conn *HvsockConn) IsClosed() bool {
return conn.sock.IsClosed()
}
// shutdown disables sending or receiving on a socket.
func (conn *HvsockConn) shutdown(how int) error {
if conn.IsClosed() {
return socket.ErrSocketClosed
}
err := syscall.Shutdown(conn.sock.handle, how)
if err != nil {
// If the connection was closed, shutdowns fail with "not connected"
if errors.Is(err, windows.WSAENOTCONN) ||
errors.Is(err, windows.WSAESHUTDOWN) {
err = socket.ErrSocketClosed
}
return os.NewSyscallError("shutdown", err)
}
return nil
}
// CloseRead shuts down the read end of the socket, preventing future read operations.
func (conn *HvsockConn) CloseRead() error {
err := conn.shutdown(syscall.SHUT_RD)
if err != nil {
return conn.opErr("closeread", err)
}
return nil
}
// CloseWrite shuts down the write end of the socket, preventing future write operations and
// notifying the other endpoint that no more data will be written.
func (conn *HvsockConn) CloseWrite() error {
err := conn.shutdown(syscall.SHUT_WR)
if err != nil {
return conn.opErr("closewrite", err)
}
return nil
}
// LocalAddr returns the local address of the connection.
func (conn *HvsockConn) LocalAddr() net.Addr {
return &conn.local
}
// RemoteAddr returns the remote address of the connection.
func (conn *HvsockConn) RemoteAddr() net.Addr {
return &conn.remote
}
// SetDeadline implements the net.Conn SetDeadline method.
func (conn *HvsockConn) SetDeadline(t time.Time) error {
// todo: implement `SetDeadline` for `win32File`
if err := conn.SetReadDeadline(t); err != nil {
return fmt.Errorf("set read deadline: %w", err)
}
if err := conn.SetWriteDeadline(t); err != nil {
return fmt.Errorf("set write deadline: %w", err)
}
return nil
}
// SetReadDeadline implements the net.Conn SetReadDeadline method.
func (conn *HvsockConn) SetReadDeadline(t time.Time) error {
return conn.sock.SetReadDeadline(t)
}
// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
func (conn *HvsockConn) SetWriteDeadline(t time.Time) error {
return conn.sock.SetWriteDeadline(t)
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/fs/doc.go
================================================
// This package contains Win32 filesystem functionality.
package fs
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/fs/fs.go
================================================
//go:build windows
package fs
import (
"golang.org/x/sys/windows"
"github.com/Microsoft/go-winio/internal/stringbuffer"
)
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go fs.go
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
//sys CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) [failretval==windows.InvalidHandle] = CreateFileW
const NullHandle windows.Handle = 0
// AccessMask defines standard, specific, and generic rights.
//
// Bitmask:
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// +---------------+---------------+-------------------------------+
// |G|G|G|G|Resvd|A| StandardRights| SpecificRights |
// |R|W|E|A| |S| | |
// +-+-------------+---------------+-------------------------------+
//
// GR Generic Read
// GW Generic Write
// GE Generic Exectue
// GA Generic All
// Resvd Reserved
// AS Access Security System
//
// https://learn.microsoft.com/en-us/windows/win32/secauthz/access-mask
//
// https://learn.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
//
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-access-rights-constants
type AccessMask = windows.ACCESS_MASK
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const (
// Not actually any.
//
// For CreateFile: "query certain metadata such as file, directory, or device attributes without accessing that file or device"
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew#parameters
FILE_ANY_ACCESS AccessMask = 0
// Specific Object Access
// from ntioapi.h
FILE_READ_DATA AccessMask = (0x0001) // file & pipe
FILE_LIST_DIRECTORY AccessMask = (0x0001) // directory
FILE_WRITE_DATA AccessMask = (0x0002) // file & pipe
FILE_ADD_FILE AccessMask = (0x0002) // directory
FILE_APPEND_DATA AccessMask = (0x0004) // file
FILE_ADD_SUBDIRECTORY AccessMask = (0x0004) // directory
FILE_CREATE_PIPE_INSTANCE AccessMask = (0x0004) // named pipe
FILE_READ_EA AccessMask = (0x0008) // file & directory
FILE_READ_PROPERTIES AccessMask = FILE_READ_EA
FILE_WRITE_EA AccessMask = (0x0010) // file & directory
FILE_WRITE_PROPERTIES AccessMask = FILE_WRITE_EA
FILE_EXECUTE AccessMask = (0x0020) // file
FILE_TRAVERSE AccessMask = (0x0020) // directory
FILE_DELETE_CHILD AccessMask = (0x0040) // directory
FILE_READ_ATTRIBUTES AccessMask = (0x0080) // all
FILE_WRITE_ATTRIBUTES AccessMask = (0x0100) // all
FILE_ALL_ACCESS AccessMask = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF)
FILE_GENERIC_READ AccessMask = (STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE)
FILE_GENERIC_WRITE AccessMask = (STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE)
FILE_GENERIC_EXECUTE AccessMask = (STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE)
SPECIFIC_RIGHTS_ALL AccessMask = 0x0000FFFF
// Standard Access
// from ntseapi.h
DELETE AccessMask = 0x0001_0000
READ_CONTROL AccessMask = 0x0002_0000
WRITE_DAC AccessMask = 0x0004_0000
WRITE_OWNER AccessMask = 0x0008_0000
SYNCHRONIZE AccessMask = 0x0010_0000
STANDARD_RIGHTS_REQUIRED AccessMask = 0x000F_0000
STANDARD_RIGHTS_READ AccessMask = READ_CONTROL
STANDARD_RIGHTS_WRITE AccessMask = READ_CONTROL
STANDARD_RIGHTS_EXECUTE AccessMask = READ_CONTROL
STANDARD_RIGHTS_ALL AccessMask = 0x001F_0000
)
type FileShareMode uint32
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const (
FILE_SHARE_NONE FileShareMode = 0x00
FILE_SHARE_READ FileShareMode = 0x01
FILE_SHARE_WRITE FileShareMode = 0x02
FILE_SHARE_DELETE FileShareMode = 0x04
FILE_SHARE_VALID_FLAGS FileShareMode = 0x07
)
type FileCreationDisposition uint32
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const (
// from winbase.h
CREATE_NEW FileCreationDisposition = 0x01
CREATE_ALWAYS FileCreationDisposition = 0x02
OPEN_EXISTING FileCreationDisposition = 0x03
OPEN_ALWAYS FileCreationDisposition = 0x04
TRUNCATE_EXISTING FileCreationDisposition = 0x05
)
// CreateFile and co. take flags or attributes together as one parameter.
// Define alias until we can use generics to allow both
// https://learn.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants
type FileFlagOrAttribute uint32
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const ( // from winnt.h
FILE_FLAG_WRITE_THROUGH FileFlagOrAttribute = 0x8000_0000
FILE_FLAG_OVERLAPPED FileFlagOrAttribute = 0x4000_0000
FILE_FLAG_NO_BUFFERING FileFlagOrAttribute = 0x2000_0000
FILE_FLAG_RANDOM_ACCESS FileFlagOrAttribute = 0x1000_0000
FILE_FLAG_SEQUENTIAL_SCAN FileFlagOrAttribute = 0x0800_0000
FILE_FLAG_DELETE_ON_CLOSE FileFlagOrAttribute = 0x0400_0000
FILE_FLAG_BACKUP_SEMANTICS FileFlagOrAttribute = 0x0200_0000
FILE_FLAG_POSIX_SEMANTICS FileFlagOrAttribute = 0x0100_0000
FILE_FLAG_OPEN_REPARSE_POINT FileFlagOrAttribute = 0x0020_0000
FILE_FLAG_OPEN_NO_RECALL FileFlagOrAttribute = 0x0010_0000
FILE_FLAG_FIRST_PIPE_INSTANCE FileFlagOrAttribute = 0x0008_0000
)
type FileSQSFlag = FileFlagOrAttribute
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const ( // from winbase.h
SECURITY_ANONYMOUS FileSQSFlag = FileSQSFlag(SecurityAnonymous << 16)
SECURITY_IDENTIFICATION FileSQSFlag = FileSQSFlag(SecurityIdentification << 16)
SECURITY_IMPERSONATION FileSQSFlag = FileSQSFlag(SecurityImpersonation << 16)
SECURITY_DELEGATION FileSQSFlag = FileSQSFlag(SecurityDelegation << 16)
SECURITY_SQOS_PRESENT FileSQSFlag = 0x00100000
SECURITY_VALID_SQOS_FLAGS FileSQSFlag = 0x001F0000
)
// GetFinalPathNameByHandle flags
//
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew#parameters
type GetFinalPathFlag uint32
//nolint:revive // SNAKE_CASE is not idiomatic in Go, but aligned with Win32 API.
const (
GetFinalPathDefaultFlag GetFinalPathFlag = 0x0
FILE_NAME_NORMALIZED GetFinalPathFlag = 0x0
FILE_NAME_OPENED GetFinalPathFlag = 0x8
VOLUME_NAME_DOS GetFinalPathFlag = 0x0
VOLUME_NAME_GUID GetFinalPathFlag = 0x1
VOLUME_NAME_NT GetFinalPathFlag = 0x2
VOLUME_NAME_NONE GetFinalPathFlag = 0x4
)
// getFinalPathNameByHandle facilitates calling the Windows API GetFinalPathNameByHandle
// with the given handle and flags. It transparently takes care of creating a buffer of the
// correct size for the call.
//
// https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfinalpathnamebyhandlew
func GetFinalPathNameByHandle(h windows.Handle, flags GetFinalPathFlag) (string, error) {
b := stringbuffer.NewWString()
//TODO: can loop infinitely if Win32 keeps returning the same (or a larger) n?
for {
n, err := windows.GetFinalPathNameByHandle(h, b.Pointer(), b.Cap(), uint32(flags))
if err != nil {
return "", err
}
// If the buffer wasn't large enough, n will be the total size needed (including null terminator).
// Resize and try again.
if n > b.Cap() {
b.ResizeTo(n)
continue
}
// If the buffer is large enough, n will be the size not including the null terminator.
// Convert to a Go string and return.
return b.String(), nil
}
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/fs/security.go
================================================
package fs
// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ne-winnt-security_impersonation_level
type SecurityImpersonationLevel int32 // C default enums underlying type is `int`, which is Go `int32`
// Impersonation levels
const (
SecurityAnonymous SecurityImpersonationLevel = 0
SecurityIdentification SecurityImpersonationLevel = 1
SecurityImpersonation SecurityImpersonationLevel = 2
SecurityDelegation SecurityImpersonationLevel = 3
)
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/fs/zsyscall_windows.go
================================================
//go:build windows
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
package fs
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procCreateFileW = modkernel32.NewProc("CreateFileW")
)
func CreateFile(name string, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(name)
if err != nil {
return
}
return _CreateFile(_p0, access, mode, sa, createmode, attrs, templatefile)
}
func _CreateFile(name *uint16, access AccessMask, mode FileShareMode, sa *syscall.SecurityAttributes, createmode FileCreationDisposition, attrs FileFlagOrAttribute, templatefile windows.Handle) (handle windows.Handle, err error) {
r0, _, e1 := syscall.Syscall9(procCreateFileW.Addr(), 7, uintptr(unsafe.Pointer(name)), uintptr(access), uintptr(mode), uintptr(unsafe.Pointer(sa)), uintptr(createmode), uintptr(attrs), uintptr(templatefile), 0, 0)
handle = windows.Handle(r0)
if handle == windows.InvalidHandle {
err = errnoErr(e1)
}
return
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/socket/rawaddr.go
================================================
package socket
import (
"unsafe"
)
// RawSockaddr allows structs to be used with [Bind] and [ConnectEx]. The
// struct must meet the Win32 sockaddr requirements specified here:
// https://docs.microsoft.com/en-us/windows/win32/winsock/sockaddr-2
//
// Specifically, the struct size must be least larger than an int16 (unsigned short)
// for the address family.
type RawSockaddr interface {
// Sockaddr returns a pointer to the RawSockaddr and its struct size, allowing
// for the RawSockaddr's data to be overwritten by syscalls (if necessary).
//
// It is the callers responsibility to validate that the values are valid; invalid
// pointers or size can cause a panic.
Sockaddr() (unsafe.Pointer, int32, error)
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/socket/socket.go
================================================
//go:build windows
package socket
import (
"errors"
"fmt"
"net"
"sync"
"syscall"
"unsafe"
"github.com/Microsoft/go-winio/pkg/guid"
"golang.org/x/sys/windows"
)
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go socket.go
//sys getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getsockname
//sys getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) [failretval==socketError] = ws2_32.getpeername
//sys bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) [failretval==socketError] = ws2_32.bind
const socketError = uintptr(^uint32(0))
var (
// todo(helsaawy): create custom error types to store the desired vs actual size and addr family?
ErrBufferSize = errors.New("buffer size")
ErrAddrFamily = errors.New("address family")
ErrInvalidPointer = errors.New("invalid pointer")
ErrSocketClosed = fmt.Errorf("socket closed: %w", net.ErrClosed)
)
// todo(helsaawy): replace these with generics, ie: GetSockName[S RawSockaddr](s windows.Handle) (S, error)
// GetSockName writes the local address of socket s to the [RawSockaddr] rsa.
// If rsa is not large enough, the [windows.WSAEFAULT] is returned.
func GetSockName(s windows.Handle, rsa RawSockaddr) error {
ptr, l, err := rsa.Sockaddr()
if err != nil {
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
}
// although getsockname returns WSAEFAULT if the buffer is too small, it does not set
// &l to the correct size, so--apart from doubling the buffer repeatedly--there is no remedy
return getsockname(s, ptr, &l)
}
// GetPeerName returns the remote address the socket is connected to.
//
// See [GetSockName] for more information.
func GetPeerName(s windows.Handle, rsa RawSockaddr) error {
ptr, l, err := rsa.Sockaddr()
if err != nil {
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
}
return getpeername(s, ptr, &l)
}
func Bind(s windows.Handle, rsa RawSockaddr) (err error) {
ptr, l, err := rsa.Sockaddr()
if err != nil {
return fmt.Errorf("could not retrieve socket pointer and size: %w", err)
}
return bind(s, ptr, l)
}
// "golang.org/x/sys/windows".ConnectEx and .Bind only accept internal implementations of the
// their sockaddr interface, so they cannot be used with HvsockAddr
// Replicate functionality here from
// https://cs.opensource.google/go/x/sys/+/master:windows/syscall_windows.go
// The function pointers to `AcceptEx`, `ConnectEx` and `GetAcceptExSockaddrs` must be loaded at
// runtime via a WSAIoctl call:
// https://docs.microsoft.com/en-us/windows/win32/api/Mswsock/nc-mswsock-lpfn_connectex#remarks
type runtimeFunc struct {
id guid.GUID
once sync.Once
addr uintptr
err error
}
func (f *runtimeFunc) Load() error {
f.once.Do(func() {
var s windows.Handle
s, f.err = windows.Socket(windows.AF_INET, windows.SOCK_STREAM, windows.IPPROTO_TCP)
if f.err != nil {
return
}
defer windows.CloseHandle(s) //nolint:errcheck
var n uint32
f.err = windows.WSAIoctl(s,
windows.SIO_GET_EXTENSION_FUNCTION_POINTER,
(*byte)(unsafe.Pointer(&f.id)),
uint32(unsafe.Sizeof(f.id)),
(*byte)(unsafe.Pointer(&f.addr)),
uint32(unsafe.Sizeof(f.addr)),
&n,
nil, // overlapped
0, // completionRoutine
)
})
return f.err
}
var (
// todo: add `AcceptEx` and `GetAcceptExSockaddrs`
WSAID_CONNECTEX = guid.GUID{ //revive:disable-line:var-naming ALL_CAPS
Data1: 0x25a207b9,
Data2: 0xddf3,
Data3: 0x4660,
Data4: [8]byte{0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e},
}
connectExFunc = runtimeFunc{id: WSAID_CONNECTEX}
)
func ConnectEx(
fd windows.Handle,
rsa RawSockaddr,
sendBuf *byte,
sendDataLen uint32,
bytesSent *uint32,
overlapped *windows.Overlapped,
) error {
if err := connectExFunc.Load(); err != nil {
return fmt.Errorf("failed to load ConnectEx function pointer: %w", err)
}
ptr, n, err := rsa.Sockaddr()
if err != nil {
return err
}
return connectEx(fd, ptr, n, sendBuf, sendDataLen, bytesSent, overlapped)
}
// BOOL LpfnConnectex(
// [in] SOCKET s,
// [in] const sockaddr *name,
// [in] int namelen,
// [in, optional] PVOID lpSendBuffer,
// [in] DWORD dwSendDataLength,
// [out] LPDWORD lpdwBytesSent,
// [in] LPOVERLAPPED lpOverlapped
// )
func connectEx(
s windows.Handle,
name unsafe.Pointer,
namelen int32,
sendBuf *byte,
sendDataLen uint32,
bytesSent *uint32,
overlapped *windows.Overlapped,
) (err error) {
// todo: after upgrading to 1.18, switch from syscall.Syscall9 to syscall.SyscallN
r1, _, e1 := syscall.Syscall9(connectExFunc.addr,
7,
uintptr(s),
uintptr(name),
uintptr(namelen),
uintptr(unsafe.Pointer(sendBuf)),
uintptr(sendDataLen),
uintptr(unsafe.Pointer(bytesSent)),
uintptr(unsafe.Pointer(overlapped)),
0,
0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return err
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/socket/zsyscall_windows.go
================================================
//go:build windows
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
package socket
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
procbind = modws2_32.NewProc("bind")
procgetpeername = modws2_32.NewProc("getpeername")
procgetsockname = modws2_32.NewProc("getsockname")
)
func bind(s windows.Handle, name unsafe.Pointer, namelen int32) (err error) {
r1, _, e1 := syscall.Syscall(procbind.Addr(), 3, uintptr(s), uintptr(name), uintptr(namelen))
if r1 == socketError {
err = errnoErr(e1)
}
return
}
func getpeername(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
r1, _, e1 := syscall.Syscall(procgetpeername.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
if r1 == socketError {
err = errnoErr(e1)
}
return
}
func getsockname(s windows.Handle, name unsafe.Pointer, namelen *int32) (err error) {
r1, _, e1 := syscall.Syscall(procgetsockname.Addr(), 3, uintptr(s), uintptr(name), uintptr(unsafe.Pointer(namelen)))
if r1 == socketError {
err = errnoErr(e1)
}
return
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/internal/stringbuffer/wstring.go
================================================
package stringbuffer
import (
"sync"
"unicode/utf16"
)
// TODO: worth exporting and using in mkwinsyscall?
// Uint16BufferSize is the buffer size in the pool, chosen somewhat arbitrarily to accommodate
// large path strings:
// MAX_PATH (260) + size of volume GUID prefix (49) + null terminator = 310.
const MinWStringCap = 310
// use *[]uint16 since []uint16 creates an extra allocation where the slice header
// is copied to heap and then referenced via pointer in the interface header that sync.Pool
// stores.
var pathPool = sync.Pool{ // if go1.18+ adds Pool[T], use that to store []uint16 directly
New: func() interface{} {
b := make([]uint16, MinWStringCap)
return &b
},
}
func newBuffer() []uint16 { return *(pathPool.Get().(*[]uint16)) }
// freeBuffer copies the slice header data, and puts a pointer to that in the pool.
// This avoids taking a pointer to the slice header in WString, which can be set to nil.
func freeBuffer(b []uint16) { pathPool.Put(&b) }
// WString is a wide string buffer ([]uint16) meant for storing UTF-16 encoded strings
// for interacting with Win32 APIs.
// Sizes are specified as uint32 and not int.
//
// It is not thread safe.
type WString struct {
// type-def allows casting to []uint16 directly, use struct to prevent that and allow adding fields in the future.
// raw buffer
b []uint16
}
// NewWString returns a [WString] allocated from a shared pool with an
// initial capacity of at least [MinWStringCap].
// Since the buffer may have been previously used, its contents are not guaranteed to be empty.
//
// The buffer should be freed via [WString.Free]
func NewWString() *WString {
return &WString{
b: newBuffer(),
}
}
func (b *WString) Free() {
if b.empty() {
return
}
freeBuffer(b.b)
b.b = nil
}
// ResizeTo grows the buffer to at least c and returns the new capacity, freeing the
// previous buffer back into pool.
func (b *WString) ResizeTo(c uint32) uint32 {
// allready sufficient (or n is 0)
if c <= b.Cap() {
return b.Cap()
}
if c <= MinWStringCap {
c = MinWStringCap
}
// allocate at-least double buffer size, as is done in [bytes.Buffer] and other places
if c <= 2*b.Cap() {
c = 2 * b.Cap()
}
b2 := make([]uint16, c)
if !b.empty() {
copy(b2, b.b)
freeBuffer(b.b)
}
b.b = b2
return c
}
// Buffer returns the underlying []uint16 buffer.
func (b *WString) Buffer() []uint16 {
if b.empty() {
return nil
}
return b.b
}
// Pointer returns a pointer to the first uint16 in the buffer.
// If the [WString.Free] has already been called, the pointer will be nil.
func (b *WString) Pointer() *uint16 {
if b.empty() {
return nil
}
return &b.b[0]
}
// String returns the returns the UTF-8 encoding of the UTF-16 string in the buffer.
//
// It assumes that the data is null-terminated.
func (b *WString) String() string {
// Using [windows.UTF16ToString] would require importing "golang.org/x/sys/windows"
// and would make this code Windows-only, which makes no sense.
// So copy UTF16ToString code into here.
// If other windows-specific code is added, switch to [windows.UTF16ToString]
s := b.b
for i, v := range s {
if v == 0 {
s = s[:i]
break
}
}
return string(utf16.Decode(s))
}
// Cap returns the underlying buffer capacity.
func (b *WString) Cap() uint32 {
if b.empty() {
return 0
}
return b.cap()
}
func (b *WString) cap() uint32 { return uint32(cap(b.b)) }
func (b *WString) empty() bool { return b == nil || b.cap() == 0 }
================================================
FILE: vendor/github.com/Microsoft/go-winio/pipe.go
================================================
//go:build windows
// +build windows
package winio
import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"runtime"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
"github.com/Microsoft/go-winio/internal/fs"
)
//sys connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) = ConnectNamedPipe
//sys createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) [failretval==syscall.InvalidHandle] = CreateNamedPipeW
//sys getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) = GetNamedPipeInfo
//sys getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) = GetNamedPipeHandleStateW
//sys localAlloc(uFlags uint32, length uint32) (ptr uintptr) = LocalAlloc
//sys ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) = ntdll.NtCreateNamedPipeFile
//sys rtlNtStatusToDosError(status ntStatus) (winerr error) = ntdll.RtlNtStatusToDosErrorNoTeb
//sys rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) = ntdll.RtlDosPathNameToNtPathName_U
//sys rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) = ntdll.RtlDefaultNpAcl
type ioStatusBlock struct {
Status, Information uintptr
}
type objectAttributes struct {
Length uintptr
RootDirectory uintptr
ObjectName *unicodeString
Attributes uintptr
SecurityDescriptor *securityDescriptor
SecurityQoS uintptr
}
type unicodeString struct {
Length uint16
MaximumLength uint16
Buffer uintptr
}
type securityDescriptor struct {
Revision byte
Sbz1 byte
Control uint16
Owner uintptr
Group uintptr
Sacl uintptr //revive:disable-line:var-naming SACL, not Sacl
Dacl uintptr //revive:disable-line:var-naming DACL, not Dacl
}
type ntStatus int32
func (status ntStatus) Err() error {
if status >= 0 {
return nil
}
return rtlNtStatusToDosError(status)
}
var (
// ErrPipeListenerClosed is returned for pipe operations on listeners that have been closed.
ErrPipeListenerClosed = net.ErrClosed
errPipeWriteClosed = errors.New("pipe has been closed for write")
)
type win32Pipe struct {
*win32File
path string
}
type win32MessageBytePipe struct {
win32Pipe
writeClosed bool
readEOF bool
}
type pipeAddress string
func (f *win32Pipe) LocalAddr() net.Addr {
return pipeAddress(f.path)
}
func (f *win32Pipe) RemoteAddr() net.Addr {
return pipeAddress(f.path)
}
func (f *win32Pipe) SetDeadline(t time.Time) error {
if err := f.SetReadDeadline(t); err != nil {
return err
}
return f.SetWriteDeadline(t)
}
// CloseWrite closes the write side of a message pipe in byte mode.
func (f *win32MessageBytePipe) CloseWrite() error {
if f.writeClosed {
return errPipeWriteClosed
}
err := f.win32File.Flush()
if err != nil {
return err
}
_, err = f.win32File.Write(nil)
if err != nil {
return err
}
f.writeClosed = true
return nil
}
// Write writes bytes to a message pipe in byte mode. Zero-byte writes are ignored, since
// they are used to implement CloseWrite().
func (f *win32MessageBytePipe) Write(b []byte) (int, error) {
if f.writeClosed {
return 0, errPipeWriteClosed
}
if len(b) == 0 {
return 0, nil
}
return f.win32File.Write(b)
}
// Read reads bytes from a message pipe in byte mode. A read of a zero-byte message on a message
// mode pipe will return io.EOF, as will all subsequent reads.
func (f *win32MessageBytePipe) Read(b []byte) (int, error) {
if f.readEOF {
return 0, io.EOF
}
n, err := f.win32File.Read(b)
if err == io.EOF { //nolint:errorlint
// If this was the result of a zero-byte read, then
// it is possible that the read was due to a zero-size
// message. Since we are simulating CloseWrite with a
// zero-byte message, ensure that all future Read() calls
// also return EOF.
f.readEOF = true
} else if err == syscall.ERROR_MORE_DATA { //nolint:errorlint // err is Errno
// ERROR_MORE_DATA indicates that the pipe's read mode is message mode
// and the message still has more bytes. Treat this as a success, since
// this package presents all named pipes as byte streams.
err = nil
}
return n, err
}
func (pipeAddress) Network() string {
return "pipe"
}
func (s pipeAddress) String() string {
return string(s)
}
// tryDialPipe attempts to dial the pipe at `path` until `ctx` cancellation or timeout.
func tryDialPipe(ctx context.Context, path *string, access fs.AccessMask) (syscall.Handle, error) {
for {
select {
case <-ctx.Done():
return syscall.Handle(0), ctx.Err()
default:
wh, err := fs.CreateFile(*path,
access,
0, // mode
nil, // security attributes
fs.OPEN_EXISTING,
fs.FILE_FLAG_OVERLAPPED|fs.SECURITY_SQOS_PRESENT|fs.SECURITY_ANONYMOUS,
0, // template file handle
)
h := syscall.Handle(wh)
if err == nil {
return h, nil
}
if err != windows.ERROR_PIPE_BUSY { //nolint:errorlint // err is Errno
return h, &os.PathError{Err: err, Op: "open", Path: *path}
}
// Wait 10 msec and try again. This is a rather simplistic
// view, as we always try each 10 milliseconds.
time.Sleep(10 * time.Millisecond)
}
}
}
// DialPipe connects to a named pipe by path, timing out if the connection
// takes longer than the specified duration. If timeout is nil, then we use
// a default timeout of 2 seconds. (We do not use WaitNamedPipe.)
func DialPipe(path string, timeout *time.Duration) (net.Conn, error) {
var absTimeout time.Time
if timeout != nil {
absTimeout = time.Now().Add(*timeout)
} else {
absTimeout = time.Now().Add(2 * time.Second)
}
ctx, cancel := context.WithDeadline(context.Background(), absTimeout)
defer cancel()
conn, err := DialPipeContext(ctx, path)
if errors.Is(err, context.DeadlineExceeded) {
return nil, ErrTimeout
}
return conn, err
}
// DialPipeContext attempts to connect to a named pipe by `path` until `ctx`
// cancellation or timeout.
func DialPipeContext(ctx context.Context, path string) (net.Conn, error) {
return DialPipeAccess(ctx, path, syscall.GENERIC_READ|syscall.GENERIC_WRITE)
}
// DialPipeAccess attempts to connect to a named pipe by `path` with `access` until `ctx`
// cancellation or timeout.
func DialPipeAccess(ctx context.Context, path string, access uint32) (net.Conn, error) {
var err error
var h syscall.Handle
h, err = tryDialPipe(ctx, &path, fs.AccessMask(access))
if err != nil {
return nil, err
}
var flags uint32
err = getNamedPipeInfo(h, &flags, nil, nil, nil)
if err != nil {
return nil, err
}
f, err := makeWin32File(h)
if err != nil {
syscall.Close(h)
return nil, err
}
// If the pipe is in message mode, return a message byte pipe, which
// supports CloseWrite().
if flags&windows.PIPE_TYPE_MESSAGE != 0 {
return &win32MessageBytePipe{
win32Pipe: win32Pipe{win32File: f, path: path},
}, nil
}
return &win32Pipe{win32File: f, path: path}, nil
}
type acceptResponse struct {
f *win32File
err error
}
type win32PipeListener struct {
firstHandle syscall.Handle
path string
config PipeConfig
acceptCh chan (chan acceptResponse)
closeCh chan int
doneCh chan int
}
func makeServerPipeHandle(path string, sd []byte, c *PipeConfig, first bool) (syscall.Handle, error) {
path16, err := syscall.UTF16FromString(path)
if err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
var oa objectAttributes
oa.Length = unsafe.Sizeof(oa)
var ntPath unicodeString
if err := rtlDosPathNameToNtPathName(&path16[0],
&ntPath,
0,
0,
).Err(); err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
defer localFree(ntPath.Buffer)
oa.ObjectName = &ntPath
oa.Attributes = windows.OBJ_CASE_INSENSITIVE
// The security descriptor is only needed for the first pipe.
if first {
if sd != nil {
l := uint32(len(sd))
sdb := localAlloc(0, l)
defer localFree(sdb)
copy((*[0xffff]byte)(unsafe.Pointer(sdb))[:], sd)
oa.SecurityDescriptor = (*securityDescriptor)(unsafe.Pointer(sdb))
} else {
// Construct the default named pipe security descriptor.
var dacl uintptr
if err := rtlDefaultNpAcl(&dacl).Err(); err != nil {
return 0, fmt.Errorf("getting default named pipe ACL: %w", err)
}
defer localFree(dacl)
sdb := &securityDescriptor{
Revision: 1,
Control: windows.SE_DACL_PRESENT,
Dacl: dacl,
}
oa.SecurityDescriptor = sdb
}
}
typ := uint32(windows.FILE_PIPE_REJECT_REMOTE_CLIENTS)
if c.MessageMode {
typ |= windows.FILE_PIPE_MESSAGE_TYPE
}
disposition := uint32(windows.FILE_OPEN)
access := uint32(syscall.GENERIC_READ | syscall.GENERIC_WRITE | syscall.SYNCHRONIZE)
if first {
disposition = windows.FILE_CREATE
// By not asking for read or write access, the named pipe file system
// will put this pipe into an initially disconnected state, blocking
// client connections until the next call with first == false.
access = syscall.SYNCHRONIZE
}
timeout := int64(-50 * 10000) // 50ms
var (
h syscall.Handle
iosb ioStatusBlock
)
err = ntCreateNamedPipeFile(&h,
access,
&oa,
&iosb,
syscall.FILE_SHARE_READ|syscall.FILE_SHARE_WRITE,
disposition,
0,
typ,
0,
0,
0xffffffff,
uint32(c.InputBufferSize),
uint32(c.OutputBufferSize),
&timeout).Err()
if err != nil {
return 0, &os.PathError{Op: "open", Path: path, Err: err}
}
runtime.KeepAlive(ntPath)
return h, nil
}
func (l *win32PipeListener) makeServerPipe() (*win32File, error) {
h, err := makeServerPipeHandle(l.path, nil, &l.config, false)
if err != nil {
return nil, err
}
f, err := makeWin32File(h)
if err != nil {
syscall.Close(h)
return nil, err
}
return f, nil
}
func (l *win32PipeListener) makeConnectedServerPipe() (*win32File, error) {
p, err := l.makeServerPipe()
if err != nil {
return nil, err
}
// Wait for the client to connect.
ch := make(chan error)
go func(p *win32File) {
ch <- connectPipe(p)
}(p)
select {
case err = <-ch:
if err != nil {
p.Close()
p = nil
}
case <-l.closeCh:
// Abort the connect request by closing the handle.
p.Close()
p = nil
err = <-ch
if err == nil || err == ErrFileClosed { //nolint:errorlint // err is Errno
err = ErrPipeListenerClosed
}
}
return p, err
}
func (l *win32PipeListener) listenerRoutine() {
closed := false
for !closed {
select {
case <-l.closeCh:
closed = true
case responseCh := <-l.acceptCh:
var (
p *win32File
err error
)
for {
p, err = l.makeConnectedServerPipe()
// If the connection was immediately closed by the client, try
// again.
if err != windows.ERROR_NO_DATA { //nolint:errorlint // err is Errno
break
}
}
responseCh <- acceptResponse{p, err}
closed = err == ErrPipeListenerClosed //nolint:errorlint // err is Errno
}
}
syscall.Close(l.firstHandle)
l.firstHandle = 0
// Notify Close() and Accept() callers that the handle has been closed.
close(l.doneCh)
}
// PipeConfig contain configuration for the pipe listener.
type PipeConfig struct {
// SecurityDescriptor contains a Windows security descriptor in SDDL format.
SecurityDescriptor string
// MessageMode determines whether the pipe is in byte or message mode. In either
// case the pipe is read in byte mode by default. The only practical difference in
// this implementation is that CloseWrite() is only supported for message mode pipes;
// CloseWrite() is implemented as a zero-byte write, but zero-byte writes are only
// transferred to the reader (and returned as io.EOF in this implementation)
// when the pipe is in message mode.
MessageMode bool
// InputBufferSize specifies the size of the input buffer, in bytes.
InputBufferSize int32
// OutputBufferSize specifies the size of the output buffer, in bytes.
OutputBufferSize int32
}
// ListenPipe creates a listener on a Windows named pipe path, e.g. \\.\pipe\mypipe.
// The pipe must not already exist.
func ListenPipe(path string, c *PipeConfig) (net.Listener, error) {
var (
sd []byte
err error
)
if c == nil {
c = &PipeConfig{}
}
if c.SecurityDescriptor != "" {
sd, err = SddlToSecurityDescriptor(c.SecurityDescriptor)
if err != nil {
return nil, err
}
}
h, err := makeServerPipeHandle(path, sd, c, true)
if err != nil {
return nil, err
}
l := &win32PipeListener{
firstHandle: h,
path: path,
config: *c,
acceptCh: make(chan (chan acceptResponse)),
closeCh: make(chan int),
doneCh: make(chan int),
}
go l.listenerRoutine()
return l, nil
}
func connectPipe(p *win32File) error {
c, err := p.prepareIO()
if err != nil {
return err
}
defer p.wg.Done()
err = connectNamedPipe(p.handle, &c.o)
_, err = p.asyncIO(c, nil, 0, err)
if err != nil && err != windows.ERROR_PIPE_CONNECTED { //nolint:errorlint // err is Errno
return err
}
return nil
}
func (l *win32PipeListener) Accept() (net.Conn, error) {
ch := make(chan acceptResponse)
select {
case l.acceptCh <- ch:
response := <-ch
err := response.err
if err != nil {
return nil, err
}
if l.config.MessageMode {
return &win32MessageBytePipe{
win32Pipe: win32Pipe{win32File: response.f, path: l.path},
}, nil
}
return &win32Pipe{win32File: response.f, path: l.path}, nil
case <-l.doneCh:
return nil, ErrPipeListenerClosed
}
}
func (l *win32PipeListener) Close() error {
select {
case l.closeCh <- 1:
<-l.doneCh
case <-l.doneCh:
}
return nil
}
func (l *win32PipeListener) Addr() net.Addr {
return pipeAddress(l.path)
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/pkg/guid/guid.go
================================================
// Package guid provides a GUID type. The backing structure for a GUID is
// identical to that used by the golang.org/x/sys/windows GUID type.
// There are two main binary encodings used for a GUID, the big-endian encoding,
// and the Windows (mixed-endian) encoding. See here for details:
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Encoding
package guid
import (
"crypto/rand"
"crypto/sha1" //nolint:gosec // not used for secure application
"encoding"
"encoding/binary"
"fmt"
"strconv"
)
//go:generate go run golang.org/x/tools/cmd/stringer -type=Variant -trimprefix=Variant -linecomment
// Variant specifies which GUID variant (or "type") of the GUID. It determines
// how the entirety of the rest of the GUID is interpreted.
type Variant uint8
// The variants specified by RFC 4122 section 4.1.1.
const (
// VariantUnknown specifies a GUID variant which does not conform to one of
// the variant encodings specified in RFC 4122.
VariantUnknown Variant = iota
VariantNCS
VariantRFC4122 // RFC 4122
VariantMicrosoft
VariantFuture
)
// Version specifies how the bits in the GUID were generated. For instance, a
// version 4 GUID is randomly generated, and a version 5 is generated from the
// hash of an input string.
type Version uint8
func (v Version) String() string {
return strconv.FormatUint(uint64(v), 10)
}
var _ = (encoding.TextMarshaler)(GUID{})
var _ = (encoding.TextUnmarshaler)(&GUID{})
// NewV4 returns a new version 4 (pseudorandom) GUID, as defined by RFC 4122.
func NewV4() (GUID, error) {
var b [16]byte
if _, err := rand.Read(b[:]); err != nil {
return GUID{}, err
}
g := FromArray(b)
g.setVersion(4) // Version 4 means randomly generated.
g.setVariant(VariantRFC4122)
return g, nil
}
// NewV5 returns a new version 5 (generated from a string via SHA-1 hashing)
// GUID, as defined by RFC 4122. The RFC is unclear on the encoding of the name,
// and the sample code treats it as a series of bytes, so we do the same here.
//
// Some implementations, such as those found on Windows, treat the name as a
// big-endian UTF16 stream of bytes. If that is desired, the string can be
// encoded as such before being passed to this function.
func NewV5(namespace GUID, name []byte) (GUID, error) {
b := sha1.New() //nolint:gosec // not used for secure application
namespaceBytes := namespace.ToArray()
b.Write(namespaceBytes[:])
b.Write(name)
a := [16]byte{}
copy(a[:], b.Sum(nil))
g := FromArray(a)
g.setVersion(5) // Version 5 means generated from a string.
g.setVariant(VariantRFC4122)
return g, nil
}
func fromArray(b [16]byte, order binary.ByteOrder) GUID {
var g GUID
g.Data1 = order.Uint32(b[0:4])
g.Data2 = order.Uint16(b[4:6])
g.Data3 = order.Uint16(b[6:8])
copy(g.Data4[:], b[8:16])
return g
}
func (g GUID) toArray(order binary.ByteOrder) [16]byte {
b := [16]byte{}
order.PutUint32(b[0:4], g.Data1)
order.PutUint16(b[4:6], g.Data2)
order.PutUint16(b[6:8], g.Data3)
copy(b[8:16], g.Data4[:])
return b
}
// FromArray constructs a GUID from a big-endian encoding array of 16 bytes.
func FromArray(b [16]byte) GUID {
return fromArray(b, binary.BigEndian)
}
// ToArray returns an array of 16 bytes representing the GUID in big-endian
// encoding.
func (g GUID) ToArray() [16]byte {
return g.toArray(binary.BigEndian)
}
// FromWindowsArray constructs a GUID from a Windows encoding array of bytes.
func FromWindowsArray(b [16]byte) GUID {
return fromArray(b, binary.LittleEndian)
}
// ToWindowsArray returns an array of 16 bytes representing the GUID in Windows
// encoding.
func (g GUID) ToWindowsArray() [16]byte {
return g.toArray(binary.LittleEndian)
}
func (g GUID) String() string {
return fmt.Sprintf(
"%08x-%04x-%04x-%04x-%012x",
g.Data1,
g.Data2,
g.Data3,
g.Data4[:2],
g.Data4[2:])
}
// FromString parses a string containing a GUID and returns the GUID. The only
// format currently supported is the `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
// format.
func FromString(s string) (GUID, error) {
if len(s) != 36 {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
var g GUID
data1, err := strconv.ParseUint(s[0:8], 16, 32)
if err != nil {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
g.Data1 = uint32(data1)
data2, err := strconv.ParseUint(s[9:13], 16, 16)
if err != nil {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
g.Data2 = uint16(data2)
data3, err := strconv.ParseUint(s[14:18], 16, 16)
if err != nil {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
g.Data3 = uint16(data3)
for i, x := range []int{19, 21, 24, 26, 28, 30, 32, 34} {
v, err := strconv.ParseUint(s[x:x+2], 16, 8)
if err != nil {
return GUID{}, fmt.Errorf("invalid GUID %q", s)
}
g.Data4[i] = uint8(v)
}
return g, nil
}
func (g *GUID) setVariant(v Variant) {
d := g.Data4[0]
switch v {
case VariantNCS:
d = (d & 0x7f)
case VariantRFC4122:
d = (d & 0x3f) | 0x80
case VariantMicrosoft:
d = (d & 0x1f) | 0xc0
case VariantFuture:
d = (d & 0x0f) | 0xe0
case VariantUnknown:
fallthrough
default:
panic(fmt.Sprintf("invalid variant: %d", v))
}
g.Data4[0] = d
}
// Variant returns the GUID variant, as defined in RFC 4122.
func (g GUID) Variant() Variant {
b := g.Data4[0]
if b&0x80 == 0 {
return VariantNCS
} else if b&0xc0 == 0x80 {
return VariantRFC4122
} else if b&0xe0 == 0xc0 {
return VariantMicrosoft
} else if b&0xe0 == 0xe0 {
return VariantFuture
}
return VariantUnknown
}
func (g *GUID) setVersion(v Version) {
g.Data3 = (g.Data3 & 0x0fff) | (uint16(v) << 12)
}
// Version returns the GUID version, as defined in RFC 4122.
func (g GUID) Version() Version {
return Version((g.Data3 & 0xF000) >> 12)
}
// MarshalText returns the textual representation of the GUID.
func (g GUID) MarshalText() ([]byte, error) {
return []byte(g.String()), nil
}
// UnmarshalText takes the textual representation of a GUID, and unmarhals it
// into this GUID.
func (g *GUID) UnmarshalText(text []byte) error {
g2, err := FromString(string(text))
if err != nil {
return err
}
*g = g2
return nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/pkg/guid/guid_nonwindows.go
================================================
//go:build !windows
// +build !windows
package guid
// GUID represents a GUID/UUID. It has the same structure as
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
// that type. It is defined as its own type as that is only available to builds
// targeted at `windows`. The representation matches that used by native Windows
// code.
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/pkg/guid/guid_windows.go
================================================
//go:build windows
// +build windows
package guid
import "golang.org/x/sys/windows"
// GUID represents a GUID/UUID. It has the same structure as
// golang.org/x/sys/windows.GUID so that it can be used with functions expecting
// that type. It is defined as its own type so that stringification and
// marshaling can be supported. The representation matches that used by native
// Windows code.
type GUID windows.GUID
================================================
FILE: vendor/github.com/Microsoft/go-winio/pkg/guid/variant_string.go
================================================
// Code generated by "stringer -type=Variant -trimprefix=Variant -linecomment"; DO NOT EDIT.
package guid
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[VariantUnknown-0]
_ = x[VariantNCS-1]
_ = x[VariantRFC4122-2]
_ = x[VariantMicrosoft-3]
_ = x[VariantFuture-4]
}
const _Variant_name = "UnknownNCSRFC 4122MicrosoftFuture"
var _Variant_index = [...]uint8{0, 7, 10, 18, 27, 33}
func (i Variant) String() string {
if i >= Variant(len(_Variant_index)-1) {
return "Variant(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Variant_name[_Variant_index[i]:_Variant_index[i+1]]
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/privilege.go
================================================
//go:build windows
// +build windows
package winio
import (
"bytes"
"encoding/binary"
"fmt"
"runtime"
"sync"
"syscall"
"unicode/utf16"
"golang.org/x/sys/windows"
)
//sys adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) [true] = advapi32.AdjustTokenPrivileges
//sys impersonateSelf(level uint32) (err error) = advapi32.ImpersonateSelf
//sys revertToSelf() (err error) = advapi32.RevertToSelf
//sys openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) = advapi32.OpenThreadToken
//sys getCurrentThread() (h syscall.Handle) = GetCurrentThread
//sys lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) = advapi32.LookupPrivilegeValueW
//sys lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) = advapi32.LookupPrivilegeNameW
//sys lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) = advapi32.LookupPrivilegeDisplayNameW
const (
//revive:disable-next-line:var-naming ALL_CAPS
SE_PRIVILEGE_ENABLED = windows.SE_PRIVILEGE_ENABLED
//revive:disable-next-line:var-naming ALL_CAPS
ERROR_NOT_ALL_ASSIGNED syscall.Errno = windows.ERROR_NOT_ALL_ASSIGNED
SeBackupPrivilege = "SeBackupPrivilege"
SeRestorePrivilege = "SeRestorePrivilege"
SeSecurityPrivilege = "SeSecurityPrivilege"
)
var (
privNames = make(map[string]uint64)
privNameMutex sync.Mutex
)
// PrivilegeError represents an error enabling privileges.
type PrivilegeError struct {
privileges []uint64
}
func (e *PrivilegeError) Error() string {
s := "Could not enable privilege "
if len(e.privileges) > 1 {
s = "Could not enable privileges "
}
for i, p := range e.privileges {
if i != 0 {
s += ", "
}
s += `"`
s += getPrivilegeName(p)
s += `"`
}
return s
}
// RunWithPrivilege enables a single privilege for a function call.
func RunWithPrivilege(name string, fn func() error) error {
return RunWithPrivileges([]string{name}, fn)
}
// RunWithPrivileges enables privileges for a function call.
func RunWithPrivileges(names []string, fn func() error) error {
privileges, err := mapPrivileges(names)
if err != nil {
return err
}
runtime.LockOSThread()
defer runtime.UnlockOSThread()
token, err := newThreadToken()
if err != nil {
return err
}
defer releaseThreadToken(token)
err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED)
if err != nil {
return err
}
return fn()
}
func mapPrivileges(names []string) ([]uint64, error) {
privileges := make([]uint64, 0, len(names))
privNameMutex.Lock()
defer privNameMutex.Unlock()
for _, name := range names {
p, ok := privNames[name]
if !ok {
err := lookupPrivilegeValue("", name, &p)
if err != nil {
return nil, err
}
privNames[name] = p
}
privileges = append(privileges, p)
}
return privileges, nil
}
// EnableProcessPrivileges enables privileges globally for the process.
func EnableProcessPrivileges(names []string) error {
return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED)
}
// DisableProcessPrivileges disables privileges globally for the process.
func DisableProcessPrivileges(names []string) error {
return enableDisableProcessPrivilege(names, 0)
}
func enableDisableProcessPrivilege(names []string, action uint32) error {
privileges, err := mapPrivileges(names)
if err != nil {
return err
}
p := windows.CurrentProcess()
var token windows.Token
err = windows.OpenProcessToken(p, windows.TOKEN_ADJUST_PRIVILEGES|windows.TOKEN_QUERY, &token)
if err != nil {
return err
}
defer token.Close()
return adjustPrivileges(token, privileges, action)
}
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
var b bytes.Buffer
_ = binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
for _, p := range privileges {
_ = binary.Write(&b, binary.LittleEndian, p)
_ = binary.Write(&b, binary.LittleEndian, action)
}
prevState := make([]byte, b.Len())
reqSize := uint32(0)
success, err := adjustTokenPrivileges(token, false, &b.Bytes()[0], uint32(len(prevState)), &prevState[0], &reqSize)
if !success {
return err
}
if err == ERROR_NOT_ALL_ASSIGNED { //nolint:errorlint // err is Errno
return &PrivilegeError{privileges}
}
return nil
}
func getPrivilegeName(luid uint64) string {
var nameBuffer [256]uint16
bufSize := uint32(len(nameBuffer))
err := lookupPrivilegeName("", &luid, &nameBuffer[0], &bufSize)
if err != nil {
return fmt.Sprintf("", luid)
}
var displayNameBuffer [256]uint16
displayBufSize := uint32(len(displayNameBuffer))
var langID uint32
err = lookupPrivilegeDisplayName("", &nameBuffer[0], &displayNameBuffer[0], &displayBufSize, &langID)
if err != nil {
return fmt.Sprintf("", string(utf16.Decode(nameBuffer[:bufSize])))
}
return string(utf16.Decode(displayNameBuffer[:displayBufSize]))
}
func newThreadToken() (windows.Token, error) {
err := impersonateSelf(windows.SecurityImpersonation)
if err != nil {
return 0, err
}
var token windows.Token
err = openThreadToken(getCurrentThread(), syscall.TOKEN_ADJUST_PRIVILEGES|syscall.TOKEN_QUERY, false, &token)
if err != nil {
rerr := revertToSelf()
if rerr != nil {
panic(rerr)
}
return 0, err
}
return token, nil
}
func releaseThreadToken(h windows.Token) {
err := revertToSelf()
if err != nil {
panic(err)
}
h.Close()
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/reparse.go
================================================
//go:build windows
// +build windows
package winio
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
"unicode/utf16"
"unsafe"
)
const (
reparseTagMountPoint = 0xA0000003
reparseTagSymlink = 0xA000000C
)
type reparseDataBuffer struct {
ReparseTag uint32
ReparseDataLength uint16
Reserved uint16
SubstituteNameOffset uint16
SubstituteNameLength uint16
PrintNameOffset uint16
PrintNameLength uint16
}
// ReparsePoint describes a Win32 symlink or mount point.
type ReparsePoint struct {
Target string
IsMountPoint bool
}
// UnsupportedReparsePointError is returned when trying to decode a non-symlink or
// mount point reparse point.
type UnsupportedReparsePointError struct {
Tag uint32
}
func (e *UnsupportedReparsePointError) Error() string {
return fmt.Sprintf("unsupported reparse point %x", e.Tag)
}
// DecodeReparsePoint decodes a Win32 REPARSE_DATA_BUFFER structure containing either a symlink
// or a mount point.
func DecodeReparsePoint(b []byte) (*ReparsePoint, error) {
tag := binary.LittleEndian.Uint32(b[0:4])
return DecodeReparsePointData(tag, b[8:])
}
func DecodeReparsePointData(tag uint32, b []byte) (*ReparsePoint, error) {
isMountPoint := false
switch tag {
case reparseTagMountPoint:
isMountPoint = true
case reparseTagSymlink:
default:
return nil, &UnsupportedReparsePointError{tag}
}
nameOffset := 8 + binary.LittleEndian.Uint16(b[4:6])
if !isMountPoint {
nameOffset += 4
}
nameLength := binary.LittleEndian.Uint16(b[6:8])
name := make([]uint16, nameLength/2)
err := binary.Read(bytes.NewReader(b[nameOffset:nameOffset+nameLength]), binary.LittleEndian, &name)
if err != nil {
return nil, err
}
return &ReparsePoint{string(utf16.Decode(name)), isMountPoint}, nil
}
func isDriveLetter(c byte) bool {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
// EncodeReparsePoint encodes a Win32 REPARSE_DATA_BUFFER structure describing a symlink or
// mount point.
func EncodeReparsePoint(rp *ReparsePoint) []byte {
// Generate an NT path and determine if this is a relative path.
var ntTarget string
relative := false
if strings.HasPrefix(rp.Target, `\\?\`) {
ntTarget = `\??\` + rp.Target[4:]
} else if strings.HasPrefix(rp.Target, `\\`) {
ntTarget = `\??\UNC\` + rp.Target[2:]
} else if len(rp.Target) >= 2 && isDriveLetter(rp.Target[0]) && rp.Target[1] == ':' {
ntTarget = `\??\` + rp.Target
} else {
ntTarget = rp.Target
relative = true
}
// The paths must be NUL-terminated even though they are counted strings.
target16 := utf16.Encode([]rune(rp.Target + "\x00"))
ntTarget16 := utf16.Encode([]rune(ntTarget + "\x00"))
size := int(unsafe.Sizeof(reparseDataBuffer{})) - 8
size += len(ntTarget16)*2 + len(target16)*2
tag := uint32(reparseTagMountPoint)
if !rp.IsMountPoint {
tag = reparseTagSymlink
size += 4 // Add room for symlink flags
}
data := reparseDataBuffer{
ReparseTag: tag,
ReparseDataLength: uint16(size),
SubstituteNameOffset: 0,
SubstituteNameLength: uint16((len(ntTarget16) - 1) * 2),
PrintNameOffset: uint16(len(ntTarget16) * 2),
PrintNameLength: uint16((len(target16) - 1) * 2),
}
var b bytes.Buffer
_ = binary.Write(&b, binary.LittleEndian, &data)
if !rp.IsMountPoint {
flags := uint32(0)
if relative {
flags |= 1
}
_ = binary.Write(&b, binary.LittleEndian, flags)
}
_ = binary.Write(&b, binary.LittleEndian, ntTarget16)
_ = binary.Write(&b, binary.LittleEndian, target16)
return b.Bytes()
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/sd.go
================================================
//go:build windows
// +build windows
package winio
import (
"errors"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
//sys lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountNameW
//sys lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) = advapi32.LookupAccountSidW
//sys convertSidToStringSid(sid *byte, str **uint16) (err error) = advapi32.ConvertSidToStringSidW
//sys convertStringSidToSid(str *uint16, sid **byte) (err error) = advapi32.ConvertStringSidToSidW
//sys convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) = advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW
//sys convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) = advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW
//sys localFree(mem uintptr) = LocalFree
//sys getSecurityDescriptorLength(sd uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength
type AccountLookupError struct {
Name string
Err error
}
func (e *AccountLookupError) Error() string {
if e.Name == "" {
return "lookup account: empty account name specified"
}
var s string
switch {
case errors.Is(e.Err, windows.ERROR_INVALID_SID):
s = "the security ID structure is invalid"
case errors.Is(e.Err, windows.ERROR_NONE_MAPPED):
s = "not found"
default:
s = e.Err.Error()
}
return "lookup account " + e.Name + ": " + s
}
func (e *AccountLookupError) Unwrap() error { return e.Err }
type SddlConversionError struct {
Sddl string
Err error
}
func (e *SddlConversionError) Error() string {
return "convert " + e.Sddl + ": " + e.Err.Error()
}
func (e *SddlConversionError) Unwrap() error { return e.Err }
// LookupSidByName looks up the SID of an account by name
//
//revive:disable-next-line:var-naming SID, not Sid
func LookupSidByName(name string) (sid string, err error) {
if name == "" {
return "", &AccountLookupError{name, windows.ERROR_NONE_MAPPED}
}
var sidSize, sidNameUse, refDomainSize uint32
err = lookupAccountName(nil, name, nil, &sidSize, nil, &refDomainSize, &sidNameUse)
if err != nil && err != syscall.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
return "", &AccountLookupError{name, err}
}
sidBuffer := make([]byte, sidSize)
refDomainBuffer := make([]uint16, refDomainSize)
err = lookupAccountName(nil, name, &sidBuffer[0], &sidSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
if err != nil {
return "", &AccountLookupError{name, err}
}
var strBuffer *uint16
err = convertSidToStringSid(&sidBuffer[0], &strBuffer)
if err != nil {
return "", &AccountLookupError{name, err}
}
sid = syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(strBuffer))[:])
localFree(uintptr(unsafe.Pointer(strBuffer)))
return sid, nil
}
// LookupNameBySid looks up the name of an account by SID
//
//revive:disable-next-line:var-naming SID, not Sid
func LookupNameBySid(sid string) (name string, err error) {
if sid == "" {
return "", &AccountLookupError{sid, windows.ERROR_NONE_MAPPED}
}
sidBuffer, err := windows.UTF16PtrFromString(sid)
if err != nil {
return "", &AccountLookupError{sid, err}
}
var sidPtr *byte
if err = convertStringSidToSid(sidBuffer, &sidPtr); err != nil {
return "", &AccountLookupError{sid, err}
}
defer localFree(uintptr(unsafe.Pointer(sidPtr)))
var nameSize, refDomainSize, sidNameUse uint32
err = lookupAccountSid(nil, sidPtr, nil, &nameSize, nil, &refDomainSize, &sidNameUse)
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER { //nolint:errorlint // err is Errno
return "", &AccountLookupError{sid, err}
}
nameBuffer := make([]uint16, nameSize)
refDomainBuffer := make([]uint16, refDomainSize)
err = lookupAccountSid(nil, sidPtr, &nameBuffer[0], &nameSize, &refDomainBuffer[0], &refDomainSize, &sidNameUse)
if err != nil {
return "", &AccountLookupError{sid, err}
}
name = windows.UTF16ToString(nameBuffer)
return name, nil
}
func SddlToSecurityDescriptor(sddl string) ([]byte, error) {
var sdBuffer uintptr
err := convertStringSecurityDescriptorToSecurityDescriptor(sddl, 1, &sdBuffer, nil)
if err != nil {
return nil, &SddlConversionError{sddl, err}
}
defer localFree(sdBuffer)
sd := make([]byte, getSecurityDescriptorLength(sdBuffer))
copy(sd, (*[0xffff]byte)(unsafe.Pointer(sdBuffer))[:len(sd)])
return sd, nil
}
func SecurityDescriptorToSddl(sd []byte) (string, error) {
var sddl *uint16
// The returned string length seems to include an arbitrary number of terminating NULs.
// Don't use it.
err := convertSecurityDescriptorToStringSecurityDescriptor(&sd[0], 1, 0xff, &sddl, nil)
if err != nil {
return "", err
}
defer localFree(uintptr(unsafe.Pointer(sddl)))
return syscall.UTF16ToString((*[0xffff]uint16)(unsafe.Pointer(sddl))[:]), nil
}
================================================
FILE: vendor/github.com/Microsoft/go-winio/syscall.go
================================================
//go:build windows
package winio
//go:generate go run github.com/Microsoft/go-winio/tools/mkwinsyscall -output zsyscall_windows.go ./*.go
================================================
FILE: vendor/github.com/Microsoft/go-winio/tools.go
================================================
//go:build tools
package winio
import _ "golang.org/x/tools/cmd/stringer"
================================================
FILE: vendor/github.com/Microsoft/go-winio/zsyscall_windows.go
================================================
//go:build windows
// Code generated by 'go generate' using "github.com/Microsoft/go-winio/tools/mkwinsyscall"; DO NOT EDIT.
package winio
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
modntdll = windows.NewLazySystemDLL("ntdll.dll")
modws2_32 = windows.NewLazySystemDLL("ws2_32.dll")
procAdjustTokenPrivileges = modadvapi32.NewProc("AdjustTokenPrivileges")
procConvertSecurityDescriptorToStringSecurityDescriptorW = modadvapi32.NewProc("ConvertSecurityDescriptorToStringSecurityDescriptorW")
procConvertSidToStringSidW = modadvapi32.NewProc("ConvertSidToStringSidW")
procConvertStringSecurityDescriptorToSecurityDescriptorW = modadvapi32.NewProc("ConvertStringSecurityDescriptorToSecurityDescriptorW")
procConvertStringSidToSidW = modadvapi32.NewProc("ConvertStringSidToSidW")
procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength")
procImpersonateSelf = modadvapi32.NewProc("ImpersonateSelf")
procLookupAccountNameW = modadvapi32.NewProc("LookupAccountNameW")
procLookupAccountSidW = modadvapi32.NewProc("LookupAccountSidW")
procLookupPrivilegeDisplayNameW = modadvapi32.NewProc("LookupPrivilegeDisplayNameW")
procLookupPrivilegeNameW = modadvapi32.NewProc("LookupPrivilegeNameW")
procLookupPrivilegeValueW = modadvapi32.NewProc("LookupPrivilegeValueW")
procOpenThreadToken = modadvapi32.NewProc("OpenThreadToken")
procRevertToSelf = modadvapi32.NewProc("RevertToSelf")
procBackupRead = modkernel32.NewProc("BackupRead")
procBackupWrite = modkernel32.NewProc("BackupWrite")
procCancelIoEx = modkernel32.NewProc("CancelIoEx")
procConnectNamedPipe = modkernel32.NewProc("ConnectNamedPipe")
procCreateIoCompletionPort = modkernel32.NewProc("CreateIoCompletionPort")
procCreateNamedPipeW = modkernel32.NewProc("CreateNamedPipeW")
procGetCurrentThread = modkernel32.NewProc("GetCurrentThread")
procGetNamedPipeHandleStateW = modkernel32.NewProc("GetNamedPipeHandleStateW")
procGetNamedPipeInfo = modkernel32.NewProc("GetNamedPipeInfo")
procGetQueuedCompletionStatus = modkernel32.NewProc("GetQueuedCompletionStatus")
procLocalAlloc = modkernel32.NewProc("LocalAlloc")
procLocalFree = modkernel32.NewProc("LocalFree")
procSetFileCompletionNotificationModes = modkernel32.NewProc("SetFileCompletionNotificationModes")
procNtCreateNamedPipeFile = modntdll.NewProc("NtCreateNamedPipeFile")
procRtlDefaultNpAcl = modntdll.NewProc("RtlDefaultNpAcl")
procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U")
procRtlNtStatusToDosErrorNoTeb = modntdll.NewProc("RtlNtStatusToDosErrorNoTeb")
procWSAGetOverlappedResult = modws2_32.NewProc("WSAGetOverlappedResult")
)
func adjustTokenPrivileges(token windows.Token, releaseAll bool, input *byte, outputSize uint32, output *byte, requiredSize *uint32) (success bool, err error) {
var _p0 uint32
if releaseAll {
_p0 = 1
}
r0, _, e1 := syscall.Syscall6(procAdjustTokenPrivileges.Addr(), 6, uintptr(token), uintptr(_p0), uintptr(unsafe.Pointer(input)), uintptr(outputSize), uintptr(unsafe.Pointer(output)), uintptr(unsafe.Pointer(requiredSize)))
success = r0 != 0
if true {
err = errnoErr(e1)
}
return
}
func convertSecurityDescriptorToStringSecurityDescriptor(sd *byte, revision uint32, secInfo uint32, sddl **uint16, sddlSize *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procConvertSecurityDescriptorToStringSecurityDescriptorW.Addr(), 5, uintptr(unsafe.Pointer(sd)), uintptr(revision), uintptr(secInfo), uintptr(unsafe.Pointer(sddl)), uintptr(unsafe.Pointer(sddlSize)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func convertSidToStringSid(sid *byte, str **uint16) (err error) {
r1, _, e1 := syscall.Syscall(procConvertSidToStringSidW.Addr(), 2, uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(str)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func convertStringSecurityDescriptorToSecurityDescriptor(str string, revision uint32, sd *uintptr, size *uint32) (err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(str)
if err != nil {
return
}
return _convertStringSecurityDescriptorToSecurityDescriptor(_p0, revision, sd, size)
}
func _convertStringSecurityDescriptorToSecurityDescriptor(str *uint16, revision uint32, sd *uintptr, size *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procConvertStringSecurityDescriptorToSecurityDescriptorW.Addr(), 4, uintptr(unsafe.Pointer(str)), uintptr(revision), uintptr(unsafe.Pointer(sd)), uintptr(unsafe.Pointer(size)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func convertStringSidToSid(str *uint16, sid **byte) (err error) {
r1, _, e1 := syscall.Syscall(procConvertStringSidToSidW.Addr(), 2, uintptr(unsafe.Pointer(str)), uintptr(unsafe.Pointer(sid)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func getSecurityDescriptorLength(sd uintptr) (len uint32) {
r0, _, _ := syscall.Syscall(procGetSecurityDescriptorLength.Addr(), 1, uintptr(sd), 0, 0)
len = uint32(r0)
return
}
func impersonateSelf(level uint32) (err error) {
r1, _, e1 := syscall.Syscall(procImpersonateSelf.Addr(), 1, uintptr(level), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func lookupAccountName(systemName *uint16, accountName string, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(accountName)
if err != nil {
return
}
return _lookupAccountName(systemName, _p0, sid, sidSize, refDomain, refDomainSize, sidNameUse)
}
func _lookupAccountName(systemName *uint16, accountName *uint16, sid *byte, sidSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
r1, _, e1 := syscall.Syscall9(procLookupAccountNameW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(accountName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(sidSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func lookupAccountSid(systemName *uint16, sid *byte, name *uint16, nameSize *uint32, refDomain *uint16, refDomainSize *uint32, sidNameUse *uint32) (err error) {
r1, _, e1 := syscall.Syscall9(procLookupAccountSidW.Addr(), 7, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(sid)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameSize)), uintptr(unsafe.Pointer(refDomain)), uintptr(unsafe.Pointer(refDomainSize)), uintptr(unsafe.Pointer(sidNameUse)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func lookupPrivilegeDisplayName(systemName string, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(systemName)
if err != nil {
return
}
return _lookupPrivilegeDisplayName(_p0, name, buffer, size, languageId)
}
func _lookupPrivilegeDisplayName(systemName *uint16, name *uint16, buffer *uint16, size *uint32, languageId *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeDisplayNameW.Addr(), 5, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), uintptr(unsafe.Pointer(languageId)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func lookupPrivilegeName(systemName string, luid *uint64, buffer *uint16, size *uint32) (err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(systemName)
if err != nil {
return
}
return _lookupPrivilegeName(_p0, luid, buffer, size)
}
func _lookupPrivilegeName(systemName *uint16, luid *uint64, buffer *uint16, size *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procLookupPrivilegeNameW.Addr(), 4, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(luid)), uintptr(unsafe.Pointer(buffer)), uintptr(unsafe.Pointer(size)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func lookupPrivilegeValue(systemName string, name string, luid *uint64) (err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(systemName)
if err != nil {
return
}
var _p1 *uint16
_p1, err = syscall.UTF16PtrFromString(name)
if err != nil {
return
}
return _lookupPrivilegeValue(_p0, _p1, luid)
}
func _lookupPrivilegeValue(systemName *uint16, name *uint16, luid *uint64) (err error) {
r1, _, e1 := syscall.Syscall(procLookupPrivilegeValueW.Addr(), 3, uintptr(unsafe.Pointer(systemName)), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(luid)))
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func openThreadToken(thread syscall.Handle, accessMask uint32, openAsSelf bool, token *windows.Token) (err error) {
var _p0 uint32
if openAsSelf {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procOpenThreadToken.Addr(), 4, uintptr(thread), uintptr(accessMask), uintptr(_p0), uintptr(unsafe.Pointer(token)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func revertToSelf() (err error) {
r1, _, e1 := syscall.Syscall(procRevertToSelf.Addr(), 0, 0, 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func backupRead(h syscall.Handle, b []byte, bytesRead *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
var _p0 *byte
if len(b) > 0 {
_p0 = &b[0]
}
var _p1 uint32
if abort {
_p1 = 1
}
var _p2 uint32
if processSecurity {
_p2 = 1
}
r1, _, e1 := syscall.Syscall9(procBackupRead.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesRead)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func backupWrite(h syscall.Handle, b []byte, bytesWritten *uint32, abort bool, processSecurity bool, context *uintptr) (err error) {
var _p0 *byte
if len(b) > 0 {
_p0 = &b[0]
}
var _p1 uint32
if abort {
_p1 = 1
}
var _p2 uint32
if processSecurity {
_p2 = 1
}
r1, _, e1 := syscall.Syscall9(procBackupWrite.Addr(), 7, uintptr(h), uintptr(unsafe.Pointer(_p0)), uintptr(len(b)), uintptr(unsafe.Pointer(bytesWritten)), uintptr(_p1), uintptr(_p2), uintptr(unsafe.Pointer(context)), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func cancelIoEx(file syscall.Handle, o *syscall.Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procCancelIoEx.Addr(), 2, uintptr(file), uintptr(unsafe.Pointer(o)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func connectNamedPipe(pipe syscall.Handle, o *syscall.Overlapped) (err error) {
r1, _, e1 := syscall.Syscall(procConnectNamedPipe.Addr(), 2, uintptr(pipe), uintptr(unsafe.Pointer(o)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func createIoCompletionPort(file syscall.Handle, port syscall.Handle, key uintptr, threadCount uint32) (newport syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall6(procCreateIoCompletionPort.Addr(), 4, uintptr(file), uintptr(port), uintptr(key), uintptr(threadCount), 0, 0)
newport = syscall.Handle(r0)
if newport == 0 {
err = errnoErr(e1)
}
return
}
func createNamedPipe(name string, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
var _p0 *uint16
_p0, err = syscall.UTF16PtrFromString(name)
if err != nil {
return
}
return _createNamedPipe(_p0, flags, pipeMode, maxInstances, outSize, inSize, defaultTimeout, sa)
}
func _createNamedPipe(name *uint16, flags uint32, pipeMode uint32, maxInstances uint32, outSize uint32, inSize uint32, defaultTimeout uint32, sa *syscall.SecurityAttributes) (handle syscall.Handle, err error) {
r0, _, e1 := syscall.Syscall9(procCreateNamedPipeW.Addr(), 8, uintptr(unsafe.Pointer(name)), uintptr(flags), uintptr(pipeMode), uintptr(maxInstances), uintptr(outSize), uintptr(inSize), uintptr(defaultTimeout), uintptr(unsafe.Pointer(sa)), 0)
handle = syscall.Handle(r0)
if handle == syscall.InvalidHandle {
err = errnoErr(e1)
}
return
}
func getCurrentThread() (h syscall.Handle) {
r0, _, _ := syscall.Syscall(procGetCurrentThread.Addr(), 0, 0, 0, 0)
h = syscall.Handle(r0)
return
}
func getNamedPipeHandleState(pipe syscall.Handle, state *uint32, curInstances *uint32, maxCollectionCount *uint32, collectDataTimeout *uint32, userName *uint16, maxUserNameSize uint32) (err error) {
r1, _, e1 := syscall.Syscall9(procGetNamedPipeHandleStateW.Addr(), 7, uintptr(pipe), uintptr(unsafe.Pointer(state)), uintptr(unsafe.Pointer(curInstances)), uintptr(unsafe.Pointer(maxCollectionCount)), uintptr(unsafe.Pointer(collectDataTimeout)), uintptr(unsafe.Pointer(userName)), uintptr(maxUserNameSize), 0, 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func getNamedPipeInfo(pipe syscall.Handle, flags *uint32, outSize *uint32, inSize *uint32, maxInstances *uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procGetNamedPipeInfo.Addr(), 5, uintptr(pipe), uintptr(unsafe.Pointer(flags)), uintptr(unsafe.Pointer(outSize)), uintptr(unsafe.Pointer(inSize)), uintptr(unsafe.Pointer(maxInstances)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func getQueuedCompletionStatus(port syscall.Handle, bytes *uint32, key *uintptr, o **ioOperation, timeout uint32) (err error) {
r1, _, e1 := syscall.Syscall6(procGetQueuedCompletionStatus.Addr(), 5, uintptr(port), uintptr(unsafe.Pointer(bytes)), uintptr(unsafe.Pointer(key)), uintptr(unsafe.Pointer(o)), uintptr(timeout), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func localAlloc(uFlags uint32, length uint32) (ptr uintptr) {
r0, _, _ := syscall.Syscall(procLocalAlloc.Addr(), 2, uintptr(uFlags), uintptr(length), 0)
ptr = uintptr(r0)
return
}
func localFree(mem uintptr) {
syscall.Syscall(procLocalFree.Addr(), 1, uintptr(mem), 0, 0)
return
}
func setFileCompletionNotificationModes(h syscall.Handle, flags uint8) (err error) {
r1, _, e1 := syscall.Syscall(procSetFileCompletionNotificationModes.Addr(), 2, uintptr(h), uintptr(flags), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
func ntCreateNamedPipeFile(pipe *syscall.Handle, access uint32, oa *objectAttributes, iosb *ioStatusBlock, share uint32, disposition uint32, options uint32, typ uint32, readMode uint32, completionMode uint32, maxInstances uint32, inboundQuota uint32, outputQuota uint32, timeout *int64) (status ntStatus) {
r0, _, _ := syscall.Syscall15(procNtCreateNamedPipeFile.Addr(), 14, uintptr(unsafe.Pointer(pipe)), uintptr(access), uintptr(unsafe.Pointer(oa)), uintptr(unsafe.Pointer(iosb)), uintptr(share), uintptr(disposition), uintptr(options), uintptr(typ), uintptr(readMode), uintptr(completionMode), uintptr(maxInstances), uintptr(inboundQuota), uintptr(outputQuota), uintptr(unsafe.Pointer(timeout)), 0)
status = ntStatus(r0)
return
}
func rtlDefaultNpAcl(dacl *uintptr) (status ntStatus) {
r0, _, _ := syscall.Syscall(procRtlDefaultNpAcl.Addr(), 1, uintptr(unsafe.Pointer(dacl)), 0, 0)
status = ntStatus(r0)
return
}
func rtlDosPathNameToNtPathName(name *uint16, ntName *unicodeString, filePart uintptr, reserved uintptr) (status ntStatus) {
r0, _, _ := syscall.Syscall6(procRtlDosPathNameToNtPathName_U.Addr(), 4, uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(ntName)), uintptr(filePart), uintptr(reserved), 0, 0)
status = ntStatus(r0)
return
}
func rtlNtStatusToDosError(status ntStatus) (winerr error) {
r0, _, _ := syscall.Syscall(procRtlNtStatusToDosErrorNoTeb.Addr(), 1, uintptr(status), 0, 0)
if r0 != 0 {
winerr = syscall.Errno(r0)
}
return
}
func wsaGetOverlappedResult(h syscall.Handle, o *syscall.Overlapped, bytes *uint32, wait bool, flags *uint32) (err error) {
var _p0 uint32
if wait {
_p0 = 1
}
r1, _, e1 := syscall.Syscall6(procWSAGetOverlappedResult.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(o)), uintptr(unsafe.Pointer(bytes)), uintptr(_p0), uintptr(unsafe.Pointer(flags)), 0)
if r1 == 0 {
err = errnoErr(e1)
}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/AUTHORS
================================================
# This source code refers to The Go Authors for copyright purposes.
# The master list of authors is in the main Go distribution,
# visible at https://tip.golang.org/AUTHORS.
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/CONTRIBUTORS
================================================
# This source code was written by the Go contributors.
# The master list of contributors is in the main Go distribution,
# visible at https://tip.golang.org/CONTRIBUTORS.
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/LICENSE
================================================
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/PATENTS
================================================
Additional IP Rights Grant (Patents)
"This implementation" means the copyrightable works distributed by
Google as part of the Go project.
Google hereby grants to You a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer and otherwise run, modify and propagate the contents of this
implementation of Go, where such license applies only to those patent
claims, both currently owned or controlled by Google and acquired in
the future, licensable by Google that are necessarily infringed by this
implementation of Go. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of Go or any code incorporated within this
implementation of Go constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of Go
shall terminate as of the date such litigation is filed.
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/bitcurves/bitcurve.go
================================================
package bitcurves
// Copyright 2010 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package bitelliptic implements several Koblitz elliptic curves over prime
// fields.
// This package operates, internally, on Jacobian coordinates. For a given
// (x, y) position on the curve, the Jacobian coordinates are (x1, y1, z1)
// where x = x1/z1² and y = y1/z1³. The greatest speedups come when the whole
// calculation can be performed within the transform (as in ScalarMult and
// ScalarBaseMult). But even for Add and Double, it's faster to apply and
// reverse the transform than to operate in affine coordinates.
import (
"crypto/elliptic"
"io"
"math/big"
"sync"
)
// A BitCurve represents a Koblitz Curve with a=0.
// See http://www.hyperelliptic.org/EFD/g1p/auto-shortw.html
type BitCurve struct {
Name string
P *big.Int // the order of the underlying field
N *big.Int // the order of the base point
B *big.Int // the constant of the BitCurve equation
Gx, Gy *big.Int // (x,y) of the base point
BitSize int // the size of the underlying field
}
// Params returns the parameters of the given BitCurve (see BitCurve struct)
func (bitCurve *BitCurve) Params() (cp *elliptic.CurveParams) {
cp = new(elliptic.CurveParams)
cp.Name = bitCurve.Name
cp.P = bitCurve.P
cp.N = bitCurve.N
cp.Gx = bitCurve.Gx
cp.Gy = bitCurve.Gy
cp.BitSize = bitCurve.BitSize
return cp
}
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
// y² = x³ + b
y2 := new(big.Int).Mul(y, y) //y²
y2.Mod(y2, bitCurve.P) //y²%P
x3 := new(big.Int).Mul(x, x) //x²
x3.Mul(x3, x) //x³
x3.Add(x3, bitCurve.B) //x³+B
x3.Mod(x3, bitCurve.P) //(x³+B)%P
return x3.Cmp(y2) == 0
}
// affineFromJacobian reverses the Jacobian transform. See the comment at the
// top of the file.
func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
if z.Cmp(big.NewInt(0)) == 0 {
panic("bitcurve: Can't convert to affine with Jacobian Z = 0")
}
// x = YZ^2 mod P
zinv := new(big.Int).ModInverse(z, bitCurve.P)
zinvsq := new(big.Int).Mul(zinv, zinv)
xOut = new(big.Int).Mul(x, zinvsq)
xOut.Mod(xOut, bitCurve.P)
// y = YZ^3 mod P
zinvsq.Mul(zinvsq, zinv)
yOut = new(big.Int).Mul(y, zinvsq)
yOut.Mod(yOut, bitCurve.P)
return xOut, yOut
}
// Add returns the sum of (x1,y1) and (x2,y2)
func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
z := new(big.Int).SetInt64(1)
x, y, z := bitCurve.addJacobian(x1, y1, z, x2, y2, z)
return bitCurve.affineFromJacobian(x, y, z)
}
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
// (x2, y2, z2) and returns their sum, also in Jacobian form.
func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
z1z1 := new(big.Int).Mul(z1, z1)
z1z1.Mod(z1z1, bitCurve.P)
z2z2 := new(big.Int).Mul(z2, z2)
z2z2.Mod(z2z2, bitCurve.P)
u1 := new(big.Int).Mul(x1, z2z2)
u1.Mod(u1, bitCurve.P)
u2 := new(big.Int).Mul(x2, z1z1)
u2.Mod(u2, bitCurve.P)
h := new(big.Int).Sub(u2, u1)
if h.Sign() == -1 {
h.Add(h, bitCurve.P)
}
i := new(big.Int).Lsh(h, 1)
i.Mul(i, i)
j := new(big.Int).Mul(h, i)
s1 := new(big.Int).Mul(y1, z2)
s1.Mul(s1, z2z2)
s1.Mod(s1, bitCurve.P)
s2 := new(big.Int).Mul(y2, z1)
s2.Mul(s2, z1z1)
s2.Mod(s2, bitCurve.P)
r := new(big.Int).Sub(s2, s1)
if r.Sign() == -1 {
r.Add(r, bitCurve.P)
}
r.Lsh(r, 1)
v := new(big.Int).Mul(u1, i)
x3 := new(big.Int).Set(r)
x3.Mul(x3, x3)
x3.Sub(x3, j)
x3.Sub(x3, v)
x3.Sub(x3, v)
x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Set(r)
v.Sub(v, x3)
y3.Mul(y3, v)
s1.Mul(s1, j)
s1.Lsh(s1, 1)
y3.Sub(y3, s1)
y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Add(z1, z2)
z3.Mul(z3, z3)
z3.Sub(z3, z1z1)
if z3.Sign() == -1 {
z3.Add(z3, bitCurve.P)
}
z3.Sub(z3, z2z2)
if z3.Sign() == -1 {
z3.Add(z3, bitCurve.P)
}
z3.Mul(z3, h)
z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// Double returns 2*(x,y)
func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
z1 := new(big.Int).SetInt64(1)
return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1))
}
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
// returns its double, also in Jacobian form.
func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
a := new(big.Int).Mul(x, x) //X1²
b := new(big.Int).Mul(y, y) //Y1²
c := new(big.Int).Mul(b, b) //B²
d := new(big.Int).Add(x, b) //X1+B
d.Mul(d, d) //(X1+B)²
d.Sub(d, a) //(X1+B)²-A
d.Sub(d, c) //(X1+B)²-A-C
d.Mul(d, big.NewInt(2)) //2*((X1+B)²-A-C)
e := new(big.Int).Mul(big.NewInt(3), a) //3*A
f := new(big.Int).Mul(e, e) //E²
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
x3.Sub(f, x3) //F-2*D
x3.Mod(x3, bitCurve.P)
y3 := new(big.Int).Sub(d, x3) //D-X3
y3.Mul(e, y3) //E*(D-X3)
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
y3.Mod(y3, bitCurve.P)
z3 := new(big.Int).Mul(y, z) //Y1*Z1
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
z3.Mod(z3, bitCurve.P)
return x3, y3, z3
}
// TODO: double check if it is okay
// ScalarMult returns k*(Bx,By) where k is a number in big-endian form.
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, k []byte) (*big.Int, *big.Int) {
// We have a slight problem in that the identity of the group (the
// point at infinity) cannot be represented in (x, y) form on a finite
// machine. Thus the standard add/double algorithm has to be tweaked
// slightly: our initial state is not the identity, but x, and we
// ignore the first true bit in |k|. If we don't find any true bits in
// |k|, then we return nil, nil, because we cannot return the identity
// element.
Bz := new(big.Int).SetInt64(1)
x := Bx
y := By
z := Bz
seenFirstTrue := false
for _, byte := range k {
for bitNum := 0; bitNum < 8; bitNum++ {
if seenFirstTrue {
x, y, z = bitCurve.doubleJacobian(x, y, z)
}
if byte&0x80 == 0x80 {
if !seenFirstTrue {
seenFirstTrue = true
} else {
x, y, z = bitCurve.addJacobian(Bx, By, Bz, x, y, z)
}
}
byte <<= 1
}
}
if !seenFirstTrue {
return nil, nil
}
return bitCurve.affineFromJacobian(x, y, z)
}
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
// an integer in big-endian form.
func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k)
}
var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
// TODO: double check if it is okay
// GenerateKey returns a public/private key pair. The private key is generated
// using the given reader, which must return random data.
func (bitCurve *BitCurve) GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) {
byteLen := (bitCurve.BitSize + 7) >> 3
priv = make([]byte, byteLen)
for x == nil {
_, err = io.ReadFull(rand, priv)
if err != nil {
return
}
// We have to mask off any excess bits in the case that the size of the
// underlying field is not a whole number of bytes.
priv[0] &= mask[bitCurve.BitSize%8]
// This is because, in tests, rand will return all zeros and we don't
// want to get the point at infinity and loop forever.
priv[1] ^= 0x42
x, y = bitCurve.ScalarBaseMult(priv)
}
return
}
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
// X9.62.
func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
byteLen := (bitCurve.BitSize + 7) >> 3
ret := make([]byte, 1+2*byteLen)
ret[0] = 4 // uncompressed point
xBytes := x.Bytes()
copy(ret[1+byteLen-len(xBytes):], xBytes)
yBytes := y.Bytes()
copy(ret[1+2*byteLen-len(yBytes):], yBytes)
return ret
}
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
// error, x = nil.
func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
byteLen := (bitCurve.BitSize + 7) >> 3
if len(data) != 1+2*byteLen {
return
}
if data[0] != 4 { // uncompressed form
return
}
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
y = new(big.Int).SetBytes(data[1+byteLen:])
return
}
//curve parameters taken from:
//http://www.secg.org/collateral/sec2_final.pdf
var initonce sync.Once
var secp160k1 *BitCurve
var secp192k1 *BitCurve
var secp224k1 *BitCurve
var secp256k1 *BitCurve
func initAll() {
initS160()
initS192()
initS224()
initS256()
}
func initS160() {
// See SEC 2 section 2.4.1
secp160k1 = new(BitCurve)
secp160k1.Name = "secp160k1"
secp160k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", 16)
secp160k1.N, _ = new(big.Int).SetString("0100000000000000000001B8FA16DFAB9ACA16B6B3", 16)
secp160k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000007", 16)
secp160k1.Gx, _ = new(big.Int).SetString("3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", 16)
secp160k1.Gy, _ = new(big.Int).SetString("938CF935318FDCED6BC28286531733C3F03C4FEE", 16)
secp160k1.BitSize = 160
}
func initS192() {
// See SEC 2 section 2.5.1
secp192k1 = new(BitCurve)
secp192k1.Name = "secp192k1"
secp192k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", 16)
secp192k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 16)
secp192k1.B, _ = new(big.Int).SetString("000000000000000000000000000000000000000000000003", 16)
secp192k1.Gx, _ = new(big.Int).SetString("DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", 16)
secp192k1.Gy, _ = new(big.Int).SetString("9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", 16)
secp192k1.BitSize = 192
}
func initS224() {
// See SEC 2 section 2.6.1
secp224k1 = new(BitCurve)
secp224k1.Name = "secp224k1"
secp224k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", 16)
secp224k1.N, _ = new(big.Int).SetString("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 16)
secp224k1.B, _ = new(big.Int).SetString("00000000000000000000000000000000000000000000000000000005", 16)
secp224k1.Gx, _ = new(big.Int).SetString("A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", 16)
secp224k1.Gy, _ = new(big.Int).SetString("7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", 16)
secp224k1.BitSize = 224
}
func initS256() {
// See SEC 2 section 2.7.1
secp256k1 = new(BitCurve)
secp256k1.Name = "secp256k1"
secp256k1.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
secp256k1.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
secp256k1.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16)
secp256k1.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
secp256k1.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
secp256k1.BitSize = 256
}
// S160 returns a BitCurve which implements secp160k1 (see SEC 2 section 2.4.1)
func S160() *BitCurve {
initonce.Do(initAll)
return secp160k1
}
// S192 returns a BitCurve which implements secp192k1 (see SEC 2 section 2.5.1)
func S192() *BitCurve {
initonce.Do(initAll)
return secp192k1
}
// S224 returns a BitCurve which implements secp224k1 (see SEC 2 section 2.6.1)
func S224() *BitCurve {
initonce.Do(initAll)
return secp224k1
}
// S256 returns a BitCurve which implements bitcurves (see SEC 2 section 2.7.1)
func S256() *BitCurve {
initonce.Do(initAll)
return secp256k1
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/brainpool/brainpool.go
================================================
// Package brainpool implements Brainpool elliptic curves.
// Implementation of rcurves is from github.com/ebfe/brainpool
// Note that these curves are implemented with naive, non-constant time operations
// and are likely not suitable for environments where timing attacks are a concern.
package brainpool
import (
"crypto/elliptic"
"math/big"
"sync"
)
var (
once sync.Once
p256t1, p384t1, p512t1 *elliptic.CurveParams
p256r1, p384r1, p512r1 *rcurve
)
func initAll() {
initP256t1()
initP384t1()
initP512t1()
initP256r1()
initP384r1()
initP512r1()
}
func initP256t1() {
p256t1 = &elliptic.CurveParams{Name: "brainpoolP256t1"}
p256t1.P, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16)
p256t1.N, _ = new(big.Int).SetString("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16)
p256t1.B, _ = new(big.Int).SetString("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16)
p256t1.Gx, _ = new(big.Int).SetString("A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4", 16)
p256t1.Gy, _ = new(big.Int).SetString("2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE", 16)
p256t1.BitSize = 256
}
func initP256r1() {
twisted := p256t1
params := &elliptic.CurveParams{
Name: "brainpoolP256r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", 16)
params.Gy, _ = new(big.Int).SetString("547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", 16)
z, _ := new(big.Int).SetString("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0", 16)
p256r1 = newrcurve(twisted, params, z)
}
func initP384t1() {
p384t1 = &elliptic.CurveParams{Name: "brainpoolP384t1"}
p384t1.P, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16)
p384t1.N, _ = new(big.Int).SetString("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16)
p384t1.B, _ = new(big.Int).SetString("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16)
p384t1.Gx, _ = new(big.Int).SetString("18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC", 16)
p384t1.Gy, _ = new(big.Int).SetString("25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928", 16)
p384t1.BitSize = 384
}
func initP384r1() {
twisted := p384t1
params := &elliptic.CurveParams{
Name: "brainpoolP384r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", 16)
params.Gy, _ = new(big.Int).SetString("8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", 16)
z, _ := new(big.Int).SetString("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C", 16)
p384r1 = newrcurve(twisted, params, z)
}
func initP512t1() {
p512t1 = &elliptic.CurveParams{Name: "brainpoolP512t1"}
p512t1.P, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16)
p512t1.N, _ = new(big.Int).SetString("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16)
p512t1.B, _ = new(big.Int).SetString("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16)
p512t1.Gx, _ = new(big.Int).SetString("640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA", 16)
p512t1.Gy, _ = new(big.Int).SetString("5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332", 16)
p512t1.BitSize = 512
}
func initP512r1() {
twisted := p512t1
params := &elliptic.CurveParams{
Name: "brainpoolP512r1",
P: twisted.P,
N: twisted.N,
BitSize: twisted.BitSize,
}
params.Gx, _ = new(big.Int).SetString("81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", 16)
params.Gy, _ = new(big.Int).SetString("7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", 16)
z, _ := new(big.Int).SetString("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB", 16)
p512r1 = newrcurve(twisted, params, z)
}
// P256t1 returns a Curve which implements Brainpool P256t1 (see RFC 5639, section 3.4)
func P256t1() elliptic.Curve {
once.Do(initAll)
return p256t1
}
// P256r1 returns a Curve which implements Brainpool P256r1 (see RFC 5639, section 3.4)
func P256r1() elliptic.Curve {
once.Do(initAll)
return p256r1
}
// P384t1 returns a Curve which implements Brainpool P384t1 (see RFC 5639, section 3.6)
func P384t1() elliptic.Curve {
once.Do(initAll)
return p384t1
}
// P384r1 returns a Curve which implements Brainpool P384r1 (see RFC 5639, section 3.6)
func P384r1() elliptic.Curve {
once.Do(initAll)
return p384r1
}
// P512t1 returns a Curve which implements Brainpool P512t1 (see RFC 5639, section 3.7)
func P512t1() elliptic.Curve {
once.Do(initAll)
return p512t1
}
// P512r1 returns a Curve which implements Brainpool P512r1 (see RFC 5639, section 3.7)
func P512r1() elliptic.Curve {
once.Do(initAll)
return p512r1
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/brainpool/rcurve.go
================================================
package brainpool
import (
"crypto/elliptic"
"math/big"
)
var _ elliptic.Curve = (*rcurve)(nil)
type rcurve struct {
twisted elliptic.Curve
params *elliptic.CurveParams
z *big.Int
zinv *big.Int
z2 *big.Int
z3 *big.Int
zinv2 *big.Int
zinv3 *big.Int
}
var (
two = big.NewInt(2)
three = big.NewInt(3)
)
func newrcurve(twisted elliptic.Curve, params *elliptic.CurveParams, z *big.Int) *rcurve {
zinv := new(big.Int).ModInverse(z, params.P)
return &rcurve{
twisted: twisted,
params: params,
z: z,
zinv: zinv,
z2: new(big.Int).Exp(z, two, params.P),
z3: new(big.Int).Exp(z, three, params.P),
zinv2: new(big.Int).Exp(zinv, two, params.P),
zinv3: new(big.Int).Exp(zinv, three, params.P),
}
}
func (curve *rcurve) toTwisted(x, y *big.Int) (*big.Int, *big.Int) {
var tx, ty big.Int
tx.Mul(x, curve.z2)
tx.Mod(&tx, curve.params.P)
ty.Mul(y, curve.z3)
ty.Mod(&ty, curve.params.P)
return &tx, &ty
}
func (curve *rcurve) fromTwisted(tx, ty *big.Int) (*big.Int, *big.Int) {
var x, y big.Int
x.Mul(tx, curve.zinv2)
x.Mod(&x, curve.params.P)
y.Mul(ty, curve.zinv3)
y.Mod(&y, curve.params.P)
return &x, &y
}
func (curve *rcurve) Params() *elliptic.CurveParams {
return curve.params
}
func (curve *rcurve) IsOnCurve(x, y *big.Int) bool {
return curve.twisted.IsOnCurve(curve.toTwisted(x, y))
}
func (curve *rcurve) Add(x1, y1, x2, y2 *big.Int) (x, y *big.Int) {
tx1, ty1 := curve.toTwisted(x1, y1)
tx2, ty2 := curve.toTwisted(x2, y2)
return curve.fromTwisted(curve.twisted.Add(tx1, ty1, tx2, ty2))
}
func (curve *rcurve) Double(x1, y1 *big.Int) (x, y *big.Int) {
return curve.fromTwisted(curve.twisted.Double(curve.toTwisted(x1, y1)))
}
func (curve *rcurve) ScalarMult(x1, y1 *big.Int, scalar []byte) (x, y *big.Int) {
tx1, ty1 := curve.toTwisted(x1, y1)
return curve.fromTwisted(curve.twisted.ScalarMult(tx1, ty1, scalar))
}
func (curve *rcurve) ScalarBaseMult(scalar []byte) (x, y *big.Int) {
return curve.fromTwisted(curve.twisted.ScalarBaseMult(scalar))
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/eax/eax.go
================================================
// Copyright (C) 2019 ProtonTech AG
// Package eax provides an implementation of the EAX
// (encrypt-authenticate-translate) mode of operation, as described in
// Bellare, Rogaway, and Wagner "THE EAX MODE OF OPERATION: A TWO-PASS
// AUTHENTICATED-ENCRYPTION SCHEME OPTIMIZED FOR SIMPLICITY AND EFFICIENCY."
// In FSE'04, volume 3017 of LNCS, 2004
package eax
import (
"crypto/cipher"
"crypto/subtle"
"errors"
"github.com/ProtonMail/go-crypto/internal/byteutil"
)
const (
defaultTagSize = 16
defaultNonceSize = 16
)
type eax struct {
block cipher.Block // Only AES-{128, 192, 256} supported
tagSize int // At least 12 bytes recommended
nonceSize int
}
func (e *eax) NonceSize() int {
return e.nonceSize
}
func (e *eax) Overhead() int {
return e.tagSize
}
// NewEAX returns an EAX instance with AES-{KEYLENGTH} and default nonce and
// tag lengths. Supports {128, 192, 256}- bit key length.
func NewEAX(block cipher.Block) (cipher.AEAD, error) {
return NewEAXWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
}
// NewEAXWithNonceAndTagSize returns an EAX instance with AES-{keyLength} and
// given nonce and tag lengths in bytes. Panics on zero nonceSize and
// exceedingly long tags.
//
// It is recommended to use at least 12 bytes as tag length (see, for instance,
// NIST SP 800-38D).
//
// Only to be used for compatibility with existing cryptosystems with
// non-standard parameters. For all other cases, prefer NewEAX.
func NewEAXWithNonceAndTagSize(
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
if nonceSize < 1 {
return nil, eaxError("Cannot initialize EAX with nonceSize = 0")
}
if tagSize > block.BlockSize() {
return nil, eaxError("Custom tag length exceeds blocksize")
}
return &eax{
block: block,
tagSize: tagSize,
nonceSize: nonceSize,
}, nil
}
func (e *eax) Seal(dst, nonce, plaintext, adata []byte) []byte {
if len(nonce) > e.nonceSize {
panic("crypto/eax: Nonce too long for this instance")
}
ret, out := byteutil.SliceForAppend(dst, len(plaintext)+e.tagSize)
omacNonce := e.omacT(0, nonce)
omacAdata := e.omacT(1, adata)
// Encrypt message using CTR mode and omacNonce as IV
ctr := cipher.NewCTR(e.block, omacNonce)
ciphertextData := out[:len(plaintext)]
ctr.XORKeyStream(ciphertextData, plaintext)
omacCiphertext := e.omacT(2, ciphertextData)
tag := out[len(plaintext):]
for i := 0; i < e.tagSize; i++ {
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
}
return ret
}
func (e *eax) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
if len(nonce) > e.nonceSize {
panic("crypto/eax: Nonce too long for this instance")
}
if len(ciphertext) < e.tagSize {
return nil, eaxError("Ciphertext shorter than tag length")
}
sep := len(ciphertext) - e.tagSize
// Compute tag
omacNonce := e.omacT(0, nonce)
omacAdata := e.omacT(1, adata)
omacCiphertext := e.omacT(2, ciphertext[:sep])
tag := make([]byte, e.tagSize)
for i := 0; i < e.tagSize; i++ {
tag[i] = omacCiphertext[i] ^ omacNonce[i] ^ omacAdata[i]
}
// Compare tags
if subtle.ConstantTimeCompare(ciphertext[sep:], tag) != 1 {
return nil, eaxError("Tag authentication failed")
}
// Decrypt ciphertext
ret, out := byteutil.SliceForAppend(dst, len(ciphertext))
ctr := cipher.NewCTR(e.block, omacNonce)
ctr.XORKeyStream(out, ciphertext[:sep])
return ret[:sep], nil
}
// Tweakable OMAC - Calls OMAC_K([t]_n || plaintext)
func (e *eax) omacT(t byte, plaintext []byte) []byte {
blockSize := e.block.BlockSize()
byteT := make([]byte, blockSize)
byteT[blockSize-1] = t
concat := append(byteT, plaintext...)
return e.omac(concat)
}
func (e *eax) omac(plaintext []byte) []byte {
blockSize := e.block.BlockSize()
// L ← E_K(0^n); B ← 2L; P ← 4L
L := make([]byte, blockSize)
e.block.Encrypt(L, L)
B := byteutil.GfnDouble(L)
P := byteutil.GfnDouble(B)
// CBC with IV = 0
cbc := cipher.NewCBCEncrypter(e.block, make([]byte, blockSize))
padded := e.pad(plaintext, B, P)
cbcCiphertext := make([]byte, len(padded))
cbc.CryptBlocks(cbcCiphertext, padded)
return cbcCiphertext[len(cbcCiphertext)-blockSize:]
}
func (e *eax) pad(plaintext, B, P []byte) []byte {
// if |M| in {n, 2n, 3n, ...}
blockSize := e.block.BlockSize()
if len(plaintext) != 0 && len(plaintext)%blockSize == 0 {
return byteutil.RightXor(plaintext, B)
}
// else return (M || 1 || 0^(n−1−(|M| % n))) xor→ P
ending := make([]byte, blockSize-len(plaintext)%blockSize)
ending[0] = 0x80
padded := append(plaintext, ending...)
return byteutil.RightXor(padded, P)
}
func eaxError(err string) error {
return errors.New("crypto/eax: " + err)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/eax/eax_test_vectors.go
================================================
package eax
// Test vectors from
// https://web.cs.ucdavis.edu/~rogaway/papers/eax.pdf
var testVectors = []struct {
msg, key, nonce, header, ciphertext string
}{
{"",
"233952DEE4D5ED5F9B9C6D6FF80FF478",
"62EC67F9C3A4A407FCB2A8C49031A8B3",
"6BFB914FD07EAE6B",
"E037830E8389F27B025A2D6527E79D01"},
{"F7FB",
"91945D3F4DCBEE0BF45EF52255F095A4",
"BECAF043B0A23D843194BA972C66DEBD",
"FA3BFD4806EB53FA",
"19DD5C4C9331049D0BDAB0277408F67967E5"},
{"1A47CB4933",
"01F74AD64077F2E704C0F60ADA3DD523",
"70C3DB4F0D26368400A10ED05D2BFF5E",
"234A3463C1264AC6",
"D851D5BAE03A59F238A23E39199DC9266626C40F80"},
{"481C9E39B1",
"D07CF6CBB7F313BDDE66B727AFD3C5E8",
"8408DFFF3C1A2B1292DC199E46B7D617",
"33CCE2EABFF5A79D",
"632A9D131AD4C168A4225D8E1FF755939974A7BEDE"},
{"40D0C07DA5E4",
"35B6D0580005BBC12B0587124557D2C2",
"FDB6B06676EEDC5C61D74276E1F8E816",
"AEB96EAEBE2970E9",
"071DFE16C675CB0677E536F73AFE6A14B74EE49844DD"},
{"4DE3B35C3FC039245BD1FB7D",
"BD8E6E11475E60B268784C38C62FEB22",
"6EAC5C93072D8E8513F750935E46DA1B",
"D4482D1CA78DCE0F",
"835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F"},
{"8B0A79306C9CE7ED99DAE4F87F8DD61636",
"7C77D6E813BED5AC98BAA417477A2E7D",
"1A8C98DCD73D38393B2BF1569DEEFC19",
"65D2017990D62528",
"02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2"},
{"1BDA122BCE8A8DBAF1877D962B8592DD2D56",
"5FFF20CAFAB119CA2FC73549E20F5B0D",
"DDE59B97D722156D4D9AFF2BC7559826",
"54B9F04E6A09189A",
"2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A"},
{"6CF36720872B8513F6EAB1A8A44438D5EF11",
"A4A4782BCFFD3EC5E7EF6D8C34A56123",
"B781FCF2F75FA5A8DE97A9CA48E522EC",
"899A175897561D7E",
"0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700"},
{"CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7",
"8395FCF1E95BEBD697BD010BC766AAC3",
"22E7ADD93CFC6393C57EC0B3C17D6B44",
"126735FCC320D25A",
"CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E"},
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/eax/random_vectors.go
================================================
// These vectors include key length in {128, 192, 256}, tag size 128, and
// random nonce, header, and plaintext lengths.
// This file was automatically generated.
package eax
var randomVectors = []struct {
key, nonce, header, plaintext, ciphertext string
}{
{"DFDE093F36B0356E5A81F609786982E3",
"1D8AC604419001816905BA72B14CED7E",
"152A1517A998D7A24163FCDD146DE81AC347C8B97088F502093C1ABB8F6E33D9A219C34D7603A18B1F5ABE02E56661B7D7F67E81EC08C1302EF38D80A859486D450E94A4F26AD9E68EEBBC0C857A0FC5CF9E641D63D565A7E361BC8908F5A8DC8FD6",
"1C8EAAB71077FE18B39730A3156ADE29C5EE824C7EE86ED2A253B775603FB237116E654F6FEC588DD27F523A0E01246FE73FE348491F2A8E9ABC6CA58D663F71CDBCF4AD798BE46C42AE6EE8B599DB44A1A48D7BBBBA0F7D2750181E1C5E66967F7D57CBD30AFBDA5727",
"79E7E150934BBEBF7013F61C60462A14D8B15AF7A248AFB8A344EF021C1500E16666891D6E973D8BB56B71A371F12CA34660C4410C016982B20F547E3762A58B7BF4F20236CADCF559E2BE7D783B13723B2741FC7CDC8997D839E39A3DDD2BADB96743DD7049F1BDB0516A262869915B3F70498AFB7B191BF960"},
{"F10619EF02E5D94D7550EB84ED364A21",
"8DC0D4F2F745BBAE835CC5574B942D20",
"FE561358F2E8DF7E1024FF1AE9A8D36EBD01352214505CB99D644777A8A1F6027FA2BDBFC529A9B91136D5F2416CFC5F0F4EC3A1AFD32BDDA23CA504C5A5CB451785FABF4DFE4CD50D817491991A60615B30286361C100A95D1712F2A45F8E374461F4CA2B",
"D7B5A971FC219631D30EFC3664AE3127D9CF3097DAD9C24AC7905D15E8D9B25B026B31D68CAE00975CDB81EB1FD96FD5E1A12E2BB83FA25F1B1D91363457657FC03875C27F2946C5",
"2F336ED42D3CC38FC61660C4CD60BA4BD438B05F5965D8B7B399D2E7167F5D34F792D318F94DB15D67463AC449E13D568CC09BFCE32A35EE3EE96A041927680AE329811811E27F2D1E8E657707AF99BA96D13A478D695D59"},
{"429F514EFC64D98A698A9247274CFF45",
"976AA5EB072F912D126ACEBC954FEC38",
"A71D89DC5B6CEDBB7451A27C3C2CAE09126DB4C421",
"5632FE62AB1DC549D54D3BC3FC868ACCEDEFD9ECF5E9F8",
"848AE4306CA8C7F416F8707625B7F55881C0AB430353A5C967CDA2DA787F581A70E34DBEBB2385"},
{"398138F309085F47F8457CDF53895A63",
"F8A8A7F2D28E5FFF7BBC2F24353F7A36",
"5D633C21BA7764B8855CAB586F3746E236AD486039C83C6B56EFA9C651D38A41D6B20DAEE3418BFEA44B8BD6",
"A3BBAA91920AF5E10659818B1B3B300AC79BFC129C8329E75251F73A66D3AE0128EB91D5031E0A65C329DB7D1E9C0493E268",
"D078097267606E5FB07CFB7E2B4B718172A82C6A4CEE65D549A4DFB9838003BD2FBF64A7A66988AC1A632FD88F9E9FBB57C5A78AD2E086EACBA3DB68511D81C2970A"},
{"7A4151EBD3901B42CBA45DAFB2E931BA",
"0FC88ACEE74DD538040321C330974EB8",
"250464FB04733BAB934C59E6AD2D6AE8D662CBCFEFBE61E5A308D4211E58C4C25935B72C69107722E946BFCBF416796600542D76AEB73F2B25BF53BAF97BDEB36ED3A7A51C31E7F170EB897457E7C17571D1BA0A908954E9",
"88C41F3EBEC23FAB8A362D969CAC810FAD4F7CA6A7F7D0D44F060F92E37E1183768DD4A8C733F71C96058D362A39876D183B86C103DE",
"74A25B2182C51096D48A870D80F18E1CE15867778E34FCBA6BD7BFB3739FDCD42AD0F2D9F4EBA29085285C6048C15BCE5E5166F1F962D3337AA88E6062F05523029D0A7F0BF9"},
{"BFB147E1CD5459424F8C0271FC0E0DC5",
"EABCC126442BF373969EA3015988CC45",
"4C0880E1D71AA2C7",
"BE1B5EC78FBF73E7A6682B21BA7E0E5D2D1C7ABE",
"5660D7C1380E2F306895B1402CB2D6C37876504276B414D120F4CF92FDDDBB293A238EA0"},
{"595DD6F52D18BC2CA8EB4EDAA18D9FA3",
"0F84B5D36CF4BC3B863313AF3B4D2E97",
"30AE6CC5F99580F12A779D98BD379A60948020C0B6FBD5746B30BA3A15C6CD33DAF376C70A9F15B6C0EB410A93161F7958AE23",
"8EF3687A1642B070970B0B91462229D1D76ABC154D18211F7152AA9FF368",
"317C1DDB11417E5A9CC4DDE7FDFF6659A5AC4B31DE025212580A05CDAC6024D3E4AE7C2966E52B9129E9ECDBED86"},
{"44E6F2DC8FDC778AD007137D11410F50",
"270A237AD977F7187AA6C158A0BAB24F",
"509B0F0EB12E2AA5C5BA2DE553C07FAF4CE0C9E926531AA709A3D6224FCB783ACCF1559E10B1123EBB7D52E8AB54E6B5352A9ED0D04124BF0E9D9BACFD7E32B817B2E625F5EE94A64EDE9E470DE7FE6886C19B294F9F828209FE257A78",
"8B3D7815DF25618A5D0C55A601711881483878F113A12EC36CF64900549A3199555528559DC118F789788A55FAFD944E6E99A9CA3F72F238CD3F4D88223F7A745992B3FAED1848",
"1CC00D79F7AD82FDA71B58D286E5F34D0CC4CEF30704E771CC1E50746BDF83E182B078DB27149A42BAE619DF0F85B0B1090AD55D3B4471B0D6F6ECCD09C8F876B30081F0E7537A9624F8AAF29DA85E324122EFB4D68A56"},
{"BB7BC352A03044B4428D8DBB4B0701FDEC4649FD17B81452",
"8B4BBE26CCD9859DCD84884159D6B0A4",
"2212BEB0E78E0F044A86944CF33C8D5C80D9DBE1034BF3BCF73611835C7D3A52F5BD2D81B68FD681B68540A496EE5DA16FD8AC8824E60E1EC2042BE28FB0BFAD4E4B03596446BDD8C37D936D9B3D5295BE19F19CF5ACE1D33A46C952CE4DE5C12F92C1DD051E04AEED",
"9037234CC44FFF828FABED3A7084AF40FA7ABFF8E0C0EFB57A1CC361E18FC4FAC1AB54F3ABFE9FF77263ACE16C3A",
"A9391B805CCD956081E0B63D282BEA46E7025126F1C1631239C33E92AA6F92CD56E5A4C56F00FF9658E93D48AF4EF0EF81628E34AD4DB0CDAEDCD2A17EE7"},
{"99C0AD703196D2F60A74E6B378B838B31F82EA861F06FC4E",
"92745C018AA708ECFEB1667E9F3F1B01",
"828C69F376C0C0EC651C67749C69577D589EE39E51404D80EBF70C8660A8F5FD375473F4A7C611D59CB546A605D67446CE2AA844135FCD78BB5FBC90222A00D42920BB1D7EEDFB0C4672554F583EF23184F89063CDECBE482367B5F9AF3ACBC3AF61392BD94CBCD9B64677",
"A879214658FD0A5B0E09836639BF82E05EC7A5EF71D4701934BDA228435C68AC3D5CEB54997878B06A655EEACEFB1345C15867E7FE6C6423660C8B88DF128EBD6BCD85118DBAE16E9252FFB204324E5C8F38CA97759BDBF3CB0083",
"51FE87996F194A2585E438B023B345439EA60D1AEBED4650CDAF48A4D4EEC4FC77DC71CC4B09D3BEEF8B7B7AF716CE2B4EFFB3AC9E6323C18AC35E0AA6E2BBBC8889490EB6226C896B0D105EAB42BFE7053CCF00ED66BA94C1BA09A792AA873F0C3B26C5C5F9A936E57B25"},
{"7086816D00D648FB8304AA8C9E552E1B69A9955FB59B25D1",
"0F45CF7F0BF31CCEB85D9DA10F4D749F",
"93F27C60A417D9F0669E86ACC784FC8917B502DAF30A6338F11B30B94D74FEFE2F8BE1BBE2EAD10FAB7EED3C6F72B7C3ECEE1937C32ED4970A6404E139209C05",
"877F046601F3CBE4FB1491943FA29487E738F94B99AF206262A1D6FF856C9AA0B8D4D08A54370C98F8E88FA3DCC2B14C1F76D71B2A4C7963AEE8AF960464C5BEC8357AD00DC8",
"FE96906B895CE6A8E72BC72344E2C8BB3C63113D70EAFA26C299BAFE77A8A6568172EB447FB3E86648A0AF3512DEB1AAC0819F3EC553903BF28A9FB0F43411237A774BF9EE03E445D280FBB9CD12B9BAAB6EF5E52691"},
{"062F65A896D5BF1401BADFF70E91B458E1F9BD4888CB2E4D",
"5B11EA1D6008EBB41CF892FCA5B943D1",
"BAF4FF5C8242",
"A8870E091238355984EB2F7D61A865B9170F440BFF999A5993DD41A10F4440D21FF948DDA2BF663B2E03AC3324492DC5E40262ECC6A65C07672353BE23E7FB3A9D79FF6AA38D97960905A38DECC312CB6A59E5467ECF06C311CD43ADC0B543EDF34FE8BE611F176460D5627CA51F8F8D9FED71F55C",
"B10E127A632172CF8AA7539B140D2C9C2590E6F28C3CB892FC498FCE56A34F732FBFF32E79C7B9747D9094E8635A0C084D6F0247F9768FB5FF83493799A9BEC6C39572120C40E9292C8C947AE8573462A9108C36D9D7112E6995AE5867E6C8BB387D1C5D4BEF524F391B9FD9F0A3B4BFA079E915BCD920185CFD38D114C558928BD7D47877"},
{"38A8E45D6D705A11AF58AED5A1344896998EACF359F2E26A",
"FD82B5B31804FF47D44199B533D0CF84",
"DE454D4E62FE879F2050EE3E25853623D3E9AC52EEC1A1779A48CFAF5ECA0BFDE44749391866D1",
"B804",
"164BB965C05EBE0931A1A63293EDF9C38C27"},
{"34C33C97C6D7A0850DA94D78A58DC61EC717CD7574833068",
"343BE00DA9483F05C14F2E9EB8EA6AE8",
"78312A43EFDE3CAE34A65796FF059A3FE15304EEA5CF1D9306949FE5BF3349D4977D4EBE76C040FE894C5949E4E4D6681153DA87FB9AC5062063CA2EA183566343362370944CE0362D25FC195E124FD60E8682E665D13F2229DDA3E4B2CB1DCA",
"CC11BB284B1153578E4A5ED9D937B869DAF00F5B1960C23455CA9CC43F486A3BE0B66254F1041F04FDF459C8640465B6E1D2CF899A381451E8E7FCB50CF87823BE77E24B132BBEEDC72E53369B275E1D8F49ECE59F4F215230AC4FE133FC80E4F634EE80BA4682B62C86",
"E7F703DC31A95E3A4919FF957836CB76C063D81702AEA4703E1C2BF30831E58C4609D626EC6810E12EAA5B930F049FF9EFC22C3E3F1EBD4A1FB285CB02A1AC5AD46B425199FC0A85670A5C4E3DAA9636C8F64C199F42F18AAC8EA7457FD377F322DD7752D7D01B946C8F0A97E6113F0D50106F319AFD291AAACE"},
{"C6ECF7F053573E403E61B83052A343D93CBCC179D1E835BE",
"E280E13D7367042E3AA09A80111B6184",
"21486C9D7A9647",
"5F2639AFA6F17931853791CD8C92382BBB677FD72D0AB1A080D0E49BFAA21810E963E4FACD422E92F65CBFAD5884A60CD94740DF31AF02F95AA57DA0C4401B0ED906",
"5C51DB20755302070C45F52E50128A67C8B2E4ED0EACB7E29998CCE2E8C289DD5655913EC1A51CC3AABE5CDC2402B2BE7D6D4BF6945F266FBD70BA9F37109067157AE7530678B45F64475D4EBFCB5FFF46A5"},
{"5EC6CF7401BC57B18EF154E8C38ACCA8959E57D2F3975FF5",
"656B41CB3F9CF8C08BAD7EBFC80BD225",
"6B817C2906E2AF425861A7EF59BA5801F143EE2A139EE72697CDE168B4",
"2C0E1DDC9B1E5389BA63845B18B1F8A1DB062037151BCC56EF7C21C0BB4DAE366636BBA975685D7CC5A94AFBE89C769016388C56FB7B57CE750A12B718A8BDCF70E80E8659A8330EFC8F86640F21735E8C80E23FE43ABF23507CE3F964AE4EC99D",
"ED780CF911E6D1AA8C979B889B0B9DC1ABE261832980BDBFB576901D9EF5AB8048998E31A15BE54B3E5845A4D136AD24D0BDA1C3006168DF2F8AC06729CB0818867398150020131D8F04EDF1923758C9EABB5F735DE5EA1758D4BC0ACFCA98AFD202E9839B8720253693B874C65586C6F0"},
{"C92F678EB2208662F5BCF3403EC05F5961E957908A3E79421E1D25FC19054153",
"DA0F3A40983D92F2D4C01FED33C7A192",
"2B6E9D26DB406A0FAB47608657AA10EFC2B4AA5F459B29FF85AC9A40BFFE7AEB04F77E9A11FAAA116D7F6D4DA417671A9AB02C588E0EF59CB1BFB4B1CC931B63A3B3A159FCEC97A04D1E6F0C7E6A9CEF6B0ABB04758A69F1FE754DF4C2610E8C46B6CF413BDB31351D55BEDCB7B4A13A1C98E10984475E0F2F957853",
"F37326A80E08",
"83519E53E321D334F7C10B568183775C0E9AAE55F806"},
{"6847E0491BE57E72995D186D50094B0B3593957A5146798FCE68B287B2FB37B5",
"3EE1182AEBB19A02B128F28E1D5F7F99",
"D9F35ABB16D776CE",
"DB7566ED8EA95BDF837F23DB277BAFBC5E70D1105ADFD0D9EF15475051B1EF94709C67DCA9F8D5",
"2CDCED0C9EBD6E2A508822A685F7DCD1CDD99E7A5FCA786C234E7F7F1D27EC49751AD5DCFA30C5EDA87C43CAE3B919B6BBCFE34C8EDA59"},
{"82B019673642C08388D3E42075A4D5D587558C229E4AB8F660E37650C4C41A0A",
"336F5D681E0410FAE7B607246092C6DC",
"D430CBD8FE435B64214E9E9CDC5DE99D31CFCFB8C10AA0587A49DF276611",
"998404153AD77003E1737EDE93ED79859EE6DCCA93CB40C4363AA817ABF2DBBD46E42A14A7183B6CC01E12A577888141363D0AE011EB6E8D28C0B235",
"9BEF69EEB60BD3D6065707B7557F25292A8872857CFBD24F2F3C088E4450995333088DA50FD9121221C504DF1D0CD5EFE6A12666C5D5BB12282CF4C19906E9CFAB97E9BDF7F49DC17CFC384B"},
{"747B2E269B1859F0622C15C8BAD6A725028B1F94B8DB7326948D1E6ED663A8BC",
"AB91F7245DDCE3F1C747872D47BE0A8A",
"3B03F786EF1DDD76E1D42646DA4CD2A5165DC5383CE86D1A0B5F13F910DC278A4E451EE0192CBA178E13B3BA27FDC7840DF73D2E104B",
"6B803F4701114F3E5FE21718845F8416F70F626303F545BE197189E0A2BA396F37CE06D389EB2658BC7D56D67868708F6D0D32",
"1570DDB0BCE75AA25D1957A287A2C36B1A5F2270186DA81BA6112B7F43B0F3D1D0ED072591DCF1F1C99BBB25621FC39B896FF9BD9413A2845363A9DCD310C32CF98E57"},
{"02E59853FB29AEDA0FE1C5F19180AD99A12FF2F144670BB2B8BADF09AD812E0A",
"C691294EF67CD04D1B9242AF83DD1421",
"879334DAE3",
"1E17F46A98FEF5CBB40759D95354",
"FED8C3FF27DDF6313AED444A2985B36CBA268AAD6AAC563C0BA28F6DB5DB"},
{"F6C1FB9B4188F2288FF03BD716023198C3582CF2A037FC2F29760916C2B7FCDB",
"4228DA0678CA3534588859E77DFF014C",
"D8153CAF35539A61DD8D05B3C9B44F01E564FB9348BCD09A1C23B84195171308861058F0A3CD2A55B912A3AAEE06FF4D356C77275828F2157C2FC7C115DA39E443210CCC56BEDB0CC99BBFB227ABD5CC454F4E7F547C7378A659EEB6A7E809101A84F866503CB18D4484E1FA09B3EC7FC75EB2E35270800AA7",
"23B660A779AD285704B12EC1C580387A47BEC7B00D452C6570",
"5AA642BBABA8E49849002A2FAF31DB8FC7773EFDD656E469CEC19B3206D4174C9A263D0A05484261F6"},
{"8FF6086F1FADB9A3FBE245EAC52640C43B39D43F89526BB5A6EBA47710931446",
"943188480C99437495958B0AE4831AA9",
"AD5CD0BDA426F6EBA23C8EB23DC73FF9FEC173355EDBD6C9344C4C4383F211888F7CE6B29899A6801DF6B38651A7C77150941A",
"80CD5EA8D7F81DDF5070B934937912E8F541A5301877528EB41AB60C020968D459960ED8FB73083329841A",
"ABAE8EB7F36FCA2362551E72DAC890BA1BB6794797E0FC3B67426EC9372726ED4725D379EA0AC9147E48DCD0005C502863C2C5358A38817C8264B5"},
{"A083B54E6B1FE01B65D42FCD248F97BB477A41462BBFE6FD591006C022C8FD84",
"B0490F5BD68A52459556B3749ACDF40E",
"8892E047DA5CFBBDF7F3CFCBD1BD21C6D4C80774B1826999234394BD3E513CC7C222BB40E1E3140A152F19B3802F0D036C24A590512AD0E8",
"D7B15752789DC94ED0F36778A5C7BBB207BEC32BAC66E702B39966F06E381E090C6757653C3D26A81EC6AD6C364D66867A334C91BB0B8A8A4B6EACDF0783D09010AEBA2DD2062308FE99CC1F",
"C071280A732ADC93DF272BF1E613B2BB7D46FC6665EF2DC1671F3E211D6BDE1D6ADDD28DF3AA2E47053FC8BB8AE9271EC8BC8B2CFFA320D225B451685B6D23ACEFDD241FE284F8ADC8DB07F456985B14330BBB66E0FB212213E05B3E"},
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/internal/byteutil/byteutil.go
================================================
// Copyright (C) 2019 ProtonTech AG
// This file contains necessary tools for the aex and ocb packages.
//
// These functions SHOULD NOT be used elsewhere, since they are optimized for
// specific input nature in the EAX and OCB modes of operation.
package byteutil
// GfnDouble computes 2 * input in the field of 2^n elements.
// The irreducible polynomial in the finite field for n=128 is
// x^128 + x^7 + x^2 + x + 1 (equals 0x87)
// Constant-time execution in order to avoid side-channel attacks
func GfnDouble(input []byte) []byte {
if len(input) != 16 {
panic("Doubling in GFn only implemented for n = 128")
}
// If the first bit is zero, return 2L = L << 1
// Else return (L << 1) xor 0^120 10000111
shifted := ShiftBytesLeft(input)
shifted[15] ^= ((input[0] >> 7) * 0x87)
return shifted
}
// ShiftBytesLeft outputs the byte array corresponding to x << 1 in binary.
func ShiftBytesLeft(x []byte) []byte {
l := len(x)
dst := make([]byte, l)
for i := 0; i < l-1; i++ {
dst[i] = (x[i] << 1) | (x[i+1] >> 7)
}
dst[l-1] = x[l-1] << 1
return dst
}
// ShiftNBytesLeft puts in dst the byte array corresponding to x << n in binary.
func ShiftNBytesLeft(dst, x []byte, n int) {
// Erase first n / 8 bytes
copy(dst, x[n/8:])
// Shift the remaining n % 8 bits
bits := uint(n % 8)
l := len(dst)
for i := 0; i < l-1; i++ {
dst[i] = (dst[i] << bits) | (dst[i+1] >> uint(8-bits))
}
dst[l-1] = dst[l-1] << bits
// Append trailing zeroes
dst = append(dst, make([]byte, n/8)...)
}
// XorBytesMut replaces X with X XOR Y. len(X) must be >= len(Y).
func XorBytesMut(X, Y []byte) {
for i := 0; i < len(Y); i++ {
X[i] ^= Y[i]
}
}
// XorBytes puts X XOR Y into Z. len(Z) and len(X) must be >= len(Y).
func XorBytes(Z, X, Y []byte) {
for i := 0; i < len(Y); i++ {
Z[i] = X[i] ^ Y[i]
}
}
// RightXor XORs smaller input (assumed Y) at the right of the larger input (assumed X)
func RightXor(X, Y []byte) []byte {
offset := len(X) - len(Y)
xored := make([]byte, len(X))
copy(xored, X)
for i := 0; i < len(Y); i++ {
xored[offset+i] ^= Y[i]
}
return xored
}
// SliceForAppend takes a slice and a requested number of bytes. It returns a
// slice with the contents of the given slice followed by that many bytes and a
// second slice that aliases into it and contains only the extra bytes. If the
// original slice has sufficient capacity then no allocation is performed.
func SliceForAppend(in []byte, n int) (head, tail []byte) {
if total := len(in) + n; cap(in) >= total {
head = in[:total]
} else {
head = make([]byte, total)
copy(head, in)
}
tail = head[len(in):]
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/ocb/ocb.go
================================================
// Copyright (C) 2019 ProtonTech AG
// Package ocb provides an implementation of the OCB (offset codebook) mode of
// operation, as described in RFC-7253 of the IRTF and in Rogaway, Bellare,
// Black and Krovetz - OCB: A BLOCK-CIPHER MODE OF OPERATION FOR EFFICIENT
// AUTHENTICATED ENCRYPTION (2003).
// Security considerations (from RFC-7253): A private key MUST NOT be used to
// encrypt more than 2^48 blocks. Tag length should be at least 12 bytes (a
// brute-force forging adversary succeeds after 2^{tag length} attempts). A
// single key SHOULD NOT be used to decrypt ciphertext with different tag
// lengths. Nonces need not be secret, but MUST NOT be reused.
// This package only supports underlying block ciphers with 128-bit blocks,
// such as AES-{128, 192, 256}, but may be extended to other sizes.
package ocb
import (
"bytes"
"crypto/cipher"
"crypto/subtle"
"errors"
"math/bits"
"github.com/ProtonMail/go-crypto/internal/byteutil"
)
type ocb struct {
block cipher.Block
tagSize int
nonceSize int
mask mask
// Optimized en/decrypt: For each nonce N used to en/decrypt, the 'Ktop'
// internal variable can be reused for en/decrypting with nonces sharing
// all but the last 6 bits with N. The prefix of the first nonce used to
// compute the new Ktop, and the Ktop value itself, are stored in
// reusableKtop. If using incremental nonces, this saves one block cipher
// call every 63 out of 64 OCB encryptions, and stores one nonce and one
// output of the block cipher in memory only.
reusableKtop reusableKtop
}
type mask struct {
// L_*, L_$, (L_i)_{i ∈ N}
lAst []byte
lDol []byte
L [][]byte
}
type reusableKtop struct {
noncePrefix []byte
Ktop []byte
}
const (
defaultTagSize = 16
defaultNonceSize = 15
)
const (
enc = iota
dec
)
func (o *ocb) NonceSize() int {
return o.nonceSize
}
func (o *ocb) Overhead() int {
return o.tagSize
}
// NewOCB returns an OCB instance with the given block cipher and default
// tag and nonce sizes.
func NewOCB(block cipher.Block) (cipher.AEAD, error) {
return NewOCBWithNonceAndTagSize(block, defaultNonceSize, defaultTagSize)
}
// NewOCBWithNonceAndTagSize returns an OCB instance with the given block
// cipher, nonce length, and tag length. Panics on zero nonceSize and
// exceedingly long tag size.
//
// It is recommended to use at least 12 bytes as tag length.
func NewOCBWithNonceAndTagSize(
block cipher.Block, nonceSize, tagSize int) (cipher.AEAD, error) {
if block.BlockSize() != 16 {
return nil, ocbError("Block cipher must have 128-bit blocks")
}
if nonceSize < 1 {
return nil, ocbError("Incorrect nonce length")
}
if nonceSize >= block.BlockSize() {
return nil, ocbError("Nonce length exceeds blocksize - 1")
}
if tagSize > block.BlockSize() {
return nil, ocbError("Custom tag length exceeds blocksize")
}
return &ocb{
block: block,
tagSize: tagSize,
nonceSize: nonceSize,
mask: initializeMaskTable(block),
reusableKtop: reusableKtop{
noncePrefix: nil,
Ktop: nil,
},
}, nil
}
func (o *ocb) Seal(dst, nonce, plaintext, adata []byte) []byte {
if len(nonce) > o.nonceSize {
panic("crypto/ocb: Incorrect nonce length given to OCB")
}
sep := len(plaintext)
ret, out := byteutil.SliceForAppend(dst, sep+o.tagSize)
tag := o.crypt(enc, out[:sep], nonce, adata, plaintext)
copy(out[sep:], tag)
return ret
}
func (o *ocb) Open(dst, nonce, ciphertext, adata []byte) ([]byte, error) {
if len(nonce) > o.nonceSize {
panic("Nonce too long for this instance")
}
if len(ciphertext) < o.tagSize {
return nil, ocbError("Ciphertext shorter than tag length")
}
sep := len(ciphertext) - o.tagSize
ret, out := byteutil.SliceForAppend(dst, sep)
ciphertextData := ciphertext[:sep]
tag := o.crypt(dec, out, nonce, adata, ciphertextData)
if subtle.ConstantTimeCompare(tag, ciphertext[sep:]) == 1 {
return ret, nil
}
for i := range out {
out[i] = 0
}
return nil, ocbError("Tag authentication failed")
}
// On instruction enc (resp. dec), crypt is the encrypt (resp. decrypt)
// function. It writes the resulting plain/ciphertext into Y and returns
// the tag.
func (o *ocb) crypt(instruction int, Y, nonce, adata, X []byte) []byte {
//
// Consider X as a sequence of 128-bit blocks
//
// Note: For encryption (resp. decryption), X is the plaintext (resp., the
// ciphertext without the tag).
blockSize := o.block.BlockSize()
//
// Nonce-dependent and per-encryption variables
//
// Zero out the last 6 bits of the nonce into truncatedNonce to see if Ktop
// is already computed.
truncatedNonce := make([]byte, len(nonce))
copy(truncatedNonce, nonce)
truncatedNonce[len(truncatedNonce)-1] &= 192
var Ktop []byte
if bytes.Equal(truncatedNonce, o.reusableKtop.noncePrefix) {
Ktop = o.reusableKtop.Ktop
} else {
// Nonce = num2str(TAGLEN mod 128, 7) || zeros(120 - bitlen(N)) || 1 || N
paddedNonce := append(make([]byte, blockSize-1-len(nonce)), 1)
paddedNonce = append(paddedNonce, truncatedNonce...)
paddedNonce[0] |= byte(((8 * o.tagSize) % (8 * blockSize)) << 1)
// Last 6 bits of paddedNonce are already zero. Encrypt into Ktop
paddedNonce[blockSize-1] &= 192
Ktop = paddedNonce
o.block.Encrypt(Ktop, Ktop)
o.reusableKtop.noncePrefix = truncatedNonce
o.reusableKtop.Ktop = Ktop
}
// Stretch = Ktop || ((lower half of Ktop) XOR (lower half of Ktop << 8))
xorHalves := make([]byte, blockSize/2)
byteutil.XorBytes(xorHalves, Ktop[:blockSize/2], Ktop[1:1+blockSize/2])
stretch := append(Ktop, xorHalves...)
bottom := int(nonce[len(nonce)-1] & 63)
offset := make([]byte, len(stretch))
byteutil.ShiftNBytesLeft(offset, stretch, bottom)
offset = offset[:blockSize]
//
// Process any whole blocks
//
// Note: For encryption Y is ciphertext || tag, for decryption Y is
// plaintext || tag.
checksum := make([]byte, blockSize)
m := len(X) / blockSize
for i := 0; i < m; i++ {
index := bits.TrailingZeros(uint(i + 1))
if len(o.mask.L)-1 < index {
o.mask.extendTable(index)
}
byteutil.XorBytesMut(offset, o.mask.L[bits.TrailingZeros(uint(i+1))])
blockX := X[i*blockSize : (i+1)*blockSize]
blockY := Y[i*blockSize : (i+1)*blockSize]
switch instruction {
case enc:
byteutil.XorBytesMut(checksum, blockX)
byteutil.XorBytes(blockY, blockX, offset)
o.block.Encrypt(blockY, blockY)
byteutil.XorBytesMut(blockY, offset)
case dec:
byteutil.XorBytes(blockY, blockX, offset)
o.block.Decrypt(blockY, blockY)
byteutil.XorBytesMut(blockY, offset)
byteutil.XorBytesMut(checksum, blockY)
}
}
//
// Process any final partial block and compute raw tag
//
tag := make([]byte, blockSize)
if len(X)%blockSize != 0 {
byteutil.XorBytesMut(offset, o.mask.lAst)
pad := make([]byte, blockSize)
o.block.Encrypt(pad, offset)
chunkX := X[blockSize*m:]
chunkY := Y[blockSize*m : len(X)]
switch instruction {
case enc:
byteutil.XorBytesMut(checksum, chunkX)
checksum[len(chunkX)] ^= 128
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
// P_* || bit(1) || zeroes(127) - len(P_*)
case dec:
byteutil.XorBytes(chunkY, chunkX, pad[:len(chunkX)])
// P_* || bit(1) || zeroes(127) - len(P_*)
byteutil.XorBytesMut(checksum, chunkY)
checksum[len(chunkY)] ^= 128
}
}
byteutil.XorBytes(tag, checksum, offset)
byteutil.XorBytesMut(tag, o.mask.lDol)
o.block.Encrypt(tag, tag)
byteutil.XorBytesMut(tag, o.hash(adata))
return tag[:o.tagSize]
}
// This hash function is used to compute the tag. Per design, on empty input it
// returns a slice of zeros, of the same length as the underlying block cipher
// block size.
func (o *ocb) hash(adata []byte) []byte {
//
// Consider A as a sequence of 128-bit blocks
//
A := make([]byte, len(adata))
copy(A, adata)
blockSize := o.block.BlockSize()
//
// Process any whole blocks
//
sum := make([]byte, blockSize)
offset := make([]byte, blockSize)
m := len(A) / blockSize
for i := 0; i < m; i++ {
chunk := A[blockSize*i : blockSize*(i+1)]
index := bits.TrailingZeros(uint(i + 1))
// If the mask table is too short
if len(o.mask.L)-1 < index {
o.mask.extendTable(index)
}
byteutil.XorBytesMut(offset, o.mask.L[index])
byteutil.XorBytesMut(chunk, offset)
o.block.Encrypt(chunk, chunk)
byteutil.XorBytesMut(sum, chunk)
}
//
// Process any final partial block; compute final hash value
//
if len(A)%blockSize != 0 {
byteutil.XorBytesMut(offset, o.mask.lAst)
// Pad block with 1 || 0 ^ 127 - bitlength(a)
ending := make([]byte, blockSize-len(A)%blockSize)
ending[0] = 0x80
encrypted := append(A[blockSize*m:], ending...)
byteutil.XorBytesMut(encrypted, offset)
o.block.Encrypt(encrypted, encrypted)
byteutil.XorBytesMut(sum, encrypted)
}
return sum
}
func initializeMaskTable(block cipher.Block) mask {
//
// Key-dependent variables
//
lAst := make([]byte, block.BlockSize())
block.Encrypt(lAst, lAst)
lDol := byteutil.GfnDouble(lAst)
L := make([][]byte, 1)
L[0] = byteutil.GfnDouble(lDol)
return mask{
lAst: lAst,
lDol: lDol,
L: L,
}
}
// Extends the L array of mask m up to L[limit], with L[i] = GfnDouble(L[i-1])
func (m *mask) extendTable(limit int) {
for i := len(m.L); i <= limit; i++ {
m.L = append(m.L, byteutil.GfnDouble(m.L[i-1]))
}
}
func ocbError(err string) error {
return errors.New("crypto/ocb: " + err)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/ocb/random_vectors.go
================================================
// In the test vectors provided by RFC 7253, the "bottom"
// internal variable, which defines "offset" for the first time, does not
// exceed 15. However, it can attain values up to 63.
// These vectors include key length in {128, 192, 256}, tag size 128, and
// random nonce, header, and plaintext lengths.
// This file was automatically generated.
package ocb
var randomVectors = []struct {
key, nonce, header, plaintext, ciphertext string
}{
{"9438C5D599308EAF13F800D2D31EA7F0",
"C38EE4801BEBFFA1CD8635BE",
"0E507B7DADD8A98CDFE272D3CB6B3E8332B56AE583FB049C0874D4200BED16BD1A044182434E9DA0E841F182DFD5B3016B34641CED0784F1745F63AB3D0DA22D3351C9EF9A658B8081E24498EBF61FCE40DA6D8E184536",
"962D227786FB8913A8BAD5DC3250",
"EEDEF5FFA5986D1E3BF86DDD33EF9ADC79DCA06E215FA772CCBA814F63AD"},
{"BA7DE631C7D6712167C6724F5B9A2B1D",
"35263EBDA05765DC0E71F1F5",
"0103257B4224507C0242FEFE821EA7FA42E0A82863E5F8B68F7D881B4B44FA428A2B6B21D2F591260802D8AB6D83",
"9D6D1FC93AE8A64E7889B7B2E3521EFA9B920A8DDB692E6F833DDC4A38AFA535E5E2A3ED82CB7E26404AB86C54D01C4668F28398C2DF33D5D561CBA1C8DCFA7A912F5048E545B59483C0E3221F54B14DAA2E4EB657B3BEF9554F34CAD69B2724AE962D3D8A",
"E93852D1985C5E775655E937FA79CE5BF28A585F2AF53A5018853B9634BE3C84499AC0081918FDCE0624494D60E25F76ACD6853AC7576E3C350F332249BFCABD4E73CEABC36BE4EDDA40914E598AE74174A0D7442149B26990899491BDDFE8FC54D6C18E83AE9E9A6FFBF5D376565633862EEAD88D"},
{"2E74B25289F6FD3E578C24866E9C72A5",
"FD912F15025AF8414642BA1D1D",
"FB5FB8C26F365EEDAB5FE260C6E3CCD27806729C8335F146063A7F9EA93290E56CF84576EB446350D22AD730547C267B1F0BBB97EB34E1E2C41A",
"6C092EBF78F76EE8C1C6E592277D9545BA16EDB67BC7D8480B9827702DC2F8A129E2B08A2CE710CA7E1DA45CE162BB6CD4B512E632116E2211D3C90871EFB06B8D4B902681C7FB",
"6AC0A77F26531BF4F354A1737F99E49BE32ECD909A7A71AD69352906F54B08A9CE9B8CA5D724CBFFC5673437F23F630697F3B84117A1431D6FA8CC13A974FB4AD360300522E09511B99E71065D5AC4BBCB1D791E864EF4"},
{"E7EC507C802528F790AFF5303A017B17",
"4B97A7A568940A9E3CE7A99E93031E",
"28349BDC5A09390C480F9B8AA3EDEA3DDB8B9D64BCA322C570B8225DF0E31190DAB25A4014BA39519E02ABFB12B89AA28BBFD29E486E7FB28734258C817B63CED9912DBAFEBB93E2798AB2890DE3B0ACFCFF906AB15563EF7823CE83D27CDB251195E22BD1337BCBDE65E7C2C427321C463C2777BFE5AEAA",
"9455B3EA706B74",
"7F33BA3EA848D48A96B9530E26888F43EBD4463C9399B6"},
{"6C928AA3224736F28EE7378DE0090191",
"8936138E2E4C6A13280017A1622D",
"6202717F2631565BDCDC57C6584543E72A7C8BD444D0D108ED35069819633C",
"DA0691439E5F035F3E455269D14FE5C201C8C9B0A3FE2D3F86BCC59387C868FE65733D388360B31E3CE28B4BF6A8BE636706B536D5720DB66B47CF1C7A5AFD6F61E0EF90F1726D6B0E169F9A768B2B7AE4EE00A17F630AC905FCAAA1B707FFF25B3A1AAE83B504837C64A5639B2A34002B300EC035C9B43654DA55",
"B8804D182AB0F0EEB464FA7BD1329AD6154F982013F3765FEDFE09E26DAC078C9C1439BFC1159D6C02A25E3FF83EF852570117B315852AD5EE20E0FA3AA0A626B0E43BC0CEA38B44579DD36803455FB46989B90E6D229F513FD727AF8372517E9488384C515D6067704119C931299A0982EDDFB9C2E86A90C450C077EB222511EC9CCABC9FCFDB19F70088"},
{"ECEA315CA4B3F425B0C9957A17805EA4",
"664CDAE18403F4F9BA13015A44FC",
"642AFB090D6C6DB46783F08B01A3EF2A8FEB5736B531EAC226E7888FCC8505F396818F83105065FACB3267485B9E5E4A0261F621041C08FCCB2A809A49AB5252A91D0971BCC620B9D614BD77E57A0EED2FA5",
"6852C31F8083E20E364CEA21BB7854D67CEE812FE1C9ED2425C0932A90D3780728D1BB",
"2ECEF962A9695A463ADABB275BDA9FF8B2BA57AEC2F52EFFB700CD9271A74D2A011C24AEA946051BD6291776429B7E681BA33E"},
{"4EE616C4A58AAA380878F71A373461F6",
"91B8C9C176D9C385E9C47E52",
"CDA440B7F9762C572A718AC754EDEECC119E5EE0CCB9FEA4FFB22EEE75087C032EBF3DA9CDD8A28CC010B99ED45143B41A4BA50EA2A005473F89639237838867A57F23B0F0ED3BF22490E4501DAC9C658A9B9F",
"D6E645FA9AE410D15B8123FD757FA356A8DBE9258DDB5BE88832E615910993F497EC",
"B70ED7BF959FB2AAED4F36174A2A99BFB16992C8CDF369C782C4DB9C73DE78C5DB8E0615F647243B97ACDB24503BC9CADC48"},
{"DCD475773136C830D5E3D0C5FE05B7FF",
"BB8E1FBB483BE7616A922C4A",
"36FEF2E1CB29E76A6EA663FC3AF66ECD7404F466382F7B040AABED62293302B56E8783EF7EBC21B4A16C3E78A7483A0A403F253A2CDC5BBF79DC3DAE6C73F39A961D8FBBE8D41B",
"441E886EA38322B2437ECA7DEB5282518865A66780A454E510878E61BFEC3106A3CD93D2A02052E6F9E1832F9791053E3B76BF4C07EFDD6D4106E3027FABB752E60C1AA425416A87D53938163817A1051EBA1D1DEEB4B9B25C7E97368B52E5911A31810B0EC5AF547559B6142D9F4C4A6EF24A4CF75271BF9D48F62B",
"1BE4DD2F4E25A6512C2CC71D24BBB07368589A94C2714962CD0ACE5605688F06342587521E75F0ACAFFD86212FB5C34327D238DB36CF2B787794B9A4412E7CD1410EA5DDD2450C265F29CF96013CD213FD2880657694D718558964BC189B4A84AFCF47EB012935483052399DBA5B088B0A0477F20DFE0E85DCB735E21F22A439FB837DD365A93116D063E607"},
{"3FBA2B3D30177FFE15C1C59ED2148BB2C091F5615FBA7C07",
"FACF804A4BEBF998505FF9DE",
"8213B9263B2971A5BDA18DBD02208EE1",
"15B323926993B326EA19F892D704439FC478828322AF72118748284A1FD8A6D814E641F70512FD706980337379F31DC63355974738D7FEA87AD2858C0C2EBBFBE74371C21450072373C7B651B334D7C4D43260B9D7CCD3AF9EDB",
"6D35DC1469B26E6AAB26272A41B46916397C24C485B61162E640A062D9275BC33DDCFD3D9E1A53B6C8F51AC89B66A41D59B3574197A40D9B6DCF8A4E2A001409C8112F16B9C389E0096179DB914E05D6D11ED0005AD17E1CE105A2F0BAB8F6B1540DEB968B7A5428FF44"},
{"53B52B8D4D748BCDF1DDE68857832FA46227FA6E2F32EFA1",
"0B0EF53D4606B28D1398355F",
"F23882436349094AF98BCACA8218E81581A043B19009E28EFBF2DE37883E04864148CC01D240552CA8844EC1456F42034653067DA67E80F87105FD06E14FF771246C9612867BE4D215F6D761",
"F15030679BD4088D42CAC9BF2E9606EAD4798782FA3ED8C57EBE7F84A53236F51B25967C6489D0CD20C9EEA752F9BC",
"67B96E2D67C3729C96DAEAEDF821D61C17E648643A2134C5621FEC621186915AD80864BFD1EB5B238BF526A679385E012A457F583AFA78134242E9D9C1B4E4"},
{"0272DD80F23399F49BFC320381A5CD8225867245A49A7D41",
"5C83F4896D0738E1366B1836",
"69B0337289B19F73A12BAEEA857CCAF396C11113715D9500CCCF48BA08CFF12BC8B4BADB3084E63B85719DB5058FA7C2C11DEB096D7943CFA7CAF5",
"C01AD10FC8B562CD17C7BC2FAB3E26CBDFF8D7F4DEA816794BBCC12336991712972F52816AABAB244EB43B0137E2BAC1DD413CE79531E78BEF782E6B439612BB3AEF154DE3502784F287958EBC159419F9EBA27916A28D6307324129F506B1DE80C1755A929F87",
"FEFE52DD7159C8DD6E8EC2D3D3C0F37AB6CB471A75A071D17EC4ACDD8F3AA4D7D4F7BB559F3C09099E3D9003E5E8AA1F556B79CECDE66F85B08FA5955E6976BF2695EA076388A62D2AD5BAB7CBF1A7F3F4C8D5CDF37CDE99BD3E30B685D9E5EEE48C7C89118EF4878EB89747F28271FA2CC45F8E9E7601"},
{"3EEAED04A455D6E5E5AB53CFD5AFD2F2BC625C7BF4BE49A5",
"36B88F63ADBB5668588181D774",
"D367E3CB3703E762D23C6533188EF7028EFF9D935A3977150361997EC9DEAF1E4794BDE26AA8B53C124980B1362EC86FCDDFC7A90073171C1BAEE351A53234B86C66E8AB92FAE99EC6967A6D3428892D80",
"573454C719A9A55E04437BF7CBAAF27563CCCD92ADD5E515CD63305DFF0687E5EEF790C5DCA5C0033E9AB129505E2775438D92B38F08F3B0356BA142C6F694",
"E9F79A5B432D9E682C9AAA5661CFC2E49A0FCB81A431E54B42EB73DD3BED3F377FEC556ABA81624BA64A5D739AD41467460088F8D4F442180A9382CA635745473794C382FCDDC49BA4EB6D8A44AE3C"},
{"B695C691538F8CBD60F039D0E28894E3693CC7C36D92D79D",
"BC099AEB637361BAC536B57618",
"BFFF1A65AE38D1DC142C71637319F5F6508E2CB33C9DCB94202B359ED5A5ED8042E7F4F09231D32A7242976677E6F4C549BF65FADC99E5AF43F7A46FD95E16C2",
"081DF3FD85B415D803F0BE5AC58CFF0023FDDED99788296C3731D8",
"E50C64E3614D94FE69C47092E46ACC9957C6FEA2CCBF96BC62FBABE7424753C75F9C147C42AE26FE171531"},
{"C9ACBD2718F0689A1BE9802A551B6B8D9CF5614DAF5E65ED",
"B1B0AAF373B8B026EB80422051D8",
"6648C0E61AC733C76119D23FB24548D637751387AA2EAE9D80E912B7BD486CAAD9EAF4D7A5FE2B54AAD481E8EC94BB4D558000896E2010462B70C9FED1E7273080D1",
"189F591F6CB6D59AFEDD14C341741A8F1037DC0DF00FC57CE65C30F49E860255CEA5DC6019380CC0FE8880BC1A9E685F41C239C38F36E3F2A1388865C5C311059C0A",
"922A5E949B61D03BE34AB5F4E58607D4504EA14017BB363DAE3C873059EA7A1C77A746FB78981671D26C2CF6D9F24952D510044CE02A10177E9DB42D0145211DFE6E84369C5E3BC2669EAB4147B2822895F9"},
{"7A832BD2CF5BF4919F353CE2A8C86A5E406DA2D52BE16A72",
"2F2F17CECF7E5A756D10785A3CB9DB",
"61DA05E3788CC2D8405DBA70C7A28E5AF699863C9F72E6C6770126929F5D6FA267F005EBCF49495CB46400958A3AE80D1289D1C671",
"44E91121195A41AF14E8CFDBD39A4B517BE0DF1A72977ED8A3EEF8EEDA1166B2EB6DB2C4AE2E74FA0F0C74537F659BFBD141E5DDEC67E64EDA85AABD3F52C85A785B9FB3CECD70E7DF",
"BEDF596EA21288D2B84901E188F6EE1468B14D5161D3802DBFE00D60203A24E2AB62714BF272A45551489838C3A7FEAADC177B591836E73684867CCF4E12901DCF2064058726BBA554E84ADC5136F507E961188D4AF06943D3"},
{"1508E8AE9079AA15F1CEC4F776B4D11BCCB061B58AA56C18",
"BCA625674F41D1E3AB47672DC0C3",
"8B12CF84F16360F0EAD2A41BC021530FFCEC7F3579CAE658E10E2D3D81870F65AFCED0C77C6C4C6E6BA424FF23088C796BA6195ABA35094BF1829E089662E7A95FC90750AE16D0C8AFA55DAC789D7735B970B58D4BE7CEC7341DA82A0179A01929C27A59C5063215B859EA43",
"E525422519ECE070E82C",
"B47BC07C3ED1C0A43BA52C43CBACBCDBB29CAF1001E09FDF7107"},
{"7550C2761644E911FE9ADD119BAC07376BEA442845FEAD876D7E7AC1B713E464",
"36D2EC25ADD33CDEDF495205BBC923",
"7FCFE81A3790DE97FFC3DE160C470847EA7E841177C2F759571CBD837EA004A6CA8C6F4AEBFF2E9FD552D73EB8A30705D58D70C0B67AEEA280CBBF0A477358ACEF1E7508F2735CD9A0E4F9AC92B8C008F575D3B6278F1C18BD01227E3502E5255F3AB1893632AD00C717C588EF652A51A43209E7EE90",
"2B1A62F8FDFAA3C16470A21AD307C9A7D03ADE8EF72C69B06F8D738CDE578D7AEFD0D40BD9C022FB9F580DF5394C998ACCCEFC5471A3996FB8F1045A81FDC6F32D13502EA65A211390C8D882B8E0BEFD8DD8CBEF51D1597B124E9F7F",
"C873E02A22DB89EB0787DB6A60B99F7E4A0A085D5C4232A81ADCE2D60AA36F92DDC33F93DD8640AC0E08416B187FB382B3EC3EE85A64B0E6EE41C1366A5AD2A282F66605E87031CCBA2FA7B2DA201D975994AADE3DD1EE122AE09604AD489B84BF0C1AB7129EE16C6934850E"},
{"A51300285E554FDBDE7F771A9A9A80955639DD87129FAEF74987C91FB9687C71",
"81691D5D20EC818FCFF24B33DECC",
"C948093218AA9EB2A8E44A87EEA73FC8B6B75A196819A14BD83709EA323E8DF8B491045220E1D88729A38DBCFFB60D3056DAD4564498FD6574F74512945DEB34B69329ACED9FFC05D5D59DFCD5B973E2ACAFE6AD1EF8BBBC49351A2DD12508ED89ED",
"EB861165DAF7625F827C6B574ED703F03215",
"C6CD1CE76D2B3679C1B5AA1CFD67CCB55444B6BFD3E22C81CBC9BB738796B83E54E3"},
{"8CE0156D26FAEB7E0B9B800BBB2E9D4075B5EAC5C62358B0E7F6FCE610223282",
"D2A7B94DD12CDACA909D3AD7",
"E021A78F374FC271389AB9A3E97077D755",
"7C26000B58929F5095E1CEE154F76C2A299248E299F9B5ADE6C403AA1FD4A67FD4E0232F214CE7B919EE7A1027D2B76C57475715CD078461",
"C556FB38DF069B56F337B5FF5775CE6EAA16824DFA754F20B78819028EA635C3BB7AA731DE8776B2DCB67DCA2D33EEDF3C7E52EA450013722A41755A0752433ED17BDD5991AAE77A"},
{"1E8000A2CE00A561C9920A30BF0D7B983FEF8A1014C8F04C35CA6970E6BA02BD",
"65ED3D63F79F90BBFD19775E",
"336A8C0B7243582A46B221AA677647FCAE91",
"134A8B34824A290E7B",
"914FBEF80D0E6E17F8BDBB6097EBF5FBB0554952DC2B9E5151"},
{"53D5607BBE690B6E8D8F6D97F3DF2BA853B682597A214B8AA0EA6E598650AF15",
"C391A856B9FE234E14BA1AC7BB40FF",
"479682BC21349C4BE1641D5E78FE2C79EC1B9CF5470936DCAD9967A4DCD7C4EFADA593BC9EDE71E6A08829B8580901B61E274227E9D918502DE3",
"EAD154DC09C5E26C5D26FF33ED148B27120C7F2C23225CC0D0631B03E1F6C6D96FEB88C1A4052ACB4CE746B884B6502931F407021126C6AAB8C514C077A5A38438AE88EE",
"938821286EBB671D999B87C032E1D6055392EB564E57970D55E545FC5E8BAB90E6E3E3C0913F6320995FC636D72CD9919657CC38BD51552F4A502D8D1FE56DB33EBAC5092630E69EBB986F0E15CEE9FC8C052501"},
{"294362FCC984F440CEA3E9F7D2C06AF20C53AAC1B3738CA2186C914A6E193ABB",
"B15B61C8BB39261A8F55AB178EC3",
"D0729B6B75BB",
"2BD089ADCE9F334BAE3B065996C7D616DD0C27DF4218DCEEA0FBCA0F968837CE26B0876083327E25681FDDD620A32EC0DA12F73FAE826CC94BFF2B90A54D2651",
"AC94B25E4E21DE2437B806966CCD5D9385EF0CD4A51AB9FA6DE675C7B8952D67802E9FEC1FDE9F5D1EAB06057498BC0EEA454804FC9D2068982A3E24182D9AC2E7AB9994DDC899A604264583F63D066B"},
{"959DBFEB039B1A5B8CE6A44649B602AAA5F98A906DB96143D202CD2024F749D9",
"01D7BDB1133E9C347486C1EFA6",
"F3843955BD741F379DD750585EDC55E2CDA05CCBA8C1F4622AC2FE35214BC3A019B8BD12C4CC42D9213D1E1556941E8D8450830287FFB3B763A13722DD4140ED9846FB5FFF745D7B0B967D810A068222E10B259AF1D392035B0D83DC1498A6830B11B2418A840212599171E0258A1C203B05362978",
"A21811232C950FA8B12237C2EBD6A7CD2C3A155905E9E0C7C120",
"63C1CE397B22F1A03F1FA549B43178BC405B152D3C95E977426D519B3DFCA28498823240592B6EEE7A14"},
{"096AE499F5294173F34FF2B375F0E5D5AB79D0D03B33B1A74D7D576826345DF4",
"0C52B3D11D636E5910A4DD76D32C",
"229E9ECA3053789E937447BC719467075B6138A142DA528DA8F0CF8DDF022FD9AF8E74779BA3AC306609",
"8B7A00038783E8BAF6EDEAE0C4EAB48FC8FD501A588C7E4A4DB71E3604F2155A97687D3D2FFF8569261375A513CF4398CE0F87CA1658A1050F6EF6C4EA3E25",
"C20B6CF8D3C8241825FD90B2EDAC7593600646E579A8D8DAAE9E2E40C3835FE801B2BE4379131452BC5182C90307B176DFBE2049544222FE7783147B690774F6D9D7CEF52A91E61E298E9AA15464AC"},
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_a.go
================================================
package ocb
import (
"encoding/hex"
)
// Test vectors from https://tools.ietf.org/html/rfc7253. Note that key is
// shared across tests.
var testKey, _ = hex.DecodeString("000102030405060708090A0B0C0D0E0F")
var rfc7253testVectors = []struct {
nonce, header, plaintext, ciphertext string
}{
{"BBAA99887766554433221100",
"",
"",
"785407BFFFC8AD9EDCC5520AC9111EE6"},
{"BBAA99887766554433221101",
"0001020304050607",
"0001020304050607",
"6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009"},
{"BBAA99887766554433221102",
"0001020304050607",
"",
"81017F8203F081277152FADE694A0A00"},
{"BBAA99887766554433221103",
"",
"0001020304050607",
"45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9"},
{"BBAA99887766554433221104",
"000102030405060708090A0B0C0D0E0F",
"000102030405060708090A0B0C0D0E0F",
"571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358"},
{"BBAA99887766554433221105",
"000102030405060708090A0B0C0D0E0F",
"",
"8CF761B6902EF764462AD86498CA6B97"},
{"BBAA99887766554433221106",
"",
"000102030405060708090A0B0C0D0E0F",
"5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D"},
{"BBAA99887766554433221107",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F"},
{"BBAA99887766554433221108",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"",
"6DC225A071FC1B9F7C69F93B0F1E10DE"},
{"BBAA99887766554433221109",
"",
"000102030405060708090A0B0C0D0E0F1011121314151617",
"221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF"},
{"BBAA9988776655443322110A",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240"},
{"BBAA9988776655443322110B",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"",
"FE80690BEE8A485D11F32965BC9D2A32"},
{"BBAA9988776655443322110C",
"",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
"2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF"},
{"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60"},
{"BBAA9988776655443322110E",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"",
"C5CD9D1850C141E358649994EE701B68"},
{"BBAA9988776655443322110F",
"",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479"},
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/ocb/rfc7253_test_vectors_suite_b.go
================================================
package ocb
// Second set of test vectors from https://tools.ietf.org/html/rfc7253
var rfc7253TestVectorTaglen96 = struct {
key, nonce, header, plaintext, ciphertext string
}{"0F0E0D0C0B0A09080706050403020100",
"BBAA9988776655443322110D",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
"1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA"}
var rfc7253AlgorithmTest = []struct {
KEYLEN, TAGLEN int
OUTPUT string
}{
{128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2"},
{192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17"},
{256, 128, "D90EB8E9C977C88B79DD793D7FFA161C"},
{128, 96, "77A3D8E73589158D25D01209"},
{192, 96, "05D56EAD2752C86BE6932C5E"},
{256, 96, "5458359AC23B0CBA9E6330DD"},
{128, 64, "192C9B7BD90BA06A"},
{192, 64, "0066BC6E0EF34E24"},
{256, 64, "7D4EA5D445501CBE"},
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/aes/keywrap/keywrap.go
================================================
// Copyright 2014 Matthew Endsley
// All rights reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted providing that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// Package keywrap is an implementation of the RFC 3394 AES key wrapping
// algorithm. This is used in OpenPGP with elliptic curve keys.
package keywrap
import (
"crypto/aes"
"encoding/binary"
"errors"
)
var (
// ErrWrapPlaintext is returned if the plaintext is not a multiple
// of 64 bits.
ErrWrapPlaintext = errors.New("keywrap: plainText must be a multiple of 64 bits")
// ErrUnwrapCiphertext is returned if the ciphertext is not a
// multiple of 64 bits.
ErrUnwrapCiphertext = errors.New("keywrap: cipherText must by a multiple of 64 bits")
// ErrUnwrapFailed is returned if unwrapping a key fails.
ErrUnwrapFailed = errors.New("keywrap: failed to unwrap key")
// NB: the AES NewCipher call only fails if the key is an invalid length.
// ErrInvalidKey is returned when the AES key is invalid.
ErrInvalidKey = errors.New("keywrap: invalid AES key")
)
// Wrap a key using the RFC 3394 AES Key Wrap Algorithm.
func Wrap(key, plainText []byte) ([]byte, error) {
if len(plainText)%8 != 0 {
return nil, ErrWrapPlaintext
}
c, err := aes.NewCipher(key)
if err != nil {
return nil, ErrInvalidKey
}
nblocks := len(plainText) / 8
// 1) Initialize variables.
var block [aes.BlockSize]byte
// - Set A = IV, an initial value (see 2.2.3)
for ii := 0; ii < 8; ii++ {
block[ii] = 0xA6
}
// - For i = 1 to n
// - Set R[i] = P[i]
intermediate := make([]byte, len(plainText))
copy(intermediate, plainText)
// 2) Calculate intermediate values.
for ii := 0; ii < 6; ii++ {
for jj := 0; jj < nblocks; jj++ {
// - B = AES(K, A | R[i])
copy(block[8:], intermediate[jj*8:jj*8+8])
c.Encrypt(block[:], block[:])
// - A = MSB(64, B) ^ t where t = (n*j)+1
t := uint64(ii*nblocks + jj + 1)
val := binary.BigEndian.Uint64(block[:8]) ^ t
binary.BigEndian.PutUint64(block[:8], val)
// - R[i] = LSB(64, B)
copy(intermediate[jj*8:jj*8+8], block[8:])
}
}
// 3) Output results.
// - Set C[0] = A
// - For i = 1 to n
// - C[i] = R[i]
return append(block[:8], intermediate...), nil
}
// Unwrap a key using the RFC 3394 AES Key Wrap Algorithm.
func Unwrap(key, cipherText []byte) ([]byte, error) {
if len(cipherText)%8 != 0 {
return nil, ErrUnwrapCiphertext
}
c, err := aes.NewCipher(key)
if err != nil {
return nil, ErrInvalidKey
}
nblocks := len(cipherText)/8 - 1
// 1) Initialize variables.
var block [aes.BlockSize]byte
// - Set A = C[0]
copy(block[:8], cipherText[:8])
// - For i = 1 to n
// - Set R[i] = C[i]
intermediate := make([]byte, len(cipherText)-8)
copy(intermediate, cipherText[8:])
// 2) Compute intermediate values.
for jj := 5; jj >= 0; jj-- {
for ii := nblocks - 1; ii >= 0; ii-- {
// - B = AES-1(K, (A ^ t) | R[i]) where t = n*j+1
// - A = MSB(64, B)
t := uint64(jj*nblocks + ii + 1)
val := binary.BigEndian.Uint64(block[:8]) ^ t
binary.BigEndian.PutUint64(block[:8], val)
copy(block[8:], intermediate[ii*8:ii*8+8])
c.Decrypt(block[:], block[:])
// - R[i] = LSB(B, 64)
copy(intermediate[ii*8:ii*8+8], block[8:])
}
}
// 3) Output results.
// - If A is an appropriate initial value (see 2.2.3),
for ii := 0; ii < 8; ii++ {
if block[ii] != 0xA6 {
return nil, ErrUnwrapFailed
}
}
// - For i = 1 to n
// - P[i] = R[i]
return intermediate, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/armor/armor.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package armor implements OpenPGP ASCII Armor, see RFC 4880. OpenPGP Armor is
// very similar to PEM except that it has an additional CRC checksum.
package armor // import "github.com/ProtonMail/go-crypto/openpgp/armor"
import (
"bufio"
"bytes"
"encoding/base64"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// A Block represents an OpenPGP armored structure.
//
// The encoded form is:
//
// -----BEGIN Type-----
// Headers
//
// base64-encoded Bytes
// '=' base64 encoded checksum (optional) not checked anymore
// -----END Type-----
//
// where Headers is a possibly empty sequence of Key: Value lines.
//
// Since the armored data can be very large, this package presents a streaming
// interface.
type Block struct {
Type string // The type, taken from the preamble (i.e. "PGP SIGNATURE").
Header map[string]string // Optional headers.
Body io.Reader // A Reader from which the contents can be read
lReader lineReader
oReader openpgpReader
}
var ArmorCorrupt error = errors.StructuralError("armor invalid")
var armorStart = []byte("-----BEGIN ")
var armorEnd = []byte("-----END ")
var armorEndOfLine = []byte("-----")
// lineReader wraps a line based reader. It watches for the end of an armor block
type lineReader struct {
in *bufio.Reader
buf []byte
eof bool
}
func (l *lineReader) Read(p []byte) (n int, err error) {
if l.eof {
return 0, io.EOF
}
if len(l.buf) > 0 {
n = copy(p, l.buf)
l.buf = l.buf[n:]
return
}
line, isPrefix, err := l.in.ReadLine()
if err != nil {
return
}
if isPrefix {
return 0, ArmorCorrupt
}
if bytes.HasPrefix(line, armorEnd) {
l.eof = true
return 0, io.EOF
}
if len(line) == 5 && line[0] == '=' {
// This is the checksum line
// Don't check the checksum
l.eof = true
return 0, io.EOF
}
if len(line) > 96 {
return 0, ArmorCorrupt
}
n = copy(p, line)
bytesToSave := len(line) - n
if bytesToSave > 0 {
if cap(l.buf) < bytesToSave {
l.buf = make([]byte, 0, bytesToSave)
}
l.buf = l.buf[0:bytesToSave]
copy(l.buf, line[n:])
}
return
}
// openpgpReader passes Read calls to the underlying base64 decoder.
type openpgpReader struct {
lReader *lineReader
b64Reader io.Reader
}
func (r *openpgpReader) Read(p []byte) (n int, err error) {
n, err = r.b64Reader.Read(p)
return
}
// Decode reads a PGP armored block from the given Reader. It will ignore
// leading garbage. If it doesn't find a block, it will return nil, io.EOF. The
// given Reader is not usable after calling this function: an arbitrary amount
// of data may have been read past the end of the block.
func Decode(in io.Reader) (p *Block, err error) {
r := bufio.NewReaderSize(in, 100)
var line []byte
ignoreNext := false
TryNextBlock:
p = nil
// Skip leading garbage
for {
ignoreThis := ignoreNext
line, ignoreNext, err = r.ReadLine()
if err != nil {
return
}
if ignoreNext || ignoreThis {
continue
}
line = bytes.TrimSpace(line)
if len(line) > len(armorStart)+len(armorEndOfLine) && bytes.HasPrefix(line, armorStart) {
break
}
}
p = new(Block)
p.Type = string(line[len(armorStart) : len(line)-len(armorEndOfLine)])
p.Header = make(map[string]string)
nextIsContinuation := false
var lastKey string
// Read headers
for {
isContinuation := nextIsContinuation
line, nextIsContinuation, err = r.ReadLine()
if err != nil {
p = nil
return
}
if isContinuation {
p.Header[lastKey] += string(line)
continue
}
line = bytes.TrimSpace(line)
if len(line) == 0 {
break
}
i := bytes.Index(line, []byte(":"))
if i == -1 {
goto TryNextBlock
}
lastKey = string(line[:i])
var value string
if len(line) > i+2 {
value = string(line[i+2:])
}
p.Header[lastKey] = value
}
p.lReader.in = r
p.oReader.lReader = &p.lReader
p.oReader.b64Reader = base64.NewDecoder(base64.StdEncoding, &p.lReader)
p.Body = &p.oReader
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/armor/encode.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package armor
import (
"encoding/base64"
"io"
"sort"
)
var armorHeaderSep = []byte(": ")
var blockEnd = []byte("\n=")
var newline = []byte("\n")
var armorEndOfLineOut = []byte("-----\n")
const crc24Init = 0xb704ce
const crc24Poly = 0x1864cfb
// crc24 calculates the OpenPGP checksum as specified in RFC 4880, section 6.1
func crc24(crc uint32, d []byte) uint32 {
for _, b := range d {
crc ^= uint32(b) << 16
for i := 0; i < 8; i++ {
crc <<= 1
if crc&0x1000000 != 0 {
crc ^= crc24Poly
}
}
}
return crc
}
// writeSlices writes its arguments to the given Writer.
func writeSlices(out io.Writer, slices ...[]byte) (err error) {
for _, s := range slices {
_, err = out.Write(s)
if err != nil {
return err
}
}
return
}
// lineBreaker breaks data across several lines, all of the same byte length
// (except possibly the last). Lines are broken with a single '\n'.
type lineBreaker struct {
lineLength int
line []byte
used int
out io.Writer
haveWritten bool
}
func newLineBreaker(out io.Writer, lineLength int) *lineBreaker {
return &lineBreaker{
lineLength: lineLength,
line: make([]byte, lineLength),
used: 0,
out: out,
}
}
func (l *lineBreaker) Write(b []byte) (n int, err error) {
n = len(b)
if n == 0 {
return
}
if l.used == 0 && l.haveWritten {
_, err = l.out.Write([]byte{'\n'})
if err != nil {
return
}
}
if l.used+len(b) < l.lineLength {
l.used += copy(l.line[l.used:], b)
return
}
l.haveWritten = true
_, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
excess := l.lineLength - l.used
l.used = 0
_, err = l.out.Write(b[0:excess])
if err != nil {
return
}
_, err = l.Write(b[excess:])
return
}
func (l *lineBreaker) Close() (err error) {
if l.used > 0 {
_, err = l.out.Write(l.line[0:l.used])
if err != nil {
return
}
}
return
}
// encoding keeps track of a running CRC24 over the data which has been written
// to it and outputs a OpenPGP checksum when closed, followed by an armor
// trailer.
//
// It's built into a stack of io.Writers:
//
// encoding -> base64 encoder -> lineBreaker -> out
type encoding struct {
out io.Writer
breaker *lineBreaker
b64 io.WriteCloser
crc uint32
crcEnabled bool
blockType []byte
}
func (e *encoding) Write(data []byte) (n int, err error) {
if e.crcEnabled {
e.crc = crc24(e.crc, data)
}
return e.b64.Write(data)
}
func (e *encoding) Close() (err error) {
err = e.b64.Close()
if err != nil {
return
}
e.breaker.Close()
if e.crcEnabled {
var checksumBytes [3]byte
checksumBytes[0] = byte(e.crc >> 16)
checksumBytes[1] = byte(e.crc >> 8)
checksumBytes[2] = byte(e.crc)
var b64ChecksumBytes [4]byte
base64.StdEncoding.Encode(b64ChecksumBytes[:], checksumBytes[:])
return writeSlices(e.out, blockEnd, b64ChecksumBytes[:], newline, armorEnd, e.blockType, armorEndOfLine)
}
return writeSlices(e.out, newline, armorEnd, e.blockType, armorEndOfLine)
}
func encode(out io.Writer, blockType string, headers map[string]string, checksum bool) (w io.WriteCloser, err error) {
bType := []byte(blockType)
err = writeSlices(out, armorStart, bType, armorEndOfLineOut)
if err != nil {
return
}
keys := make([]string, len(headers))
i := 0
for k := range headers {
keys[i] = k
i++
}
sort.Strings(keys)
for _, k := range keys {
err = writeSlices(out, []byte(k), armorHeaderSep, []byte(headers[k]), newline)
if err != nil {
return
}
}
_, err = out.Write(newline)
if err != nil {
return
}
e := &encoding{
out: out,
breaker: newLineBreaker(out, 64),
blockType: bType,
crc: crc24Init,
crcEnabled: checksum,
}
e.b64 = base64.NewEncoder(base64.StdEncoding, e.breaker)
return e, nil
}
// Encode returns a WriteCloser which will encode the data written to it in
// OpenPGP armor.
func Encode(out io.Writer, blockType string, headers map[string]string) (w io.WriteCloser, err error) {
return encode(out, blockType, headers, true)
}
// EncodeWithChecksumOption returns a WriteCloser which will encode the data written to it in
// OpenPGP armor and provides the option to include a checksum.
// When forming ASCII Armor, the CRC24 footer SHOULD NOT be generated,
// unless interoperability with implementations that require the CRC24 footer
// to be present is a concern.
func EncodeWithChecksumOption(out io.Writer, blockType string, headers map[string]string, doChecksum bool) (w io.WriteCloser, err error) {
return encode(out, blockType, headers, doChecksum)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/canonical_text.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
"hash"
"io"
)
// NewCanonicalTextHash reformats text written to it into the canonical
// form and then applies the hash h. See RFC 4880, section 5.2.1.
func NewCanonicalTextHash(h hash.Hash) hash.Hash {
return &canonicalTextHash{h, 0}
}
type canonicalTextHash struct {
h hash.Hash
s int
}
var newline = []byte{'\r', '\n'}
func writeCanonical(cw io.Writer, buf []byte, s *int) (int, error) {
start := 0
for i, c := range buf {
switch *s {
case 0:
if c == '\r' {
*s = 1
} else if c == '\n' {
if _, err := cw.Write(buf[start:i]); err != nil {
return 0, err
}
if _, err := cw.Write(newline); err != nil {
return 0, err
}
start = i + 1
}
case 1:
*s = 0
}
}
if _, err := cw.Write(buf[start:]); err != nil {
return 0, err
}
return len(buf), nil
}
func (cth *canonicalTextHash) Write(buf []byte) (int, error) {
return writeCanonical(cth.h, buf, &cth.s)
}
func (cth *canonicalTextHash) Sum(in []byte) []byte {
return cth.h.Sum(in)
}
func (cth *canonicalTextHash) Reset() {
cth.h.Reset()
cth.s = 0
}
func (cth *canonicalTextHash) Size() int {
return cth.h.Size()
}
func (cth *canonicalTextHash) BlockSize() int {
return cth.h.BlockSize()
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/ecdh/ecdh.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package ecdh implements ECDH encryption, suitable for OpenPGP,
// as specified in RFC 6637, section 8.
package ecdh
import (
"bytes"
"errors"
"io"
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
)
type KDF struct {
Hash algorithm.Hash
Cipher algorithm.Cipher
}
type PublicKey struct {
curve ecc.ECDHCurve
Point []byte
KDF
}
type PrivateKey struct {
PublicKey
D []byte
}
func NewPublicKey(curve ecc.ECDHCurve, kdfHash algorithm.Hash, kdfCipher algorithm.Cipher) *PublicKey {
return &PublicKey{
curve: curve,
KDF: KDF{
Hash: kdfHash,
Cipher: kdfCipher,
},
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.ECDHCurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalBytePoint(pk.Point)
}
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
pk.Point = pk.curve.UnmarshalBytePoint(p)
if pk.Point == nil {
return errors.New("ecdh: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalByteSecret() []byte {
return sk.curve.MarshalByteSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
sk.D = sk.curve.UnmarshalByteSecret(d)
if sk.D == nil {
return errors.New("ecdh: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.ECDHCurve, kdf KDF) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.KDF = kdf
priv.PublicKey.Point, priv.D, err = c.GenerateECDH(rand)
return
}
func Encrypt(random io.Reader, pub *PublicKey, msg, curveOID, fingerprint []byte) (vsG, c []byte, err error) {
if len(msg) > 40 {
return nil, nil, errors.New("ecdh: message too long")
}
// the sender MAY use 21, 13, and 5 bytes of padding for AES-128,
// AES-192, and AES-256, respectively, to provide the same number of
// octets, 40 total, as an input to the key wrapping method.
padding := make([]byte, 40-len(msg))
for i := range padding {
padding[i] = byte(40 - len(msg))
}
m := append(msg, padding...)
ephemeral, zb, err := pub.curve.Encaps(random, pub.Point)
if err != nil {
return nil, nil, err
}
vsG = pub.curve.MarshalBytePoint(ephemeral)
z, err := buildKey(pub, zb, curveOID, fingerprint, false, false)
if err != nil {
return nil, nil, err
}
if c, err = keywrap.Wrap(z, m); err != nil {
return nil, nil, err
}
return vsG, c, nil
}
func Decrypt(priv *PrivateKey, vsG, c, curveOID, fingerprint []byte) (msg []byte, err error) {
var m []byte
zb, err := priv.PublicKey.curve.Decaps(priv.curve.UnmarshalBytePoint(vsG), priv.D)
// Try buildKey three times to workaround an old bug, see comments in buildKey.
for i := 0; i < 3; i++ {
var z []byte
// RFC6637 §8: "Compute Z = KDF( S, Z_len, Param );"
z, err = buildKey(&priv.PublicKey, zb, curveOID, fingerprint, i == 1, i == 2)
if err != nil {
return nil, err
}
// RFC6637 §8: "Compute C = AESKeyWrap( Z, c ) as per [RFC3394]"
m, err = keywrap.Unwrap(z, c)
if err == nil {
break
}
}
// Only return an error after we've tried all (required) variants of buildKey.
if err != nil {
return nil, err
}
// RFC6637 §8: "m = symm_alg_ID || session key || checksum || pkcs5_padding"
// The last byte should be the length of the padding, as per PKCS5; strip it off.
return m[:len(m)-int(m[len(m)-1])], nil
}
func buildKey(pub *PublicKey, zb []byte, curveOID, fingerprint []byte, stripLeading, stripTrailing bool) ([]byte, error) {
// Param = curve_OID_len || curve_OID || public_key_alg_ID || 03
// || 01 || KDF_hash_ID || KEK_alg_ID for AESKeyWrap
// || "Anonymous Sender " || recipient_fingerprint;
param := new(bytes.Buffer)
if _, err := param.Write(curveOID); err != nil {
return nil, err
}
algKDF := []byte{18, 3, 1, pub.KDF.Hash.Id(), pub.KDF.Cipher.Id()}
if _, err := param.Write(algKDF); err != nil {
return nil, err
}
if _, err := param.Write([]byte("Anonymous Sender ")); err != nil {
return nil, err
}
if _, err := param.Write(fingerprint[:]); err != nil {
return nil, err
}
// MB = Hash ( 00 || 00 || 00 || 01 || ZB || Param );
h := pub.KDF.Hash.New()
if _, err := h.Write([]byte{0x0, 0x0, 0x0, 0x1}); err != nil {
return nil, err
}
zbLen := len(zb)
i := 0
j := zbLen - 1
if stripLeading {
// Work around old go crypto bug where the leading zeros are missing.
for i < zbLen && zb[i] == 0 {
i++
}
}
if stripTrailing {
// Work around old OpenPGP.js bug where insignificant trailing zeros in
// this little-endian number are missing.
// (See https://github.com/openpgpjs/openpgpjs/pull/853.)
for j >= 0 && zb[j] == 0 {
j--
}
}
if _, err := h.Write(zb[i : j+1]); err != nil {
return nil, err
}
if _, err := h.Write(param.Bytes()); err != nil {
return nil, err
}
mb := h.Sum(nil)
return mb[:pub.KDF.Cipher.KeySize()], nil // return oBits leftmost bits of MB.
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateECDH(priv.Point, priv.D)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/ecdsa/ecdsa.go
================================================
// Package ecdsa implements ECDSA signature, suitable for OpenPGP,
// as specified in RFC 6637, section 5.
package ecdsa
import (
"errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"io"
"math/big"
)
type PublicKey struct {
X, Y *big.Int
curve ecc.ECDSACurve
}
type PrivateKey struct {
PublicKey
D *big.Int
}
func NewPublicKey(curve ecc.ECDSACurve) *PublicKey {
return &PublicKey{
curve: curve,
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.ECDSACurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalIntegerPoint(pk.X, pk.Y)
}
func (pk *PublicKey) UnmarshalPoint(p []byte) error {
pk.X, pk.Y = pk.curve.UnmarshalIntegerPoint(p)
if pk.X == nil {
return errors.New("ecdsa: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalIntegerSecret() []byte {
return sk.curve.MarshalIntegerSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalIntegerSecret(d []byte) error {
sk.D = sk.curve.UnmarshalIntegerSecret(d)
if sk.D == nil {
return errors.New("ecdsa: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.ECDSACurve) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.X, priv.PublicKey.Y, priv.D, err = c.GenerateECDSA(rand)
return
}
func Sign(rand io.Reader, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
return priv.PublicKey.curve.Sign(rand, priv.X, priv.Y, priv.D, hash)
}
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
return pub.curve.Verify(pub.X, pub.Y, hash, r, s)
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateECDSA(priv.X, priv.Y, priv.D.Bytes())
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/ed25519/ed25519.go
================================================
// Package ed25519 implements the ed25519 signature algorithm for OpenPGP
// as defined in the Open PGP crypto refresh.
package ed25519
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
)
const (
// PublicKeySize is the size, in bytes, of public keys in this package.
PublicKeySize = ed25519lib.PublicKeySize
// SeedSize is the size, in bytes, of private key seeds.
// The private key representation used by RFC 8032.
SeedSize = ed25519lib.SeedSize
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = ed25519lib.SignatureSize
)
type PublicKey struct {
// Point represents the elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Key the private key representation by RFC 8032,
// encoded as seed | pub key point.
Key []byte
}
// NewPublicKey creates a new empty ed25519 public key.
func NewPublicKey() *PublicKey {
return &PublicKey{}
}
// NewPrivateKey creates a new empty private key referencing the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Seed returns the ed25519 private key secret seed.
// The private key representation by RFC 8032.
func (pk *PrivateKey) Seed() []byte {
return pk.Key[:SeedSize]
}
// MarshalByteSecret returns the underlying 32 byte seed of the private key.
func (pk *PrivateKey) MarshalByteSecret() []byte {
return pk.Seed()
}
// UnmarshalByteSecret computes the private key from the secret seed
// and stores it in the private key object.
func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
sk.Key = ed25519lib.NewKeyFromSeed(seed)
return nil
}
// GenerateKey generates a fresh private key with the provided randomness source.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
publicKey, privateKey, err := ed25519lib.GenerateKey(rand)
if err != nil {
return nil, err
}
privateKeyOut := new(PrivateKey)
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Key = privateKey[:]
return privateKeyOut, nil
}
// Sign signs a message with the ed25519 algorithm.
// priv MUST be a valid key! Check this with Validate() before use.
func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
return ed25519lib.Sign(priv.Key, message), nil
}
// Verify verifies an ed25519 signature.
func Verify(pub *PublicKey, message []byte, signature []byte) bool {
return ed25519lib.Verify(pub.Point, message, signature)
}
// Validate checks if the ed25519 private key is valid.
func Validate(priv *PrivateKey) error {
expectedPrivateKey := ed25519lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
return errors.KeyInvalidError("ed25519: invalid ed25519 secret")
}
if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
return errors.KeyInvalidError("ed25519: invalid ed25519 public key")
}
return nil
}
// ENCODING/DECODING signature:
// WriteSignature encodes and writes an ed25519 signature to writer.
func WriteSignature(writer io.Writer, signature []byte) error {
_, err := writer.Write(signature)
return err
}
// ReadSignature decodes an ed25519 signature from a reader.
func ReadSignature(reader io.Reader) ([]byte, error) {
signature := make([]byte, SignatureSize)
if _, err := io.ReadFull(reader, signature); err != nil {
return nil, err
}
return signature, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/ed448/ed448.go
================================================
// Package ed448 implements the ed448 signature algorithm for OpenPGP
// as defined in the Open PGP crypto refresh.
package ed448
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed448lib "github.com/cloudflare/circl/sign/ed448"
)
const (
// PublicKeySize is the size, in bytes, of public keys in this package.
PublicKeySize = ed448lib.PublicKeySize
// SeedSize is the size, in bytes, of private key seeds.
// The private key representation used by RFC 8032.
SeedSize = ed448lib.SeedSize
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = ed448lib.SignatureSize
)
type PublicKey struct {
// Point represents the elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Key the private key representation by RFC 8032,
// encoded as seed | public key point.
Key []byte
}
// NewPublicKey creates a new empty ed448 public key.
func NewPublicKey() *PublicKey {
return &PublicKey{}
}
// NewPrivateKey creates a new empty private key referencing the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Seed returns the ed448 private key secret seed.
// The private key representation by RFC 8032.
func (pk *PrivateKey) Seed() []byte {
return pk.Key[:SeedSize]
}
// MarshalByteSecret returns the underlying seed of the private key.
func (pk *PrivateKey) MarshalByteSecret() []byte {
return pk.Seed()
}
// UnmarshalByteSecret computes the private key from the secret seed
// and stores it in the private key object.
func (sk *PrivateKey) UnmarshalByteSecret(seed []byte) error {
sk.Key = ed448lib.NewKeyFromSeed(seed)
return nil
}
// GenerateKey generates a fresh private key with the provided randomness source.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
publicKey, privateKey, err := ed448lib.GenerateKey(rand)
if err != nil {
return nil, err
}
privateKeyOut := new(PrivateKey)
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Key = privateKey[:]
return privateKeyOut, nil
}
// Sign signs a message with the ed448 algorithm.
// priv MUST be a valid key! Check this with Validate() before use.
func Sign(priv *PrivateKey, message []byte) ([]byte, error) {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
return ed448lib.Sign(priv.Key, message, ""), nil
}
// Verify verifies a ed448 signature
func Verify(pub *PublicKey, message []byte, signature []byte) bool {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-08#section-13.7
return ed448lib.Verify(pub.Point, message, signature, "")
}
// Validate checks if the ed448 private key is valid
func Validate(priv *PrivateKey) error {
expectedPrivateKey := ed448lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv.Key, expectedPrivateKey) == 0 {
return errors.KeyInvalidError("ed448: invalid ed448 secret")
}
if subtle.ConstantTimeCompare(priv.PublicKey.Point, expectedPrivateKey[SeedSize:]) == 0 {
return errors.KeyInvalidError("ed448: invalid ed448 public key")
}
return nil
}
// ENCODING/DECODING signature:
// WriteSignature encodes and writes an ed448 signature to writer.
func WriteSignature(writer io.Writer, signature []byte) error {
_, err := writer.Write(signature)
return err
}
// ReadSignature decodes an ed448 signature from a reader.
func ReadSignature(reader io.Reader) ([]byte, error) {
signature := make([]byte, SignatureSize)
if _, err := io.ReadFull(reader, signature); err != nil {
return nil, err
}
return signature, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/eddsa/eddsa.go
================================================
// Package eddsa implements EdDSA signature, suitable for OpenPGP, as specified in
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
package eddsa
import (
"errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"io"
)
type PublicKey struct {
X []byte
curve ecc.EdDSACurve
}
type PrivateKey struct {
PublicKey
D []byte
}
func NewPublicKey(curve ecc.EdDSACurve) *PublicKey {
return &PublicKey{
curve: curve,
}
}
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
func (pk *PublicKey) GetCurve() ecc.EdDSACurve {
return pk.curve
}
func (pk *PublicKey) MarshalPoint() []byte {
return pk.curve.MarshalBytePoint(pk.X)
}
func (pk *PublicKey) UnmarshalPoint(x []byte) error {
pk.X = pk.curve.UnmarshalBytePoint(x)
if pk.X == nil {
return errors.New("eddsa: failed to parse EC point")
}
return nil
}
func (sk *PrivateKey) MarshalByteSecret() []byte {
return sk.curve.MarshalByteSecret(sk.D)
}
func (sk *PrivateKey) UnmarshalByteSecret(d []byte) error {
sk.D = sk.curve.UnmarshalByteSecret(d)
if sk.D == nil {
return errors.New("eddsa: failed to parse scalar")
}
return nil
}
func GenerateKey(rand io.Reader, c ecc.EdDSACurve) (priv *PrivateKey, err error) {
priv = new(PrivateKey)
priv.PublicKey.curve = c
priv.PublicKey.X, priv.D, err = c.GenerateEdDSA(rand)
return
}
func Sign(priv *PrivateKey, message []byte) (r, s []byte, err error) {
sig, err := priv.PublicKey.curve.Sign(priv.PublicKey.X, priv.D, message)
if err != nil {
return nil, nil, err
}
r, s = priv.PublicKey.curve.MarshalSignature(sig)
return
}
func Verify(pub *PublicKey, message, r, s []byte) bool {
sig := pub.curve.UnmarshalSignature(r, s)
if sig == nil {
return false
}
return pub.curve.Verify(pub.X, message, sig)
}
func Validate(priv *PrivateKey) error {
return priv.curve.ValidateEdDSA(priv.PublicKey.X, priv.D)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/elgamal/elgamal.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package elgamal implements ElGamal encryption, suitable for OpenPGP,
// as specified in "A Public-Key Cryptosystem and a Signature Scheme Based on
// Discrete Logarithms," IEEE Transactions on Information Theory, v. IT-31,
// n. 4, 1985, pp. 469-472.
//
// This form of ElGamal embeds PKCS#1 v1.5 padding, which may make it
// unsuitable for other protocols. RSA should be used in preference in any
// case.
package elgamal // import "github.com/ProtonMail/go-crypto/openpgp/elgamal"
import (
"crypto/rand"
"crypto/subtle"
"errors"
"io"
"math/big"
)
// PublicKey represents an ElGamal public key.
type PublicKey struct {
G, P, Y *big.Int
}
// PrivateKey represents an ElGamal private key.
type PrivateKey struct {
PublicKey
X *big.Int
}
// Encrypt encrypts the given message to the given public key. The result is a
// pair of integers. Errors can result from reading random, or because msg is
// too large to be encrypted to the public key.
func Encrypt(random io.Reader, pub *PublicKey, msg []byte) (c1, c2 *big.Int, err error) {
pLen := (pub.P.BitLen() + 7) / 8
if len(msg) > pLen-11 {
err = errors.New("elgamal: message too long")
return
}
// EM = 0x02 || PS || 0x00 || M
em := make([]byte, pLen-1)
em[0] = 2
ps, mm := em[1:len(em)-len(msg)-1], em[len(em)-len(msg):]
err = nonZeroRandomBytes(ps, random)
if err != nil {
return
}
em[len(em)-len(msg)-1] = 0
copy(mm, msg)
m := new(big.Int).SetBytes(em)
k, err := rand.Int(random, pub.P)
if err != nil {
return
}
c1 = new(big.Int).Exp(pub.G, k, pub.P)
s := new(big.Int).Exp(pub.Y, k, pub.P)
c2 = s.Mul(s, m)
c2.Mod(c2, pub.P)
return
}
// Decrypt takes two integers, resulting from an ElGamal encryption, and
// returns the plaintext of the message. An error can result only if the
// ciphertext is invalid. Users should keep in mind that this is a padding
// oracle and thus, if exposed to an adaptive chosen ciphertext attack, can
// be used to break the cryptosystem. See “Chosen Ciphertext Attacks
// Against Protocols Based on the RSA Encryption Standard PKCS #1”, Daniel
// Bleichenbacher, Advances in Cryptology (Crypto '98),
func Decrypt(priv *PrivateKey, c1, c2 *big.Int) (msg []byte, err error) {
s := new(big.Int).Exp(c1, priv.X, priv.P)
if s.ModInverse(s, priv.P) == nil {
return nil, errors.New("elgamal: invalid private key")
}
s.Mul(s, c2)
s.Mod(s, priv.P)
em := s.Bytes()
firstByteIsTwo := subtle.ConstantTimeByteEq(em[0], 2)
// The remainder of the plaintext must be a string of non-zero random
// octets, followed by a 0, followed by the message.
// lookingForIndex: 1 iff we are still looking for the zero.
// index: the offset of the first zero byte.
var lookingForIndex, index int
lookingForIndex = 1
for i := 1; i < len(em); i++ {
equals0 := subtle.ConstantTimeByteEq(em[i], 0)
index = subtle.ConstantTimeSelect(lookingForIndex&equals0, i, index)
lookingForIndex = subtle.ConstantTimeSelect(equals0, 0, lookingForIndex)
}
if firstByteIsTwo != 1 || lookingForIndex != 0 || index < 9 {
return nil, errors.New("elgamal: decryption error")
}
return em[index+1:], nil
}
// nonZeroRandomBytes fills the given slice with non-zero random octets.
func nonZeroRandomBytes(s []byte, rand io.Reader) (err error) {
_, err = io.ReadFull(rand, s)
if err != nil {
return
}
for i := 0; i < len(s); i++ {
for s[i] == 0 {
_, err = io.ReadFull(rand, s[i:i+1])
if err != nil {
return
}
}
}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/errors/errors.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package errors contains common error types for the OpenPGP packages.
package errors // import "github.com/ProtonMail/go-crypto/openpgp/errors"
import (
"strconv"
)
var (
// ErrDecryptSessionKeyParsing is a generic error message for parsing errors in decrypted data
// to reduce the risk of oracle attacks.
ErrDecryptSessionKeyParsing = DecryptWithSessionKeyError("parsing error")
// ErrAEADTagVerification is returned if one of the tag verifications in SEIPDv2 fails
ErrAEADTagVerification error = DecryptWithSessionKeyError("AEAD tag verification failed")
// ErrMDCHashMismatch
ErrMDCHashMismatch error = SignatureError("MDC hash mismatch")
// ErrMDCMissing
ErrMDCMissing error = SignatureError("MDC packet not found")
)
// A StructuralError is returned when OpenPGP data is found to be syntactically
// invalid.
type StructuralError string
func (s StructuralError) Error() string {
return "openpgp: invalid data: " + string(s)
}
// A DecryptWithSessionKeyError is returned when a failure occurs when reading from symmetrically decrypted data or
// an authentication tag verification fails.
// Such an error indicates that the supplied session key is likely wrong or the data got corrupted.
type DecryptWithSessionKeyError string
func (s DecryptWithSessionKeyError) Error() string {
return "openpgp: decryption with session key failed: " + string(s)
}
// HandleSensitiveParsingError handles parsing errors when reading data from potentially decrypted data.
// The function makes parsing errors generic to reduce the risk of oracle attacks in SEIPDv1.
func HandleSensitiveParsingError(err error, decrypted bool) error {
if !decrypted {
// Data was not encrypted so we return the inner error.
return err
}
// The data is read from a stream that decrypts using a session key;
// therefore, we need to handle parsing errors appropriately.
// This is essential to mitigate the risk of oracle attacks.
if decError, ok := err.(*DecryptWithSessionKeyError); ok {
return decError
}
if decError, ok := err.(DecryptWithSessionKeyError); ok {
return decError
}
return ErrDecryptSessionKeyParsing
}
// UnsupportedError indicates that, although the OpenPGP data is valid, it
// makes use of currently unimplemented features.
type UnsupportedError string
func (s UnsupportedError) Error() string {
return "openpgp: unsupported feature: " + string(s)
}
// InvalidArgumentError indicates that the caller is in error and passed an
// incorrect value.
type InvalidArgumentError string
func (i InvalidArgumentError) Error() string {
return "openpgp: invalid argument: " + string(i)
}
// SignatureError indicates that a syntactically valid signature failed to
// validate.
type SignatureError string
func (b SignatureError) Error() string {
return "openpgp: invalid signature: " + string(b)
}
type signatureExpiredError int
func (se signatureExpiredError) Error() string {
return "openpgp: signature expired"
}
var ErrSignatureExpired error = signatureExpiredError(0)
type keyExpiredError int
func (ke keyExpiredError) Error() string {
return "openpgp: key expired"
}
var ErrSignatureOlderThanKey error = signatureOlderThanKeyError(0)
type signatureOlderThanKeyError int
func (ske signatureOlderThanKeyError) Error() string {
return "openpgp: signature is older than the key"
}
var ErrKeyExpired error = keyExpiredError(0)
type keyIncorrectError int
func (ki keyIncorrectError) Error() string {
return "openpgp: incorrect key"
}
var ErrKeyIncorrect error = keyIncorrectError(0)
// KeyInvalidError indicates that the public key parameters are invalid
// as they do not match the private ones
type KeyInvalidError string
func (e KeyInvalidError) Error() string {
return "openpgp: invalid key: " + string(e)
}
type unknownIssuerError int
func (unknownIssuerError) Error() string {
return "openpgp: signature made by unknown entity"
}
var ErrUnknownIssuer error = unknownIssuerError(0)
type keyRevokedError int
func (keyRevokedError) Error() string {
return "openpgp: signature made by revoked key"
}
var ErrKeyRevoked error = keyRevokedError(0)
type WeakAlgorithmError string
func (e WeakAlgorithmError) Error() string {
return "openpgp: weak algorithms are rejected: " + string(e)
}
type UnknownPacketTypeError uint8
func (upte UnknownPacketTypeError) Error() string {
return "openpgp: unknown packet type: " + strconv.Itoa(int(upte))
}
type CriticalUnknownPacketTypeError uint8
func (upte CriticalUnknownPacketTypeError) Error() string {
return "openpgp: unknown critical packet type: " + strconv.Itoa(int(upte))
}
// AEADError indicates that there is a problem when initializing or using a
// AEAD instance, configuration struct, nonces or index values.
type AEADError string
func (ae AEADError) Error() string {
return "openpgp: aead error: " + string(ae)
}
// ErrDummyPrivateKey results when operations are attempted on a private key
// that is just a dummy key. See
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
type ErrDummyPrivateKey string
func (dke ErrDummyPrivateKey) Error() string {
return "openpgp: s2k GNU dummy key: " + string(dke)
}
// ErrMalformedMessage results when the packet sequence is incorrect
type ErrMalformedMessage string
func (dke ErrMalformedMessage) Error() string {
return "openpgp: malformed message " + string(dke)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/hash.go
================================================
package openpgp
import (
"crypto"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
return algorithm.HashIdToHash(id)
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
return algorithm.HashIdToString(id)
}
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
return algorithm.HashToHashId(h)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/aead.go
================================================
// Copyright (C) 2019 ProtonTech AG
package algorithm
import (
"crypto/cipher"
"github.com/ProtonMail/go-crypto/eax"
"github.com/ProtonMail/go-crypto/ocb"
)
// AEADMode defines the Authenticated Encryption with Associated Data mode of
// operation.
type AEADMode uint8
// Supported modes of operation (see RFC4880bis [EAX] and RFC7253)
const (
AEADModeEAX = AEADMode(1)
AEADModeOCB = AEADMode(2)
AEADModeGCM = AEADMode(3)
)
// TagLength returns the length in bytes of authentication tags.
func (mode AEADMode) TagLength() int {
switch mode {
case AEADModeEAX:
return 16
case AEADModeOCB:
return 16
case AEADModeGCM:
return 16
default:
return 0
}
}
// NonceLength returns the length in bytes of nonces.
func (mode AEADMode) NonceLength() int {
switch mode {
case AEADModeEAX:
return 16
case AEADModeOCB:
return 15
case AEADModeGCM:
return 12
default:
return 0
}
}
// New returns a fresh instance of the given mode
func (mode AEADMode) New(block cipher.Block) (alg cipher.AEAD) {
var err error
switch mode {
case AEADModeEAX:
alg, err = eax.NewEAX(block)
case AEADModeOCB:
alg, err = ocb.NewOCB(block)
case AEADModeGCM:
alg, err = cipher.NewGCM(block)
}
if err != nil {
panic(err.Error())
}
return alg
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/cipher.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package algorithm
import (
"crypto/aes"
"crypto/cipher"
"crypto/des"
"golang.org/x/crypto/cast5"
)
// Cipher is an official symmetric key cipher algorithm. See RFC 4880,
// section 9.2.
type Cipher interface {
// Id returns the algorithm ID, as a byte, of the cipher.
Id() uint8
// KeySize returns the key size, in bytes, of the cipher.
KeySize() int
// BlockSize returns the block size, in bytes, of the cipher.
BlockSize() int
// New returns a fresh instance of the given cipher.
New(key []byte) cipher.Block
}
// The following constants mirror the OpenPGP standard (RFC 4880).
const (
TripleDES = CipherFunction(2)
CAST5 = CipherFunction(3)
AES128 = CipherFunction(7)
AES192 = CipherFunction(8)
AES256 = CipherFunction(9)
)
// CipherById represents the different block ciphers specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
var CipherById = map[uint8]Cipher{
TripleDES.Id(): TripleDES,
CAST5.Id(): CAST5,
AES128.Id(): AES128,
AES192.Id(): AES192,
AES256.Id(): AES256,
}
type CipherFunction uint8
// ID returns the algorithm Id, as a byte, of cipher.
func (sk CipherFunction) Id() uint8 {
return uint8(sk)
}
// KeySize returns the key size, in bytes, of cipher.
func (cipher CipherFunction) KeySize() int {
switch cipher {
case CAST5:
return cast5.KeySize
case AES128:
return 16
case AES192, TripleDES:
return 24
case AES256:
return 32
}
return 0
}
// BlockSize returns the block size, in bytes, of cipher.
func (cipher CipherFunction) BlockSize() int {
switch cipher {
case TripleDES:
return des.BlockSize
case CAST5:
return 8
case AES128, AES192, AES256:
return 16
}
return 0
}
// New returns a fresh instance of the given cipher.
func (cipher CipherFunction) New(key []byte) (block cipher.Block) {
var err error
switch cipher {
case TripleDES:
block, err = des.NewTripleDESCipher(key)
case CAST5:
block, err = cast5.NewCipher(key)
case AES128, AES192, AES256:
block, err = aes.NewCipher(key)
}
if err != nil {
panic(err.Error())
}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/algorithm/hash.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package algorithm
import (
"crypto"
"fmt"
"hash"
)
// Hash is an official hash function algorithm. See RFC 4880, section 9.4.
type Hash interface {
// Id returns the algorithm ID, as a byte, of Hash.
Id() uint8
// Available reports whether the given hash function is linked into the binary.
Available() bool
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
HashFunc() crypto.Hash
// New returns a new hash.Hash calculating the given hash function. New
// panics if the hash function is not linked into the binary.
New() hash.Hash
// Size returns the length, in bytes, of a digest resulting from the given
// hash function. It doesn't require that the hash function in question be
// linked into the program.
Size() int
// String is the name of the hash function corresponding to the given
// OpenPGP hash id.
String() string
}
// The following vars mirror the crypto/Hash supported hash functions.
var (
SHA1 Hash = cryptoHash{2, crypto.SHA1}
SHA256 Hash = cryptoHash{8, crypto.SHA256}
SHA384 Hash = cryptoHash{9, crypto.SHA384}
SHA512 Hash = cryptoHash{10, crypto.SHA512}
SHA224 Hash = cryptoHash{11, crypto.SHA224}
SHA3_256 Hash = cryptoHash{12, crypto.SHA3_256}
SHA3_512 Hash = cryptoHash{14, crypto.SHA3_512}
)
// HashById represents the different hash functions specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-14
var (
HashById = map[uint8]Hash{
SHA256.Id(): SHA256,
SHA384.Id(): SHA384,
SHA512.Id(): SHA512,
SHA224.Id(): SHA224,
SHA3_256.Id(): SHA3_256,
SHA3_512.Id(): SHA3_512,
}
)
// cryptoHash contains pairs relating OpenPGP's hash identifier with
// Go's crypto.Hash type. See RFC 4880, section 9.4.
type cryptoHash struct {
id uint8
crypto.Hash
}
// Id returns the algorithm ID, as a byte, of cryptoHash.
func (h cryptoHash) Id() uint8 {
return h.id
}
var hashNames = map[uint8]string{
SHA256.Id(): "SHA256",
SHA384.Id(): "SHA384",
SHA512.Id(): "SHA512",
SHA224.Id(): "SHA224",
SHA3_256.Id(): "SHA3-256",
SHA3_512.Id(): "SHA3-512",
}
func (h cryptoHash) String() string {
s, ok := hashNames[h.id]
if !ok {
panic(fmt.Sprintf("Unsupported hash function %d", h.id))
}
return s
}
// HashIdToHash returns a crypto.Hash which corresponds to the given OpenPGP
// hash id.
func HashIdToHash(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
return 0, false
}
// HashIdToHashWithSha1 returns a crypto.Hash which corresponds to the given OpenPGP
// hash id, allowing sha1.
func HashIdToHashWithSha1(id byte) (h crypto.Hash, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.HashFunc(), true
}
if id == SHA1.Id() {
return SHA1.HashFunc(), true
}
return 0, false
}
// HashIdToString returns the name of the hash function corresponding to the
// given OpenPGP hash id.
func HashIdToString(id byte) (name string, ok bool) {
if hash, ok := HashById[id]; ok {
return hash.String(), true
}
return "", false
}
// HashToHashId returns an OpenPGP hash id which corresponds the given Hash.
func HashToHashId(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
return 0, false
}
// HashToHashIdWithSha1 returns an OpenPGP hash id which corresponds the given Hash,
// allowing instances of SHA1
func HashToHashIdWithSha1(h crypto.Hash) (id byte, ok bool) {
for id, hash := range HashById {
if hash.HashFunc() == h {
return id, true
}
}
if h == SHA1.HashFunc() {
return SHA1.Id(), true
}
return 0, false
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve25519.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x25519lib "github.com/cloudflare/circl/dh/x25519"
)
type curve25519 struct{}
func NewCurve25519() *curve25519 {
return &curve25519{}
}
func (c *curve25519) GetCurveName() string {
return "curve25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes the public point to native format, removing the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *curve25519) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x25519lib.Size+1 {
return nil
}
// Remove prefix
return point[1:]
}
// MarshalByteSecret encodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
// Note that leading zero bytes are stripped later when encoding as an MPI.
func (c *curve25519) MarshalByteSecret(secret []byte) []byte {
d := make([]byte, x25519lib.Size)
copyReversed(d, secret)
// The following ensures that the private key is a number of the form
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of
// the curve.
//
// This masking is done internally in the underlying lib and so is unnecessary
// for security, but OpenPGP implementations require that private keys be
// pre-masked.
d[0] &= 127
d[0] |= 64
d[31] &= 248
return d
}
// UnmarshalByteSecret decodes the secret scalar from native format.
// Note that the EC secret scalar differs from the definition of public keys in
// [Curve25519] in two ways: (1) the byte-ordering is big-endian, which is
// more uniform with how big integers are represented in OpenPGP, and (2) the
// leading zeros are truncated.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.1
func (c *curve25519) UnmarshalByteSecret(d []byte) []byte {
if len(d) > x25519lib.Size {
return nil
}
// Ensure truncated leading bytes are re-added
secret := make([]byte, x25519lib.Size)
copyReversed(secret, d)
return secret
}
// generateKeyPairBytes Generates a private-public key-pair.
// 'priv' is a private key; a little-endian scalar belonging to the set
// 2^{254} + 8 * [0, 2^{251}), in order to avoid the small subgroup of the
// curve. 'pub' is simply 'priv' * G where G is the base point.
// See https://cr.yp.to/ecdh.html and RFC7748, sec 5.
func (c *curve25519) generateKeyPairBytes(rand io.Reader) (priv, pub x25519lib.Key, err error) {
_, err = io.ReadFull(rand, priv[:])
if err != nil {
return
}
x25519lib.KeyGen(&pub, &priv)
return
}
func (c *curve25519) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *genericCurve) MaskSecret(secret []byte) []byte {
return secret
}
func (c *curve25519) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
// RFC6637 §8: "Generate an ephemeral key pair {v, V=vG}"
// ephemeralPrivate corresponds to `v`.
// ephemeralPublic corresponds to `V`.
ephemeralPrivate, ephemeralPublic, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
// RFC6637 §8: "Obtain the authenticated recipient public key R"
// pubKey corresponds to `R`.
var pubKey x25519lib.Key
copy(pubKey[:], point)
// RFC6637 §8: "Compute the shared point S = vR"
// "VB = convert point V to the octet string"
// sharedPoint corresponds to `VB`.
var sharedPoint x25519lib.Key
x25519lib.Shared(&sharedPoint, &ephemeralPrivate, &pubKey)
return ephemeralPublic[:], sharedPoint[:], nil
}
func (c *curve25519) Decaps(vsG, secret []byte) (sharedSecret []byte, err error) {
var ephemeralPublic, decodedPrivate, sharedPoint x25519lib.Key
// RFC6637 §8: "The decryption is the inverse of the method given."
// All quoted descriptions in comments below describe encryption, and
// the reverse is performed.
// vsG corresponds to `VB` in RFC6637 §8 .
// RFC6637 §8: "VB = convert point V to the octet string"
copy(ephemeralPublic[:], vsG)
// decodedPrivate corresponds to `r` in RFC6637 §8 .
copy(decodedPrivate[:], secret)
// RFC6637 §8: "Note that the recipient obtains the shared secret by calculating
// S = rV = rvG, where (r,R) is the recipient's key pair."
// sharedPoint corresponds to `S`.
x25519lib.Shared(&sharedPoint, &decodedPrivate, &ephemeralPublic)
return sharedPoint[:], nil
}
func (c *curve25519) ValidateECDH(point []byte, secret []byte) (err error) {
var pk, sk x25519lib.Key
copy(sk[:], secret)
x25519lib.KeyGen(&pk, &sk)
if subtle.ConstantTimeCompare(point, pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}
func copyReversed(out []byte, in []byte) {
l := len(in)
for i := 0; i < l; i++ {
out[i] = in[l-i-1]
}
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curve_info.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/elliptic"
"github.com/ProtonMail/go-crypto/bitcurves"
"github.com/ProtonMail/go-crypto/brainpool"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
)
const Curve25519GenName = "Curve25519"
type CurveInfo struct {
GenName string
Oid *encoding.OID
Curve Curve
}
var Curves = []CurveInfo{
{
// NIST P-256
GenName: "P256",
Oid: encoding.NewOID([]byte{0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07}),
Curve: NewGenericCurve(elliptic.P256()),
},
{
// NIST P-384
GenName: "P384",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x22}),
Curve: NewGenericCurve(elliptic.P384()),
},
{
// NIST P-521
GenName: "P521",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x23}),
Curve: NewGenericCurve(elliptic.P521()),
},
{
// SecP256k1
GenName: "SecP256k1",
Oid: encoding.NewOID([]byte{0x2B, 0x81, 0x04, 0x00, 0x0A}),
Curve: NewGenericCurve(bitcurves.S256()),
},
{
// Curve25519
GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01}),
Curve: NewCurve25519(),
},
{
// x448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x6F}),
Curve: NewX448(),
},
{
// Ed25519
GenName: Curve25519GenName,
Oid: encoding.NewOID([]byte{0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01}),
Curve: NewEd25519(),
},
{
// Ed448
GenName: "Curve448",
Oid: encoding.NewOID([]byte{0x2B, 0x65, 0x71}),
Curve: NewEd448(),
},
{
// BrainpoolP256r1
GenName: "BrainpoolP256",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07}),
Curve: NewGenericCurve(brainpool.P256r1()),
},
{
// BrainpoolP384r1
GenName: "BrainpoolP384",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0B}),
Curve: NewGenericCurve(brainpool.P384r1()),
},
{
// BrainpoolP512r1
GenName: "BrainpoolP512",
Oid: encoding.NewOID([]byte{0x2B, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0D}),
Curve: NewGenericCurve(brainpool.P512r1()),
},
}
func FindByCurve(curve Curve) *CurveInfo {
for _, curveInfo := range Curves {
if curveInfo.Curve.GetCurveName() == curve.GetCurveName() {
return &curveInfo
}
}
return nil
}
func FindByOid(oid encoding.Field) *CurveInfo {
var rawBytes = oid.Bytes()
for _, curveInfo := range Curves {
if bytes.Equal(curveInfo.Oid.Bytes(), rawBytes) {
return &curveInfo
}
}
return nil
}
func FindEdDSAByGenName(curveGenName string) EdDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(EdDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDSAByGenName(curveGenName string) ECDSACurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDSACurve)
if ok {
return curve
}
}
}
return nil
}
func FindECDHByGenName(curveGenName string) ECDHCurve {
for _, curveInfo := range Curves {
if curveInfo.GenName == curveGenName {
curve, ok := curveInfo.Curve.(ECDHCurve)
if ok {
return curve
}
}
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/curves.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"io"
"math/big"
)
type Curve interface {
GetCurveName() string
}
type ECDSACurve interface {
Curve
MarshalIntegerPoint(x, y *big.Int) []byte
UnmarshalIntegerPoint([]byte) (x, y *big.Int)
MarshalIntegerSecret(d *big.Int) []byte
UnmarshalIntegerSecret(d []byte) *big.Int
GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error)
Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error)
Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool
ValidateECDSA(x, y *big.Int, secret []byte) error
}
type EdDSACurve interface {
Curve
MarshalBytePoint(x []byte) []byte
UnmarshalBytePoint([]byte) (x []byte)
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
MarshalSignature(sig []byte) (r, s []byte)
UnmarshalSignature(r, s []byte) (sig []byte)
GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error)
Sign(publicKey, privateKey, message []byte) (sig []byte, err error)
Verify(publicKey, message, sig []byte) bool
ValidateEdDSA(publicKey, privateKey []byte) (err error)
}
type ECDHCurve interface {
Curve
MarshalBytePoint([]byte) (encoded []byte)
UnmarshalBytePoint(encoded []byte) []byte
MarshalByteSecret(d []byte) []byte
UnmarshalByteSecret(d []byte) []byte
GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error)
Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error)
Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error)
ValidateECDH(public []byte, secret []byte) error
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed25519.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed25519lib "github.com/cloudflare/circl/sign/ed25519"
)
const ed25519Size = 32
type ed25519 struct{}
func NewEd25519() *ed25519 {
return &ed25519{}
}
func (c *ed25519) GetCurveName() string {
return "ed25519"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalBytePoint(x []byte) []byte {
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed25519lib.PublicKeySize+1 {
return nil
}
// Return unprefixed
return point[1:]
}
// MarshalByteSecret encodes a scalar in native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) MarshalByteSecret(d []byte) []byte {
return d
}
// UnmarshalByteSecret decodes a scalar in native format and re-adds the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed25519) UnmarshalByteSecret(s []byte) (d []byte) {
if len(s) > ed25519lib.SeedSize {
return nil
}
// Handle stripped leading zeroes
d = make([]byte, ed25519lib.SeedSize)
copy(d[ed25519lib.SeedSize-len(s):], s)
return
}
// MarshalSignature splits a signature in R and S.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) MarshalSignature(sig []byte) (r, s []byte) {
return sig[:ed25519Size], sig[ed25519Size:]
}
// UnmarshalSignature decodes R and S in the native format, re-adding the stripped leading zeroes
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.1
func (c *ed25519) UnmarshalSignature(r, s []byte) (sig []byte) {
// Check size
if len(r) > 32 || len(s) > 32 {
return nil
}
sig = make([]byte, ed25519lib.SignatureSize)
// Handle stripped leading zeroes
copy(sig[ed25519Size-len(r):ed25519Size], r)
copy(sig[ed25519lib.SignatureSize-len(s):], s)
return sig
}
func (c *ed25519) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed25519lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed25519lib.SeedSize], nil
}
func getEd25519Sk(publicKey, privateKey []byte) ed25519lib.PrivateKey {
privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
if privateKeyCap >= privateKeyLen+publicKeyLen &&
bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
return privateKey[:privateKeyLen+publicKeyLen]
}
return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed25519) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
sig = ed25519lib.Sign(getEd25519Sk(publicKey, privateKey), message)
return sig, nil
}
func (c *ed25519) Verify(publicKey, message, sig []byte) bool {
return ed25519lib.Verify(publicKey, message, sig)
}
func (c *ed25519) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd25519Sk(publicKey, privateKey)
expectedPriv := ed25519lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed25519 secret")
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/ed448.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"bytes"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
ed448lib "github.com/cloudflare/circl/sign/ed448"
)
type ed448 struct{}
func NewEd448() *ed448 {
return &ed448{}
}
func (c *ed448) GetCurveName() string {
return "ed448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalBytePoint(x []byte) []byte {
// Return prefixed
return append([]byte{0x40}, x...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalBytePoint(point []byte) (x []byte) {
if len(point) != ed448lib.PublicKeySize+1 {
return nil
}
// Strip prefix
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) MarshalByteSecret(d []byte) []byte {
// Return prefixed
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.5
func (c *ed448) UnmarshalByteSecret(s []byte) (d []byte) {
// Check prefixed size
if len(s) != ed448lib.SeedSize+1 {
return nil
}
// Strip prefix
return s[1:]
}
// MarshalSignature splits a signature in R and S, where R is in prefixed native format and
// S is an MPI with value zero.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) MarshalSignature(sig []byte) (r, s []byte) {
return append([]byte{0x40}, sig...), []byte{}
}
// UnmarshalSignature decodes R and S in the native format. Only R is used, in prefixed native format.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.2.3.3.2
func (c *ed448) UnmarshalSignature(r, s []byte) (sig []byte) {
if len(r) != ed448lib.SignatureSize+1 {
return nil
}
return r[1:]
}
func (c *ed448) GenerateEdDSA(rand io.Reader) (pub, priv []byte, err error) {
pk, sk, err := ed448lib.GenerateKey(rand)
if err != nil {
return nil, nil, err
}
return pk, sk[:ed448lib.SeedSize], nil
}
func getEd448Sk(publicKey, privateKey []byte) ed448lib.PrivateKey {
privateKeyCap, privateKeyLen, publicKeyLen := cap(privateKey), len(privateKey), len(publicKey)
if privateKeyCap >= privateKeyLen+publicKeyLen &&
bytes.Equal(privateKey[privateKeyLen:privateKeyLen+publicKeyLen], publicKey) {
return privateKey[:privateKeyLen+publicKeyLen]
}
return append(privateKey[:privateKeyLen:privateKeyLen], publicKey...)
}
func (c *ed448) Sign(publicKey, privateKey, message []byte) (sig []byte, err error) {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
sig = ed448lib.Sign(getEd448Sk(publicKey, privateKey), message, "")
return sig, nil
}
func (c *ed448) Verify(publicKey, message, sig []byte) bool {
// Ed448 is used with the empty string as a context string.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-13.7
return ed448lib.Verify(publicKey, message, sig, "")
}
func (c *ed448) ValidateEdDSA(publicKey, privateKey []byte) (err error) {
priv := getEd448Sk(publicKey, privateKey)
expectedPriv := ed448lib.NewKeyFromSeed(priv.Seed())
if subtle.ConstantTimeCompare(priv, expectedPriv) == 0 {
return errors.KeyInvalidError("ecc: invalid ed448 secret")
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/generic.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/ecdsa"
"crypto/elliptic"
"fmt"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"io"
"math/big"
)
type genericCurve struct {
Curve elliptic.Curve
}
func NewGenericCurve(c elliptic.Curve) *genericCurve {
return &genericCurve{
Curve: c,
}
}
func (c *genericCurve) GetCurveName() string {
return c.Curve.Params().Name
}
func (c *genericCurve) MarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) UnmarshalBytePoint(point []byte) []byte {
return point
}
func (c *genericCurve) MarshalIntegerPoint(x, y *big.Int) []byte {
return elliptic.Marshal(c.Curve, x, y)
}
func (c *genericCurve) UnmarshalIntegerPoint(point []byte) (x, y *big.Int) {
return elliptic.Unmarshal(c.Curve, point)
}
func (c *genericCurve) MarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) UnmarshalByteSecret(d []byte) []byte {
return d
}
func (c *genericCurve) MarshalIntegerSecret(d *big.Int) []byte {
return d.Bytes()
}
func (c *genericCurve) UnmarshalIntegerSecret(d []byte) *big.Int {
return new(big.Int).SetBytes(d)
}
func (c *genericCurve) GenerateECDH(rand io.Reader) (point, secret []byte, err error) {
secret, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
point = elliptic.Marshal(c.Curve, x, y)
return point, secret, nil
}
func (c *genericCurve) GenerateECDSA(rand io.Reader) (x, y, secret *big.Int, err error) {
priv, err := ecdsa.GenerateKey(c.Curve, rand)
if err != nil {
return
}
return priv.X, priv.Y, priv.D, nil
}
func (c *genericCurve) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
panic("invalid point")
}
d, x, y, err := elliptic.GenerateKey(c.Curve, rand)
if err != nil {
return nil, nil, err
}
vsG := elliptic.Marshal(c.Curve, x, y)
zbBig, _ := c.Curve.ScalarMult(xP, yP, d)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return vsG, zb, nil
}
func (c *genericCurve) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
x, y := elliptic.Unmarshal(c.Curve, ephemeral)
zbBig, _ := c.Curve.ScalarMult(x, y, secret)
byteLen := (c.Curve.Params().BitSize + 7) >> 3
zb := make([]byte, byteLen)
zbBytes := zbBig.Bytes()
copy(zb[byteLen-len(zbBytes):], zbBytes)
return zb, nil
}
func (c *genericCurve) Sign(rand io.Reader, x, y, d *big.Int, hash []byte) (r, s *big.Int, err error) {
priv := &ecdsa.PrivateKey{D: d, PublicKey: ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}}
return ecdsa.Sign(rand, priv, hash)
}
func (c *genericCurve) Verify(x, y *big.Int, hash []byte, r, s *big.Int) bool {
pub := &ecdsa.PublicKey{X: x, Y: y, Curve: c.Curve}
return ecdsa.Verify(pub, hash, r, s)
}
func (c *genericCurve) validate(xP, yP *big.Int, secret []byte) error {
// the public point should not be at infinity (0,0)
zero := new(big.Int)
if xP.Cmp(zero) == 0 && yP.Cmp(zero) == 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): infinity point", c.Curve.Params().Name))
}
// re-derive the public point Q' = (X,Y) = dG
// to compare to declared Q in public key
expectedX, expectedY := c.Curve.ScalarBaseMult(secret)
if xP.Cmp(expectedX) != 0 || yP.Cmp(expectedY) != 0 {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return nil
}
func (c *genericCurve) ValidateECDSA(xP, yP *big.Int, secret []byte) error {
return c.validate(xP, yP, secret)
}
func (c *genericCurve) ValidateECDH(point []byte, secret []byte) error {
xP, yP := elliptic.Unmarshal(c.Curve, point)
if xP == nil {
return errors.KeyInvalidError(fmt.Sprintf("ecc (%s): invalid point", c.Curve.Params().Name))
}
return c.validate(xP, yP, secret)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/ecc/x448.go
================================================
// Package ecc implements a generic interface for ECDH, ECDSA, and EdDSA.
package ecc
import (
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x448lib "github.com/cloudflare/circl/dh/x448"
)
type x448 struct{}
func NewX448() *x448 {
return &x448{}
}
func (c *x448) GetCurveName() string {
return "x448"
}
// MarshalBytePoint encodes the public point from native format, adding the prefix.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) MarshalBytePoint(point []byte) []byte {
return append([]byte{0x40}, point...)
}
// UnmarshalBytePoint decodes a point from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6
func (c *x448) UnmarshalBytePoint(point []byte) []byte {
if len(point) != x448lib.Size+1 {
return nil
}
return point[1:]
}
// MarshalByteSecret encoded a scalar from native format to prefixed.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) MarshalByteSecret(d []byte) []byte {
return append([]byte{0x40}, d...)
}
// UnmarshalByteSecret decodes a scalar from prefixed format to native.
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh-06#section-5.5.5.6.1.2
func (c *x448) UnmarshalByteSecret(d []byte) []byte {
if len(d) != x448lib.Size+1 {
return nil
}
// Store without prefix
return d[1:]
}
func (c *x448) generateKeyPairBytes(rand io.Reader) (sk, pk x448lib.Key, err error) {
if _, err = rand.Read(sk[:]); err != nil {
return
}
x448lib.KeyGen(&pk, &sk)
return
}
func (c *x448) GenerateECDH(rand io.Reader) (point []byte, secret []byte, err error) {
priv, pub, err := c.generateKeyPairBytes(rand)
if err != nil {
return
}
return pub[:], priv[:], nil
}
func (c *x448) Encaps(rand io.Reader, point []byte) (ephemeral, sharedSecret []byte, err error) {
var pk, ss x448lib.Key
seed, e, err := c.generateKeyPairBytes(rand)
if err != nil {
return nil, nil, err
}
copy(pk[:], point)
x448lib.Shared(&ss, &seed, &pk)
return e[:], ss[:], nil
}
func (c *x448) Decaps(ephemeral, secret []byte) (sharedSecret []byte, err error) {
var ss, sk, e x448lib.Key
copy(sk[:], secret)
copy(e[:], ephemeral)
x448lib.Shared(&ss, &sk, &e)
return ss[:], nil
}
func (c *x448) ValidateECDH(point []byte, secret []byte) error {
var sk, pk, expectedPk x448lib.Key
copy(pk[:], point)
copy(sk[:], secret)
x448lib.KeyGen(&expectedPk, &sk)
if subtle.ConstantTimeCompare(expectedPk[:], pk[:]) == 0 {
return errors.KeyInvalidError("ecc: invalid curve25519 public point")
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/encoding.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package encoding implements openpgp packet field encodings as specified in
// RFC 4880 and 6637.
package encoding
import "io"
// Field is an encoded field of an openpgp packet.
type Field interface {
// Bytes returns the decoded data.
Bytes() []byte
// BitLength is the size in bits of the decoded data.
BitLength() uint16
// EncodedBytes returns the encoded data.
EncodedBytes() []byte
// EncodedLength is the size in bytes of the encoded data.
EncodedLength() uint16
// ReadFrom reads the next Field from r.
ReadFrom(r io.Reader) (int64, error)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/mpi.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package encoding
import (
"io"
"math/big"
"math/bits"
)
// An MPI is used to store the contents of a big integer, along with the bit
// length that was specified in the original input. This allows the MPI to be
// reserialized exactly.
type MPI struct {
bytes []byte
bitLength uint16
}
// NewMPI returns a MPI initialized with bytes.
func NewMPI(bytes []byte) *MPI {
for len(bytes) != 0 && bytes[0] == 0 {
bytes = bytes[1:]
}
if len(bytes) == 0 {
bitLength := uint16(0)
return &MPI{bytes, bitLength}
}
bitLength := 8*uint16(len(bytes)-1) + uint16(bits.Len8(bytes[0]))
return &MPI{bytes, bitLength}
}
// Bytes returns the decoded data.
func (m *MPI) Bytes() []byte {
return m.bytes
}
// BitLength is the size in bits of the decoded data.
func (m *MPI) BitLength() uint16 {
return m.bitLength
}
// EncodedBytes returns the encoded data.
func (m *MPI) EncodedBytes() []byte {
return append([]byte{byte(m.bitLength >> 8), byte(m.bitLength)}, m.bytes...)
}
// EncodedLength is the size in bytes of the encoded data.
func (m *MPI) EncodedLength() uint16 {
return uint16(2 + len(m.bytes))
}
// ReadFrom reads into m the next MPI from r.
func (m *MPI) ReadFrom(r io.Reader) (int64, error) {
var buf [2]byte
n, err := io.ReadFull(r, buf[0:])
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n), err
}
m.bitLength = uint16(buf[0])<<8 | uint16(buf[1])
m.bytes = make([]byte, (int(m.bitLength)+7)/8)
nn, err := io.ReadFull(r, m.bytes)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
// remove leading zero bytes from malformed GnuPG encoded MPIs:
// https://bugs.gnupg.org/gnupg/issue1853
// for _, b := range m.bytes {
// if b != 0 {
// break
// }
// m.bytes = m.bytes[1:]
// m.bitLength -= 8
// }
return int64(n) + int64(nn), err
}
// SetBig initializes m with the bits from n.
func (m *MPI) SetBig(n *big.Int) *MPI {
m.bytes = n.Bytes()
m.bitLength = uint16(n.BitLen())
return m
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/internal/encoding/oid.go
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package encoding
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// OID is used to store a variable-length field with a one-octet size
// prefix. See https://tools.ietf.org/html/rfc6637#section-9.
type OID struct {
bytes []byte
}
const (
// maxOID is the maximum number of bytes in a OID.
maxOID = 254
// reservedOIDLength1 and reservedOIDLength2 are OID lengths that the RFC
// specifies are reserved.
reservedOIDLength1 = 0
reservedOIDLength2 = 0xff
)
// NewOID returns a OID initialized with bytes.
func NewOID(bytes []byte) *OID {
switch len(bytes) {
case reservedOIDLength1, reservedOIDLength2:
panic("encoding: NewOID argument length is reserved")
default:
if len(bytes) > maxOID {
panic("encoding: NewOID argument too large")
}
}
return &OID{
bytes: bytes,
}
}
// Bytes returns the decoded data.
func (o *OID) Bytes() []byte {
return o.bytes
}
// BitLength is the size in bits of the decoded data.
func (o *OID) BitLength() uint16 {
return uint16(len(o.bytes) * 8)
}
// EncodedBytes returns the encoded data.
func (o *OID) EncodedBytes() []byte {
return append([]byte{byte(len(o.bytes))}, o.bytes...)
}
// EncodedLength is the size in bytes of the encoded data.
func (o *OID) EncodedLength() uint16 {
return uint16(1 + len(o.bytes))
}
// ReadFrom reads into b the next OID from r.
func (o *OID) ReadFrom(r io.Reader) (int64, error) {
var buf [1]byte
n, err := io.ReadFull(r, buf[:])
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n), err
}
switch buf[0] {
case reservedOIDLength1, reservedOIDLength2:
return int64(n), errors.UnsupportedError("reserved for future extensions")
}
o.bytes = make([]byte, buf[0])
nn, err := io.ReadFull(r, o.bytes)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return int64(n) + int64(nn), err
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/key_generation.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
"crypto"
"crypto/rand"
"crypto/rsa"
goerrors "errors"
"io"
"math/big"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/ed25519"
"github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/ProtonMail/go-crypto/openpgp/x25519"
"github.com/ProtonMail/go-crypto/openpgp/x448"
)
// NewEntity returns an Entity that contains a fresh RSA/RSA keypair with a
// single identity composed of the given full name, comment and email, any of
// which may be empty but must not contain any of "()<>\x00".
// If config is nil, sensible defaults will be used.
func NewEntity(name, comment, email string, config *packet.Config) (*Entity, error) {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
// Generate a primary signing key
primaryPrivRaw, err := newSigner(config)
if err != nil {
return nil, err
}
primary := packet.NewSignerPrivateKey(creationTime, primaryPrivRaw)
if config.V6() {
if err := primary.UpgradeToV6(); err != nil {
return nil, err
}
}
e := &Entity{
PrimaryKey: &primary.PublicKey,
PrivateKey: primary,
Identities: make(map[string]*Identity),
Subkeys: []Subkey{},
Signatures: []*packet.Signature{},
}
if config.V6() {
// In v6 keys algorithm preferences should be stored in direct key signatures
selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypeDirectSignature, config)
err = writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
if err != nil {
return nil, err
}
err = selfSignature.SignDirectKeyBinding(&primary.PublicKey, primary, config)
if err != nil {
return nil, err
}
e.Signatures = append(e.Signatures, selfSignature)
e.SelfSignature = selfSignature
}
err = e.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
if err != nil {
return nil, err
}
// NOTE: No key expiry here, but we will not return this subkey in EncryptionKey()
// if the primary/master key has expired.
err = e.addEncryptionSubkey(config, creationTime, 0)
if err != nil {
return nil, err
}
return e, nil
}
func (t *Entity) AddUserId(name, comment, email string, config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
return t.addUserId(name, comment, email, config, creationTime, keyLifetimeSecs, !config.V6())
}
func writeKeyProperties(selfSignature *packet.Signature, creationTime time.Time, keyLifetimeSecs uint32, config *packet.Config) error {
advertiseAead := config.AEAD() != nil
selfSignature.CreationTime = creationTime
selfSignature.KeyLifetimeSecs = &keyLifetimeSecs
selfSignature.FlagsValid = true
selfSignature.FlagSign = true
selfSignature.FlagCertify = true
selfSignature.SEIPDv1 = true // true by default, see 5.8 vs. 5.14
selfSignature.SEIPDv2 = advertiseAead
// Set the PreferredHash for the SelfSignature from the packet.Config.
// If it is not the must-implement algorithm from rfc4880bis, append that.
hash, ok := algorithm.HashToHashId(config.Hash())
if !ok {
return errors.UnsupportedError("unsupported preferred hash function")
}
selfSignature.PreferredHash = []uint8{hash}
if config.Hash() != crypto.SHA256 {
selfSignature.PreferredHash = append(selfSignature.PreferredHash, hashToHashId(crypto.SHA256))
}
// Likewise for DefaultCipher.
selfSignature.PreferredSymmetric = []uint8{uint8(config.Cipher())}
if config.Cipher() != packet.CipherAES128 {
selfSignature.PreferredSymmetric = append(selfSignature.PreferredSymmetric, uint8(packet.CipherAES128))
}
// We set CompressionNone as the preferred compression algorithm because
// of compression side channel attacks, then append the configured
// DefaultCompressionAlgo if any is set (to signal support for cases
// where the application knows that using compression is safe).
selfSignature.PreferredCompression = []uint8{uint8(packet.CompressionNone)}
if config.Compression() != packet.CompressionNone {
selfSignature.PreferredCompression = append(selfSignature.PreferredCompression, uint8(config.Compression()))
}
if advertiseAead {
// Get the preferred AEAD mode from the packet.Config.
// If it is not the must-implement algorithm from rfc9580, append that.
modes := []uint8{uint8(config.AEAD().Mode())}
if config.AEAD().Mode() != packet.AEADModeOCB {
modes = append(modes, uint8(packet.AEADModeOCB))
}
// For preferred (AES256, GCM), we'll generate (AES256, GCM), (AES256, OCB), (AES128, GCM), (AES128, OCB)
for _, cipher := range selfSignature.PreferredSymmetric {
for _, mode := range modes {
selfSignature.PreferredCipherSuites = append(selfSignature.PreferredCipherSuites, [2]uint8{cipher, mode})
}
}
}
return nil
}
func (t *Entity) addUserId(name, comment, email string, config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32, writeProperties bool) error {
uid := packet.NewUserId(name, comment, email)
if uid == nil {
return errors.InvalidArgumentError("user id field contained invalid characters")
}
if _, ok := t.Identities[uid.Id]; ok {
return errors.InvalidArgumentError("user id exist")
}
primary := t.PrivateKey
isPrimaryId := len(t.Identities) == 0
selfSignature := createSignaturePacket(&primary.PublicKey, packet.SigTypePositiveCert, config)
if writeProperties {
err := writeKeyProperties(selfSignature, creationTime, keyLifetimeSecs, config)
if err != nil {
return err
}
}
selfSignature.IsPrimaryId = &isPrimaryId
// User ID binding signature
err := selfSignature.SignUserId(uid.Id, &primary.PublicKey, primary, config)
if err != nil {
return err
}
t.Identities[uid.Id] = &Identity{
Name: uid.Id,
UserId: uid,
SelfSignature: selfSignature,
Signatures: []*packet.Signature{selfSignature},
}
return nil
}
// AddSigningSubkey adds a signing keypair as a subkey to the Entity.
// If config is nil, sensible defaults will be used.
func (e *Entity) AddSigningSubkey(config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
subPrivRaw, err := newSigner(config)
if err != nil {
return err
}
sub := packet.NewSignerPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
if config.V6() {
if err := sub.UpgradeToV6(); err != nil {
return err
}
}
subkey := Subkey{
PublicKey: &sub.PublicKey,
PrivateKey: sub,
}
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
subkey.Sig.CreationTime = creationTime
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
subkey.Sig.FlagsValid = true
subkey.Sig.FlagSign = true
subkey.Sig.EmbeddedSignature = createSignaturePacket(subkey.PublicKey, packet.SigTypePrimaryKeyBinding, config)
subkey.Sig.EmbeddedSignature.CreationTime = creationTime
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey, subkey.PrivateKey, config)
if err != nil {
return err
}
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return err
}
e.Subkeys = append(e.Subkeys, subkey)
return nil
}
// AddEncryptionSubkey adds an encryption keypair as a subkey to the Entity.
// If config is nil, sensible defaults will be used.
func (e *Entity) AddEncryptionSubkey(config *packet.Config) error {
creationTime := config.Now()
keyLifetimeSecs := config.KeyLifetime()
return e.addEncryptionSubkey(config, creationTime, keyLifetimeSecs)
}
func (e *Entity) addEncryptionSubkey(config *packet.Config, creationTime time.Time, keyLifetimeSecs uint32) error {
subPrivRaw, err := newDecrypter(config)
if err != nil {
return err
}
sub := packet.NewDecrypterPrivateKey(creationTime, subPrivRaw)
sub.IsSubkey = true
if config.V6() {
if err := sub.UpgradeToV6(); err != nil {
return err
}
}
subkey := Subkey{
PublicKey: &sub.PublicKey,
PrivateKey: sub,
}
subkey.Sig = createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyBinding, config)
subkey.Sig.CreationTime = creationTime
subkey.Sig.KeyLifetimeSecs = &keyLifetimeSecs
subkey.Sig.FlagsValid = true
subkey.Sig.FlagEncryptStorage = true
subkey.Sig.FlagEncryptCommunications = true
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return err
}
e.Subkeys = append(e.Subkeys, subkey)
return nil
}
// Generates a signing key
func newSigner(config *packet.Config) (signer interface{}, err error) {
switch config.PublicKeyAlgorithm() {
case packet.PubKeyAlgoRSA:
bits := config.RSAModulusBits()
if bits < 1024 {
return nil, errors.InvalidArgumentError("bits must be >= 1024")
}
if config != nil && len(config.RSAPrimes) >= 2 {
primes := config.RSAPrimes[0:2]
config.RSAPrimes = config.RSAPrimes[2:]
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
}
return rsa.GenerateKey(config.Random(), bits)
case packet.PubKeyAlgoEdDSA:
if config.V6() {
// Implementations MUST NOT accept or generate v6 key material
// using the deprecated OIDs.
return nil, errors.InvalidArgumentError("EdDSALegacy cannot be used for v6 keys")
}
curve := ecc.FindEdDSAByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
priv, err := eddsa.GenerateKey(config.Random(), curve)
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoECDSA:
curve := ecc.FindECDSAByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
priv, err := ecdsa.GenerateKey(config.Random(), curve)
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoEd25519:
priv, err := ed25519.GenerateKey(config.Random())
if err != nil {
return nil, err
}
return priv, nil
case packet.PubKeyAlgoEd448:
priv, err := ed448.GenerateKey(config.Random())
if err != nil {
return nil, err
}
return priv, nil
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
}
// Generates an encryption/decryption key
func newDecrypter(config *packet.Config) (decrypter interface{}, err error) {
switch config.PublicKeyAlgorithm() {
case packet.PubKeyAlgoRSA:
bits := config.RSAModulusBits()
if bits < 1024 {
return nil, errors.InvalidArgumentError("bits must be >= 1024")
}
if config != nil && len(config.RSAPrimes) >= 2 {
primes := config.RSAPrimes[0:2]
config.RSAPrimes = config.RSAPrimes[2:]
return generateRSAKeyWithPrimes(config.Random(), 2, bits, primes)
}
return rsa.GenerateKey(config.Random(), bits)
case packet.PubKeyAlgoEdDSA, packet.PubKeyAlgoECDSA:
fallthrough // When passing EdDSA or ECDSA, we generate an ECDH subkey
case packet.PubKeyAlgoECDH:
if config.V6() &&
(config.CurveName() == packet.Curve25519 ||
config.CurveName() == packet.Curve448) {
// Implementations MUST NOT accept or generate v6 key material
// using the deprecated OIDs.
return nil, errors.InvalidArgumentError("ECDH with Curve25519/448 legacy cannot be used for v6 keys")
}
var kdf = ecdh.KDF{
Hash: algorithm.SHA512,
Cipher: algorithm.AES256,
}
curve := ecc.FindECDHByGenName(string(config.CurveName()))
if curve == nil {
return nil, errors.InvalidArgumentError("unsupported curve")
}
return ecdh.GenerateKey(config.Random(), curve, kdf)
case packet.PubKeyAlgoEd25519, packet.PubKeyAlgoX25519: // When passing Ed25519, we generate an x25519 subkey
return x25519.GenerateKey(config.Random())
case packet.PubKeyAlgoEd448, packet.PubKeyAlgoX448: // When passing Ed448, we generate an x448 subkey
return x448.GenerateKey(config.Random())
default:
return nil, errors.InvalidArgumentError("unsupported public key algorithm")
}
}
var bigOne = big.NewInt(1)
// generateRSAKeyWithPrimes generates a multi-prime RSA keypair of the
// given bit size, using the given random source and pre-populated primes.
func generateRSAKeyWithPrimes(random io.Reader, nprimes int, bits int, prepopulatedPrimes []*big.Int) (*rsa.PrivateKey, error) {
priv := new(rsa.PrivateKey)
priv.E = 65537
if nprimes < 2 {
return nil, goerrors.New("generateRSAKeyWithPrimes: nprimes must be >= 2")
}
if bits < 1024 {
return nil, goerrors.New("generateRSAKeyWithPrimes: bits must be >= 1024")
}
primes := make([]*big.Int, nprimes)
NextSetOfPrimes:
for {
todo := bits
// crypto/rand should set the top two bits in each prime.
// Thus each prime has the form
// p_i = 2^bitlen(p_i) × 0.11... (in base 2).
// And the product is:
// P = 2^todo × α
// where α is the product of nprimes numbers of the form 0.11...
//
// If α < 1/2 (which can happen for nprimes > 2), we need to
// shift todo to compensate for lost bits: the mean value of 0.11...
// is 7/8, so todo + shift - nprimes * log2(7/8) ~= bits - 1/2
// will give good results.
if nprimes >= 7 {
todo += (nprimes - 2) / 5
}
for i := 0; i < nprimes; i++ {
var err error
if len(prepopulatedPrimes) == 0 {
primes[i], err = rand.Prime(random, todo/(nprimes-i))
if err != nil {
return nil, err
}
} else {
primes[i] = prepopulatedPrimes[0]
prepopulatedPrimes = prepopulatedPrimes[1:]
}
todo -= primes[i].BitLen()
}
// Make sure that primes is pairwise unequal.
for i, prime := range primes {
for j := 0; j < i; j++ {
if prime.Cmp(primes[j]) == 0 {
continue NextSetOfPrimes
}
}
}
n := new(big.Int).Set(bigOne)
totient := new(big.Int).Set(bigOne)
pminus1 := new(big.Int)
for _, prime := range primes {
n.Mul(n, prime)
pminus1.Sub(prime, bigOne)
totient.Mul(totient, pminus1)
}
if n.BitLen() != bits {
// This should never happen for nprimes == 2 because
// crypto/rand should set the top two bits in each prime.
// For nprimes > 2 we hope it does not happen often.
continue NextSetOfPrimes
}
priv.D = new(big.Int)
e := big.NewInt(int64(priv.E))
ok := priv.D.ModInverse(e, totient)
if ok != nil {
priv.Primes = primes
priv.N = n
break
}
}
priv.Precompute()
return priv, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/keys.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
goerrors "errors"
"fmt"
"io"
"time"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/packet"
)
// PublicKeyType is the armor type for a PGP public key.
var PublicKeyType = "PGP PUBLIC KEY BLOCK"
// PrivateKeyType is the armor type for a PGP private key.
var PrivateKeyType = "PGP PRIVATE KEY BLOCK"
// An Entity represents the components of an OpenPGP key: a primary public key
// (which must be a signing key), one or more identities claimed by that key,
// and zero or more subkeys, which may be encryption keys.
type Entity struct {
PrimaryKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Identities map[string]*Identity // indexed by Identity.Name
Revocations []*packet.Signature
Subkeys []Subkey
SelfSignature *packet.Signature // Direct-key self signature of the PrimaryKey (contains primary key properties in v6)
Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
}
// An Identity represents an identity claimed by an Entity and zero or more
// assertions by other entities about that claim.
type Identity struct {
Name string // by convention, has the form "Full Name (comment) "
UserId *packet.UserId
SelfSignature *packet.Signature
Revocations []*packet.Signature
Signatures []*packet.Signature // all (potentially unverified) self-signatures, revocations, and third-party signatures
}
// A Subkey is an additional public key in an Entity. Subkeys can be used for
// encryption.
type Subkey struct {
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
Sig *packet.Signature
Revocations []*packet.Signature
}
// A Key identifies a specific public key in an Entity. This is either the
// Entity's primary key or a subkey.
type Key struct {
Entity *Entity
PublicKey *packet.PublicKey
PrivateKey *packet.PrivateKey
SelfSignature *packet.Signature
Revocations []*packet.Signature
}
// A KeyRing provides access to public and private keys.
type KeyRing interface {
// KeysById returns the set of keys that have the given key id.
KeysById(id uint64) []Key
// KeysByIdAndUsage returns the set of keys with the given id
// that also meet the key usage given by requiredUsage.
// The requiredUsage is expressed as the bitwise-OR of
// packet.KeyFlag* values.
KeysByIdUsage(id uint64, requiredUsage byte) []Key
// DecryptionKeys returns all private keys that are valid for
// decryption.
DecryptionKeys() []Key
}
// PrimaryIdentity returns an Identity, preferring non-revoked identities,
// identities marked as primary, or the latest-created identity, in that order.
func (e *Entity) PrimaryIdentity() *Identity {
var primaryIdentity *Identity
for _, ident := range e.Identities {
if shouldPreferIdentity(primaryIdentity, ident) {
primaryIdentity = ident
}
}
return primaryIdentity
}
func shouldPreferIdentity(existingId, potentialNewId *Identity) bool {
if existingId == nil {
return true
}
if len(existingId.Revocations) > len(potentialNewId.Revocations) {
return true
}
if len(existingId.Revocations) < len(potentialNewId.Revocations) {
return false
}
if existingId.SelfSignature == nil {
return true
}
if existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId &&
!(potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId) {
return false
}
if !(existingId.SelfSignature.IsPrimaryId != nil && *existingId.SelfSignature.IsPrimaryId) &&
potentialNewId.SelfSignature.IsPrimaryId != nil && *potentialNewId.SelfSignature.IsPrimaryId {
return true
}
return potentialNewId.SelfSignature.CreationTime.After(existingId.SelfSignature.CreationTime)
}
// EncryptionKey returns the best candidate Key for encrypting a message to the
// given Entity.
func (e *Entity) EncryptionKey(now time.Time) (Key, bool) {
// Fail to find any encryption key if the...
primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
if primarySelfSignature == nil || // no self-signature found
e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
primarySelfSignature.SigExpired(now) || // user ID or or direct self-signature has expired
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
// Iterate the keys to find the newest, unexpired one
candidateSubkey := -1
var maxTime time.Time
for i, subkey := range e.Subkeys {
if subkey.Sig.FlagsValid &&
subkey.Sig.FlagEncryptCommunications &&
subkey.PublicKey.PubKeyAlgo.CanEncrypt() &&
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
!subkey.Sig.SigExpired(now) &&
!subkey.Revoked(now) &&
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) {
candidateSubkey = i
maxTime = subkey.Sig.CreationTime
}
}
if candidateSubkey != -1 {
subkey := e.Subkeys[candidateSubkey]
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
}
// If we don't have any subkeys for encryption and the primary key
// is marked as OK to encrypt with, then we can use it.
if primarySelfSignature.FlagsValid && primarySelfSignature.FlagEncryptCommunications &&
e.PrimaryKey.PubKeyAlgo.CanEncrypt() {
return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
return Key{}, false
}
// CertificationKey return the best candidate Key for certifying a key with this
// Entity.
func (e *Entity) CertificationKey(now time.Time) (Key, bool) {
return e.CertificationKeyById(now, 0)
}
// CertificationKeyById return the Key for key certification with this
// Entity and keyID.
func (e *Entity) CertificationKeyById(now time.Time, id uint64) (Key, bool) {
return e.signingKeyByIdUsage(now, id, packet.KeyFlagCertify)
}
// SigningKey return the best candidate Key for signing a message with this
// Entity.
func (e *Entity) SigningKey(now time.Time) (Key, bool) {
return e.SigningKeyById(now, 0)
}
// SigningKeyById return the Key for signing a message with this
// Entity and keyID.
func (e *Entity) SigningKeyById(now time.Time, id uint64) (Key, bool) {
return e.signingKeyByIdUsage(now, id, packet.KeyFlagSign)
}
func (e *Entity) signingKeyByIdUsage(now time.Time, id uint64, flags int) (Key, bool) {
// Fail to find any signing key if the...
primarySelfSignature, primaryIdentity := e.PrimarySelfSignature()
if primarySelfSignature == nil || // no self-signature found
e.PrimaryKey.KeyExpired(primarySelfSignature, now) || // primary key has expired
e.Revoked(now) || // primary key has been revoked
primarySelfSignature.SigExpired(now) || // user ID or direct self-signature has expired
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // user ID has been revoked (for v4 keys)
return Key{}, false
}
// Iterate the keys to find the newest, unexpired one
candidateSubkey := -1
var maxTime time.Time
for idx, subkey := range e.Subkeys {
if subkey.Sig.FlagsValid &&
(flags&packet.KeyFlagCertify == 0 || subkey.Sig.FlagCertify) &&
(flags&packet.KeyFlagSign == 0 || subkey.Sig.FlagSign) &&
subkey.PublicKey.PubKeyAlgo.CanSign() &&
!subkey.PublicKey.KeyExpired(subkey.Sig, now) &&
!subkey.Sig.SigExpired(now) &&
!subkey.Revoked(now) &&
(maxTime.IsZero() || subkey.Sig.CreationTime.After(maxTime)) &&
(id == 0 || subkey.PublicKey.KeyId == id) {
candidateSubkey = idx
maxTime = subkey.Sig.CreationTime
}
}
if candidateSubkey != -1 {
subkey := e.Subkeys[candidateSubkey]
return Key{e, subkey.PublicKey, subkey.PrivateKey, subkey.Sig, subkey.Revocations}, true
}
// If we don't have any subkeys for signing and the primary key
// is marked as OK to sign with, then we can use it.
if primarySelfSignature.FlagsValid &&
(flags&packet.KeyFlagCertify == 0 || primarySelfSignature.FlagCertify) &&
(flags&packet.KeyFlagSign == 0 || primarySelfSignature.FlagSign) &&
e.PrimaryKey.PubKeyAlgo.CanSign() &&
(id == 0 || e.PrimaryKey.KeyId == id) {
return Key{e, e.PrimaryKey, e.PrivateKey, primarySelfSignature, e.Revocations}, true
}
// No keys with a valid Signing Flag or no keys matched the id passed in
return Key{}, false
}
func revoked(revocations []*packet.Signature, now time.Time) bool {
for _, revocation := range revocations {
if revocation.RevocationReason != nil && *revocation.RevocationReason == packet.KeyCompromised {
// If the key is compromised, the key is considered revoked even before the revocation date.
return true
}
if !revocation.SigExpired(now) {
return true
}
}
return false
}
// Revoked returns whether the entity has any direct key revocation signatures.
// Note that third-party revocation signatures are not supported.
// Note also that Identity and Subkey revocation should be checked separately.
func (e *Entity) Revoked(now time.Time) bool {
return revoked(e.Revocations, now)
}
// EncryptPrivateKeys encrypts all non-encrypted keys in the entity with the same key
// derived from the provided passphrase. Public keys and dummy keys are ignored,
// and don't cause an error to be returned.
func (e *Entity) EncryptPrivateKeys(passphrase []byte, config *packet.Config) error {
var keysToEncrypt []*packet.PrivateKey
// Add entity private key to encrypt.
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && !e.PrivateKey.Encrypted {
keysToEncrypt = append(keysToEncrypt, e.PrivateKey)
}
// Add subkeys to encrypt.
for _, sub := range e.Subkeys {
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && !sub.PrivateKey.Encrypted {
keysToEncrypt = append(keysToEncrypt, sub.PrivateKey)
}
}
return packet.EncryptPrivateKeys(keysToEncrypt, passphrase, config)
}
// DecryptPrivateKeys decrypts all encrypted keys in the entity with the given passphrase.
// Avoids recomputation of similar s2k key derivations. Public keys and dummy keys are ignored,
// and don't cause an error to be returned.
func (e *Entity) DecryptPrivateKeys(passphrase []byte) error {
var keysToDecrypt []*packet.PrivateKey
// Add entity private key to decrypt.
if e.PrivateKey != nil && !e.PrivateKey.Dummy() && e.PrivateKey.Encrypted {
keysToDecrypt = append(keysToDecrypt, e.PrivateKey)
}
// Add subkeys to decrypt.
for _, sub := range e.Subkeys {
if sub.PrivateKey != nil && !sub.PrivateKey.Dummy() && sub.PrivateKey.Encrypted {
keysToDecrypt = append(keysToDecrypt, sub.PrivateKey)
}
}
return packet.DecryptPrivateKeys(keysToDecrypt, passphrase)
}
// Revoked returns whether the identity has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
func (i *Identity) Revoked(now time.Time) bool {
return revoked(i.Revocations, now)
}
// Revoked returns whether the subkey has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
func (s *Subkey) Revoked(now time.Time) bool {
return revoked(s.Revocations, now)
}
// Revoked returns whether the key or subkey has been revoked by a self-signature.
// Note that third-party revocation signatures are not supported.
// Note also that Identity revocation should be checked separately.
// Normally, it's not necessary to call this function, except on keys returned by
// KeysById or KeysByIdUsage.
func (key *Key) Revoked(now time.Time) bool {
return revoked(key.Revocations, now)
}
// An EntityList contains one or more Entities.
type EntityList []*Entity
// KeysById returns the set of keys that have the given key id.
func (el EntityList) KeysById(id uint64) (keys []Key) {
for _, e := range el {
if e.PrimaryKey.KeyId == id {
selfSig, _ := e.PrimarySelfSignature()
keys = append(keys, Key{e, e.PrimaryKey, e.PrivateKey, selfSig, e.Revocations})
}
for _, subKey := range e.Subkeys {
if subKey.PublicKey.KeyId == id {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
}
}
}
return
}
// KeysByIdAndUsage returns the set of keys with the given id that also meet
// the key usage given by requiredUsage. The requiredUsage is expressed as
// the bitwise-OR of packet.KeyFlag* values.
func (el EntityList) KeysByIdUsage(id uint64, requiredUsage byte) (keys []Key) {
for _, key := range el.KeysById(id) {
if requiredUsage != 0 {
if key.SelfSignature == nil || !key.SelfSignature.FlagsValid {
continue
}
var usage byte
if key.SelfSignature.FlagCertify {
usage |= packet.KeyFlagCertify
}
if key.SelfSignature.FlagSign {
usage |= packet.KeyFlagSign
}
if key.SelfSignature.FlagEncryptCommunications {
usage |= packet.KeyFlagEncryptCommunications
}
if key.SelfSignature.FlagEncryptStorage {
usage |= packet.KeyFlagEncryptStorage
}
if usage&requiredUsage != requiredUsage {
continue
}
}
keys = append(keys, key)
}
return
}
// DecryptionKeys returns all private keys that are valid for decryption.
func (el EntityList) DecryptionKeys() (keys []Key) {
for _, e := range el {
for _, subKey := range e.Subkeys {
if subKey.PrivateKey != nil && subKey.Sig.FlagsValid && (subKey.Sig.FlagEncryptStorage || subKey.Sig.FlagEncryptCommunications) {
keys = append(keys, Key{e, subKey.PublicKey, subKey.PrivateKey, subKey.Sig, subKey.Revocations})
}
}
}
return
}
// ReadArmoredKeyRing reads one or more public/private keys from an armor keyring file.
func ReadArmoredKeyRing(r io.Reader) (EntityList, error) {
block, err := armor.Decode(r)
if err == io.EOF {
return nil, errors.InvalidArgumentError("no armored data found")
}
if err != nil {
return nil, err
}
if block.Type != PublicKeyType && block.Type != PrivateKeyType {
return nil, errors.InvalidArgumentError("expected public or private key block, got: " + block.Type)
}
return ReadKeyRing(block.Body)
}
// ReadKeyRing reads one or more public/private keys. Unsupported keys are
// ignored as long as at least a single valid key is found.
func ReadKeyRing(r io.Reader) (el EntityList, err error) {
packets := packet.NewReader(r)
var lastUnsupportedError error
for {
var e *Entity
e, err = ReadEntity(packets)
if err != nil {
// TODO: warn about skipped unsupported/unreadable keys
if _, ok := err.(errors.UnsupportedError); ok {
lastUnsupportedError = err
err = readToNextPublicKey(packets)
} else if _, ok := err.(errors.StructuralError); ok {
// Skip unreadable, badly-formatted keys
lastUnsupportedError = err
err = readToNextPublicKey(packets)
}
if err == io.EOF {
err = nil
break
}
if err != nil {
el = nil
break
}
} else {
el = append(el, e)
}
}
if len(el) == 0 && err == nil {
err = lastUnsupportedError
}
return
}
// readToNextPublicKey reads packets until the start of the entity and leaves
// the first packet of the new entity in the Reader.
func readToNextPublicKey(packets *packet.Reader) (err error) {
var p packet.Packet
for {
p, err = packets.Next()
if err == io.EOF {
return
} else if err != nil {
if _, ok := err.(errors.UnsupportedError); ok {
continue
}
return
}
if pk, ok := p.(*packet.PublicKey); ok && !pk.IsSubkey {
packets.Unread(p)
return
}
}
}
// ReadEntity reads an entity (public key, identities, subkeys etc) from the
// given Reader.
func ReadEntity(packets *packet.Reader) (*Entity, error) {
e := new(Entity)
e.Identities = make(map[string]*Identity)
p, err := packets.Next()
if err != nil {
return nil, err
}
var ok bool
if e.PrimaryKey, ok = p.(*packet.PublicKey); !ok {
if e.PrivateKey, ok = p.(*packet.PrivateKey); !ok {
packets.Unread(p)
return nil, errors.StructuralError("first packet was not a public/private key")
}
e.PrimaryKey = &e.PrivateKey.PublicKey
}
if !e.PrimaryKey.PubKeyAlgo.CanSign() {
return nil, errors.StructuralError("primary key cannot be used for signatures")
}
var revocations []*packet.Signature
var directSignatures []*packet.Signature
EachPacket:
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
switch pkt := p.(type) {
case *packet.UserId:
if err := addUserID(e, packets, pkt); err != nil {
return nil, err
}
case *packet.Signature:
if pkt.SigType == packet.SigTypeKeyRevocation {
revocations = append(revocations, pkt)
} else if pkt.SigType == packet.SigTypeDirectSignature {
directSignatures = append(directSignatures, pkt)
}
// Else, ignoring the signature as it does not follow anything
// we would know to attach it to.
case *packet.PrivateKey:
if !pkt.IsSubkey {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, &pkt.PublicKey, pkt)
if err != nil {
return nil, err
}
case *packet.PublicKey:
if !pkt.IsSubkey {
packets.Unread(p)
break EachPacket
}
err = addSubkey(e, packets, pkt, nil)
if err != nil {
return nil, err
}
default:
// we ignore unknown packets.
}
}
if len(e.Identities) == 0 && e.PrimaryKey.Version < 6 {
return nil, errors.StructuralError(fmt.Sprintf("v%d entity without any identities", e.PrimaryKey.Version))
}
// An implementation MUST ensure that a valid direct-key signature is present before using a v6 key.
if e.PrimaryKey.Version == 6 {
if len(directSignatures) == 0 {
return nil, errors.StructuralError("v6 entity without a valid direct-key signature")
}
// Select main direct key signature.
var mainDirectKeySelfSignature *packet.Signature
for _, directSignature := range directSignatures {
if directSignature.SigType == packet.SigTypeDirectSignature &&
directSignature.CheckKeyIdOrFingerprint(e.PrimaryKey) &&
(mainDirectKeySelfSignature == nil ||
directSignature.CreationTime.After(mainDirectKeySelfSignature.CreationTime)) {
mainDirectKeySelfSignature = directSignature
}
}
if mainDirectKeySelfSignature == nil {
return nil, errors.StructuralError("no valid direct-key self-signature for v6 primary key found")
}
// Check that the main self-signature is valid.
err = e.PrimaryKey.VerifyDirectKeySignature(mainDirectKeySelfSignature)
if err != nil {
return nil, errors.StructuralError("invalid direct-key self-signature for v6 primary key")
}
e.SelfSignature = mainDirectKeySelfSignature
e.Signatures = directSignatures
}
for _, revocation := range revocations {
err = e.PrimaryKey.VerifyRevocationSignature(revocation)
if err == nil {
e.Revocations = append(e.Revocations, revocation)
} else {
// TODO: RFC 4880 5.2.3.15 defines revocation keys.
return nil, errors.StructuralError("revocation signature signed by alternate key")
}
}
return e, nil
}
func addUserID(e *Entity, packets *packet.Reader, pkt *packet.UserId) error {
// Make a new Identity object, that we might wind up throwing away.
// We'll only add it if we get a valid self-signature over this
// userID.
identity := new(Identity)
identity.Name = pkt.Id
identity.UserId = pkt
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return err
}
sig, ok := p.(*packet.Signature)
if !ok {
packets.Unread(p)
break
}
if sig.SigType != packet.SigTypeGenericCert &&
sig.SigType != packet.SigTypePersonaCert &&
sig.SigType != packet.SigTypeCasualCert &&
sig.SigType != packet.SigTypePositiveCert &&
sig.SigType != packet.SigTypeCertificationRevocation {
return errors.StructuralError("user ID signature with wrong type")
}
if sig.CheckKeyIdOrFingerprint(e.PrimaryKey) {
if err = e.PrimaryKey.VerifyUserIdSignature(pkt.Id, e.PrimaryKey, sig); err != nil {
return errors.StructuralError("user ID self-signature invalid: " + err.Error())
}
if sig.SigType == packet.SigTypeCertificationRevocation {
identity.Revocations = append(identity.Revocations, sig)
} else if identity.SelfSignature == nil || sig.CreationTime.After(identity.SelfSignature.CreationTime) {
identity.SelfSignature = sig
}
identity.Signatures = append(identity.Signatures, sig)
e.Identities[pkt.Id] = identity
} else {
identity.Signatures = append(identity.Signatures, sig)
}
}
return nil
}
func addSubkey(e *Entity, packets *packet.Reader, pub *packet.PublicKey, priv *packet.PrivateKey) error {
var subKey Subkey
subKey.PublicKey = pub
subKey.PrivateKey = priv
for {
p, err := packets.Next()
if err == io.EOF {
break
} else if err != nil {
return errors.StructuralError("subkey signature invalid: " + err.Error())
}
sig, ok := p.(*packet.Signature)
if !ok {
packets.Unread(p)
break
}
if sig.SigType != packet.SigTypeSubkeyBinding && sig.SigType != packet.SigTypeSubkeyRevocation {
return errors.StructuralError("subkey signature with wrong type")
}
if err := e.PrimaryKey.VerifyKeySignature(subKey.PublicKey, sig); err != nil {
return errors.StructuralError("subkey signature invalid: " + err.Error())
}
switch sig.SigType {
case packet.SigTypeSubkeyRevocation:
subKey.Revocations = append(subKey.Revocations, sig)
case packet.SigTypeSubkeyBinding:
if subKey.Sig == nil || sig.CreationTime.After(subKey.Sig.CreationTime) {
subKey.Sig = sig
}
}
}
if subKey.Sig == nil {
return errors.StructuralError("subkey packet not followed by signature")
}
e.Subkeys = append(e.Subkeys, subKey)
return nil
}
// SerializePrivate serializes an Entity, including private key material, but
// excluding signatures from other entities, to the given Writer.
// Identities and subkeys are re-signed in case they changed since NewEntry.
// If config is nil, sensible defaults will be used.
func (e *Entity) SerializePrivate(w io.Writer, config *packet.Config) (err error) {
if e.PrivateKey.Dummy() {
return errors.ErrDummyPrivateKey("dummy private key cannot re-sign identities")
}
return e.serializePrivate(w, config, true)
}
// SerializePrivateWithoutSigning serializes an Entity, including private key
// material, but excluding signatures from other entities, to the given Writer.
// Self-signatures of identities and subkeys are not re-signed. This is useful
// when serializing GNU dummy keys, among other things.
// If config is nil, sensible defaults will be used.
func (e *Entity) SerializePrivateWithoutSigning(w io.Writer, config *packet.Config) (err error) {
return e.serializePrivate(w, config, false)
}
func (e *Entity) serializePrivate(w io.Writer, config *packet.Config, reSign bool) (err error) {
if e.PrivateKey == nil {
return goerrors.New("openpgp: private key is missing")
}
err = e.PrivateKey.Serialize(w)
if err != nil {
return
}
for _, revocation := range e.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
for _, directSignature := range e.Signatures {
err := directSignature.Serialize(w)
if err != nil {
return err
}
}
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
return
}
if reSign {
if ident.SelfSignature == nil {
return goerrors.New("openpgp: can't re-sign identity without valid self-signature")
}
err = ident.SelfSignature.SignUserId(ident.UserId.Id, e.PrimaryKey, e.PrivateKey, config)
if err != nil {
return
}
}
for _, sig := range ident.Signatures {
err = sig.Serialize(w)
if err != nil {
return err
}
}
}
for _, subkey := range e.Subkeys {
err = subkey.PrivateKey.Serialize(w)
if err != nil {
return
}
if reSign {
err = subkey.Sig.SignKey(subkey.PublicKey, e.PrivateKey, config)
if err != nil {
return
}
if subkey.Sig.EmbeddedSignature != nil {
err = subkey.Sig.EmbeddedSignature.CrossSignKey(subkey.PublicKey, e.PrimaryKey,
subkey.PrivateKey, config)
if err != nil {
return
}
}
}
for _, revocation := range subkey.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
err = subkey.Sig.Serialize(w)
if err != nil {
return
}
}
return nil
}
// Serialize writes the public part of the given Entity to w, including
// signatures from other entities. No private key material will be output.
func (e *Entity) Serialize(w io.Writer) error {
err := e.PrimaryKey.Serialize(w)
if err != nil {
return err
}
for _, revocation := range e.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
for _, directSignature := range e.Signatures {
err := directSignature.Serialize(w)
if err != nil {
return err
}
}
for _, ident := range e.Identities {
err = ident.UserId.Serialize(w)
if err != nil {
return err
}
for _, sig := range ident.Signatures {
err = sig.Serialize(w)
if err != nil {
return err
}
}
}
for _, subkey := range e.Subkeys {
err = subkey.PublicKey.Serialize(w)
if err != nil {
return err
}
for _, revocation := range subkey.Revocations {
err := revocation.Serialize(w)
if err != nil {
return err
}
}
err = subkey.Sig.Serialize(w)
if err != nil {
return err
}
}
return nil
}
// SignIdentity adds a signature to e, from signer, attesting that identity is
// associated with e. The provided identity must already be an element of
// e.Identities and the private key of signer must have been decrypted if
// necessary.
// If config is nil, sensible defaults will be used.
func (e *Entity) SignIdentity(identity string, signer *Entity, config *packet.Config) error {
certificationKey, ok := signer.CertificationKey(config.Now())
if !ok {
return errors.InvalidArgumentError("no valid certification key found")
}
if certificationKey.PrivateKey.Encrypted {
return errors.InvalidArgumentError("signing Entity's private key must be decrypted")
}
ident, ok := e.Identities[identity]
if !ok {
return errors.InvalidArgumentError("given identity string not found in Entity")
}
sig := createSignaturePacket(certificationKey.PublicKey, packet.SigTypeGenericCert, config)
signingUserID := config.SigningUserId()
if signingUserID != "" {
if _, ok := signer.Identities[signingUserID]; !ok {
return errors.InvalidArgumentError("signer identity string not found in signer Entity")
}
sig.SignerUserId = &signingUserID
}
if err := sig.SignUserId(identity, e.PrimaryKey, certificationKey.PrivateKey, config); err != nil {
return err
}
ident.Signatures = append(ident.Signatures, sig)
return nil
}
// RevokeKey generates a key revocation signature (packet.SigTypeKeyRevocation) with the
// specified reason code and text (RFC4880 section-5.2.3.23).
// If config is nil, sensible defaults will be used.
func (e *Entity) RevokeKey(reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeKeyRevocation, config)
revSig.RevocationReason = &reason
revSig.RevocationReasonText = reasonText
if err := revSig.RevokeKey(e.PrimaryKey, e.PrivateKey, config); err != nil {
return err
}
e.Revocations = append(e.Revocations, revSig)
return nil
}
// RevokeSubkey generates a subkey revocation signature (packet.SigTypeSubkeyRevocation) for
// a subkey with the specified reason code and text (RFC4880 section-5.2.3.23).
// If config is nil, sensible defaults will be used.
func (e *Entity) RevokeSubkey(sk *Subkey, reason packet.ReasonForRevocation, reasonText string, config *packet.Config) error {
if err := e.PrimaryKey.VerifyKeySignature(sk.PublicKey, sk.Sig); err != nil {
return errors.InvalidArgumentError("given subkey is not associated with this key")
}
revSig := createSignaturePacket(e.PrimaryKey, packet.SigTypeSubkeyRevocation, config)
revSig.RevocationReason = &reason
revSig.RevocationReasonText = reasonText
if err := revSig.RevokeSubkey(sk.PublicKey, e.PrivateKey, config); err != nil {
return err
}
sk.Revocations = append(sk.Revocations, revSig)
return nil
}
func (e *Entity) primaryDirectSignature() *packet.Signature {
return e.SelfSignature
}
// PrimarySelfSignature searches the entity for the self-signature that stores key preferences.
// For V4 keys, returns the self-signature of the primary identity, and the identity.
// For V6 keys, returns the latest valid direct-key self-signature, and no identity (nil).
// This self-signature is to be used to check the key expiration,
// algorithm preferences, and so on.
func (e *Entity) PrimarySelfSignature() (*packet.Signature, *Identity) {
if e.PrimaryKey.Version == 6 {
return e.primaryDirectSignature(), nil
}
primaryIdentity := e.PrimaryIdentity()
if primaryIdentity == nil {
return nil, nil
}
return primaryIdentity.SelfSignature, primaryIdentity
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/keys_test_data.go
================================================
package openpgp
const expiringKeyHex = "c6c04d0451d0c680010800abbb021fd03ffc4e96618901180c3fdcb060ee69eeead97b91256d11420d80b5f1b51930248044130bd300605cf8a05b7a40d3d8cfb0a910be2e3db50dcd50a9c54064c2a5550801daa834ff4480b33d3d3ca495ff8a4e84a886977d17d998f881241a874083d8b995beab555b6d22b8a4817ab17ac3e7304f7d4d2c05c495fb2218348d3bc13651db1d92732e368a9dd7dcefa6eddff30b94706a9aaee47e9d39321460b740c59c6fc3c2fd8ab6c0fb868cb87c0051f0321301fe0f0e1820b15e7fb7063395769b525005c7e30a7ce85984f5cac00504e7b4fdc45d74958de8388436fd5c7ba9ea121f1c851b5911dd1b47a14d81a09e92ef37721e2325b6790011010001cd00c2c07b041001080025050251d0c680050900278d00060b09070803020415080a0203160201021901021b03021e01000a0910e7b484133a890a35ae4b0800a1beb82e7f28eaf5273d6af9d3391314f6280b2b624eaca2851f89a9ebcaf80ac589ebd509f168bc4322106ca2e2ce77a76e071a3c7444787d65216b5f05e82c77928860b92aace3b7d0327db59492f422eb9dfab7249266d37429870b091a98aba8724c2259ebf8f85093f21255eafa75aa841e31d94f2ac891b9755fed455e539044ee69fc47950b80e003fc9f298d695660f28329eaa38037c367efde1727458e514faf990d439a21461b719edaddf9296d3d0647b43ca56cb8dbf63b4fcf8b9968e7928c463470fab3b98e44d0d95645062f94b2d04fe56bd52822b71934db8ce845622c40b92fcbe765a142e7f38b61a6aa9606c8e8858dcd3b6eb1894acec04d0451d1f06b01080088bea67444e1789390e7c0335c86775502d58ec783d99c8ef4e06de235ed3dd4b0467f6f358d818c7d8989d43ec6d69fcbc8c32632d5a1b605e3fa8e41d695fcdcaa535936cd0157f9040dce362519803b908eafe838bb13216c885c6f93e9e8d5745607f0d062322085d6bdc760969149a8ff8dd9f5c18d9bfe2e6f63a06e17694cf1f67587c6fb70e9aebf90ffc528ca3b615ac7c9d4a21ea4f7c06f2e98fbbd90a859b8608bf9ea638e3a54289ce44c283110d0c45fa458de6251cd6e7baf71f80f12c8978340490fd90c92b81736ae902ed958e478dceae2835953d189c45d182aff02ea2be61b81d8e94430f041d638647b43e2fcb45fd512fbf5068b810011010001c2c06504180108000f050251d1f06b050900081095021b0c000a0910e7b484133a890a35e63407fe2ec88d6d1e6c9ce7553ece0cb2524747217bad29f251d33df84599ffcc900141a355abd62126800744068a5e05dc167056aa9205273dc7765a2ed49db15c2a83b8d6e6429c902136f1e12229086c1c10c0053242c2a4ae1930db58163387a48cad64607ff2153c320e42843dec28e3fce90e7399d63ac0affa2fee1f0adc0953c89eb3f46ef1d6c04328ed13b491669d5120a3782e3ffb7c69575fb77eebd108794f4dda9d34be2bae57e8e59ec8ebfda2f6f06104b2321be408ea146e2db482b00c5055c8618de36ac9716f80da2617e225556d0fce61b01c8cea2d1e0ea982c31711060ca370f2739366e1e708f38405d784b49d16a26cf62d152eae734327cec04d0451d1f07b010800d5af91c5e7c2fd8951c8d254eab0c97cdcb66822f868b79b78c366255059a68fd74ebca9adb9b970cd9e586690e6e0756705432306878c897b10a4b4ca0005966f99ac8fa4e6f9caf54bf8e53844544beee9872a7ac64c119cf1393d96e674254b661f61ee975633d0e8a8672531edb6bb8e211204e7754a9efa802342118eee850beea742bac95a3f706cc2024cf6037a308bb68162b2f53b9a6346a96e6d31871a2456186e24a1c7a82b82ac04afdfd57cd7fb9ba77a9c760d40b76a170f7be525e5fb6a9848cc726e806187710d9b190387df28700f321f988a392899f93815cc937f309129eb94d5299c5547cb2c085898e6639496e70d746c9d3fb9881d0011010001c2c06504180108000f050251d1f07b050900266305021b0c000a0910e7b484133a890a35bff207fd10dfe8c4a6ea1dd30568012b6fd6891a763c87ad0f7a1d112aad9e8e3239378a3b85588c235865bac2e614348cb4f216d7217f53b3ef48c192e0a4d31d64d7bfa5faccf21155965fa156e887056db644a05ad08a85cc6152d1377d9e37b46f4ff462bbe68ace2dc586ef90070314576c985d8037c2ba63f0a7dc17a62e15bd77e88bc61d9d00858979709f12304264a4cf4225c5cf86f12c8e19486cb9cdcc69f18f027e5f16f4ca8b50e28b3115eaff3a345acd21f624aef81f6ede515c1b55b26b84c1e32264754eab672d5489b287e7277ea855e0a5ff2aa9e8b8c76d579a964ec225255f4d57bf66639ccb34b64798846943e162a41096a7002ca21c7f56"
const subkeyUsageHex = "988d04533a52bc010400d26af43085558f65b9e7dbc90cb9238015259aed5e954637adcfa2181548b2d0b60c65f1f42ec5081cbf1bc0a8aa4900acfb77070837c58f26012fbce297d70afe96e759ad63531f0037538e70dbf8e384569b9720d99d8eb39d8d0a2947233ed242436cb6ac7dfe74123354b3d0119b5c235d3dd9c9d6c004f8ffaf67ad8583001101000188b7041f010200210502533b8552170c8001ce094aa433f7040bb2ddf0be3893cb843d0fe70c020700000a0910a42704b92866382aa98404009d63d916a27543da4221c60087c33f1c44bec9998c5438018ed370cca4962876c748e94b73eb39c58eb698063f3fd6346d58dd2a11c0247934c4a9d71f24754f7468f96fb24c3e791dd2392b62f626148ad724189498cbf993db2df7c0cdc2d677c35da0f16cb16c9ce7c33b4de65a4a91b1d21a130ae9cc26067718910ef8e2b417556d627261203c756d627261407379642e65642e61753e88b80413010200220502533a52bc021b03060b090807030206150802090a0b0416020301021e01021780000a0910a42704b92866382a47840400c0c2bd04f5fca586de408b395b3c280a278259c93eaaa8b79a53b97003f8ed502a8a00446dd9947fb462677e4fcac0dac2f0701847d15130aadb6cd9e0705ea0cf5f92f129136c7be21a718d46c8e641eb7f044f2adae573e11ae423a0a9ca51324f03a8a2f34b91fa40c3cc764bee4dccadedb54c768ba0469b683ea53f1c29b88d04533a52bc01040099c92a5d6f8b744224da27bc2369127c35269b58bec179de6bbc038f749344222f85a31933224f26b70243c4e4b2d242f0c4777eaef7b5502f9dad6d8bf3aaeb471210674b74de2d7078af497d55f5cdad97c7bedfbc1b41e8065a97c9c3d344b21fc81d27723af8e374bc595da26ea242dccb6ae497be26eea57e563ed517e90011010001889f0418010200090502533a52bc021b0c000a0910a42704b92866382afa1403ff70284c2de8a043ff51d8d29772602fa98009b7861c540535f874f2c230af8caf5638151a636b21f8255003997ccd29747fdd06777bb24f9593bd7d98a3e887689bf902f999915fcc94625ae487e5d13e6616f89090ebc4fdc7eb5cad8943e4056995bb61c6af37f8043016876a958ec7ebf39c43d20d53b7f546cfa83e8d2604b88d04533b8283010400c0b529316dbdf58b4c54461e7e669dc11c09eb7f73819f178ccd4177b9182b91d138605fcf1e463262fabefa73f94a52b5e15d1904635541c7ea540f07050ce0fb51b73e6f88644cec86e91107c957a114f69554548a85295d2b70bd0b203992f76eb5d493d86d9eabcaa7ef3fc7db7e458438db3fcdb0ca1cc97c638439a9170011010001889f0418010200090502533b8283021b0c000a0910a42704b92866382adc6d0400cfff6258485a21675adb7a811c3e19ebca18851533f75a7ba317950b9997fda8d1a4c8c76505c08c04b6c2cc31dc704d33da36a21273f2b388a1a706f7c3378b66d887197a525936ed9a69acb57fe7f718133da85ec742001c5d1864e9c6c8ea1b94f1c3759cebfd93b18606066c063a63be86085b7e37bdbc65f9a915bf084bb901a204533b85cd110400aed3d2c52af2b38b5b67904b0ef73d6dd7aef86adb770e2b153cd22489654dcc91730892087bb9856ae2d9f7ed1eb48f214243fe86bfe87b349ebd7c30e630e49c07b21fdabf78b7a95c8b7f969e97e3d33f2e074c63552ba64a2ded7badc05ce0ea2be6d53485f6900c7860c7aa76560376ce963d7271b9b54638a4028b573f00a0d8854bfcdb04986141568046202192263b9b67350400aaa1049dbc7943141ef590a70dcb028d730371d92ea4863de715f7f0f16d168bd3dc266c2450457d46dcbbf0b071547e5fbee7700a820c3750b236335d8d5848adb3c0da010e998908dfd93d961480084f3aea20b247034f8988eccb5546efaa35a92d0451df3aaf1aee5aa36a4c4d462c760ecd9cebcabfbe1412b1f21450f203fd126687cd486496e971a87fd9e1a8a765fe654baa219a6871ab97768596ab05c26c1aeea8f1a2c72395a58dbc12ef9640d2b95784e974a4d2d5a9b17c25fedacfe551bda52602de8f6d2e48443f5dd1a2a2a8e6a5e70ecdb88cd6e766ad9745c7ee91d78cc55c3d06536b49c3fee6c3d0b6ff0fb2bf13a314f57c953b8f4d93bf88e70418010200090502533b85cd021b0200520910a42704b92866382a47200419110200060502533b85cd000a091042ce2c64bc0ba99214b2009e26b26852c8b13b10c35768e40e78fbbb48bd084100a0c79d9ea0844fa5853dd3c85ff3ecae6f2c9dd6c557aa04008bbbc964cd65b9b8299d4ebf31f41cc7264b8cf33a00e82c5af022331fac79efc9563a822497ba012953cefe2629f1242fcdcb911dbb2315985bab060bfd58261ace3c654bdbbe2e8ed27a46e836490145c86dc7bae15c011f7e1ffc33730109b9338cd9f483e7cef3d2f396aab5bd80efb6646d7e778270ee99d934d187dd98"
const revokedKeyHex = "988d045331ce82010400c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be10011010001889f04200102000905025331d0e3021d03000a0910a401d9f09a34f7c042aa040086631196405b7e6af71026b88e98012eab44aa9849f6ef3fa930c7c9f23deaedba9db1538830f8652fb7648ec3fcade8dbcbf9eaf428e83c6cbcc272201bfe2fbb90d41963397a7c0637a1a9d9448ce695d9790db2dc95433ad7be19eb3de72dacf1d6db82c3644c13eae2a3d072b99bb341debba012c5ce4006a7d34a1f4b94b444526567205265766f6b657220283c52656727732022424d204261726973746122204b657920262530305c303e5c29203c72656740626d626172697374612e636f2e61753e88b704130102002205025331ce82021b03060b090807030206150802090a0b0416020301021e01021780000a0910a401d9f09a34f7c0019c03f75edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56889c04100102000605025331cfb5000a0910fe9645554e8266b64b4303fc084075396674fb6f778d302ac07cef6bc0b5d07b66b2004c44aef711cbac79617ef06d836b4957522d8772dd94bf41a2f4ac8b1ee6d70c57503f837445a74765a076d07b829b8111fc2a918423ddb817ead7ca2a613ef0bfb9c6b3562aec6c3cf3c75ef3031d81d95f6563e4cdcc9960bcb386c5d757b104fcca5fe11fc709df884604101102000605025331cfe7000a09107b15a67f0b3ddc0317f6009e360beea58f29c1d963a22b962b80788c3fa6c84e009d148cfde6b351469b8eae91187eff07ad9d08fcaab88d045331ce820104009f25e20a42b904f3fa555530fe5c46737cf7bd076c35a2a0d22b11f7e0b61a69320b768f4a80fe13980ce380d1cfc4a0cd8fbe2d2e2ef85416668b77208baa65bf973fe8e500e78cc310d7c8705cdb34328bf80e24f0385fce5845c33bc7943cf6b11b02348a23da0bf6428e57c05135f2dc6bd7c1ce325d666d5a5fd2fd5e410011010001889f04180102000905025331ce82021b0c000a0910a401d9f09a34f7c0418003fe34feafcbeaef348a800a0d908a7a6809cc7304017d820f70f0474d5e23cb17e38b67dc6dca282c6ca00961f4ec9edf2738d0f087b1d81e4871ef08e1798010863afb4eac4c44a376cb343be929c5be66a78cfd4456ae9ec6a99d97f4e1c3ff3583351db2147a65c0acef5c003fb544ab3a2e2dc4d43646f58b811a6c3a369d1f"
const revokedSubkeyHex = "988d04533121f6010400aefc803a3e4bb1a61c86e8a86d2726c6a43e0079e9f2713f1fa017e9854c83877f4aced8e331d675c67ea83ddab80aacbfa0b9040bb12d96f5a3d6be09455e2a76546cbd21677537db941cab710216b6d24ec277ee0bd65b910f416737ed120f6b93a9d3b306245c8cfd8394606fdb462e5cf43c551438d2864506c63367fc890011010001b41d416c696365203c616c69636540626d626172697374612e636f2e61753e88bb041301020025021b03060b090807030206150802090a0b0416020301021e01021780050253312798021901000a09104ef7e4beccde97f015a803ff5448437780f63263b0df8442a995e7f76c221351a51edd06f2063d8166cf3157aada4923dfc44aa0f2a6a4da5cf83b7fe722ba8ab416c976e77c6b5682e7f1069026673bd0de56ba06fd5d7a9f177607f277d9b55ff940a638c3e68525c67517e2b3d976899b93ca267f705b3e5efad7d61220e96b618a4497eab8d04403d23f8846041011020006050253312910000a09107b15a67f0b3ddc03d96e009f50b6365d86c4be5d5e9d0ea42d5e56f5794c617700a0ab274e19c2827780016d23417ce89e0a2c0d987d889c04100102000605025331cf7a000a0910a401d9f09a34f7c0ee970400aca292f213041c9f3b3fc49148cbda9d84afee6183c8dd6c5ff2600b29482db5fecd4303797be1ee6d544a20a858080fec43412061c9a71fae4039fd58013b4ae341273e6c66ad4c7cdd9e68245bedb260562e7b166f2461a1032f2b38c0e0e5715fb3d1656979e052b55ca827a76f872b78a9fdae64bc298170bfcebedc1271b41a416c696365203c616c696365407379646973702e6f722e61753e88b804130102002205025331278b021b03060b090807030206150802090a0b0416020301021e01021780000a09104ef7e4beccde97f06a7003fa03c3af68d272ebc1fa08aa72a03b02189c26496a2833d90450801c4e42c5b5f51ad96ce2d2c9cef4b7c02a6a2fcf1412d6a2d486098eb762f5010a201819c17fd2888aec8eda20c65a3b75744de7ee5cc8ac7bfc470cbe3cb982720405a27a3c6a8c229cfe36905f881b02ed5680f6a8f05866efb9d6c5844897e631deb949ca8846041011020006050253312910000a09107b15a67f0b3ddc0347bc009f7fa35db59147469eb6f2c5aaf6428accb138b22800a0caa2f5f0874bacc5909c652a57a31beda65eddd5889c04100102000605025331cf7a000a0910a401d9f09a34f7c0316403ff46f2a5c101256627f16384d34a38fb47a6c88ba60506843e532d91614339fccae5f884a5741e7582ffaf292ba38ee10a270a05f139bde3814b6a077e8cd2db0f105ebea2a83af70d385f13b507fac2ad93ff79d84950328bb86f3074745a8b7f9b64990fb142e2a12976e27e8d09a28dc5621f957ac49091116da410ac3cbde1b88d04533121f6010400cbd785b56905e4192e2fb62a720727d43c4fa487821203cf72138b884b78b701093243e1d8c92a0248a6c0203a5a88693da34af357499abacaf4b3309c640797d03093870a323b4b6f37865f6eaa2838148a67df4735d43a90ca87942554cdf1c4a751b1e75f9fd4ce4e97e278d6c1c7ed59d33441df7d084f3f02beb68896c70011010001889f0418010200090502533121f6021b0c000a09104ef7e4beccde97f0b98b03fc0a5ccf6a372995835a2f5da33b282a7d612c0ab2a97f59cf9fff73e9110981aac2858c41399afa29624a7fd8a0add11654e3d882c0fd199e161bdad65e5e2548f7b68a437ea64293db1246e3011cbb94dc1bcdeaf0f2539bd88ff16d95547144d97cead6a8c5927660a91e6db0d16eb36b7b49a3525b54d1644e65599b032b7eb901a204533127a0110400bd3edaa09eff9809c4edc2c2a0ebe52e53c50a19c1e49ab78e6167bf61473bb08f2050d78a5cbbc6ed66aff7b42cd503f16b4a0b99fa1609681fca9b7ce2bbb1a5b3864d6cdda4d7ef7849d156d534dea30fb0efb9e4cf8959a2b2ce623905882d5430b995a15c3b9fe92906086788b891002924f94abe139b42cbbfaaabe42f00a0b65dc1a1ad27d798adbcb5b5ad02d2688c89477b03ff4eebb6f7b15a73b96a96bed201c0e5e4ea27e4c6e2dd1005b94d4b90137a5b1cf5e01c6226c070c4cc999938101578877ee76d296b9aab8246d57049caacf489e80a3f40589cade790a020b1ac146d6f7a6241184b8c7fcde680eae3188f5dcbe846d7f7bdad34f6fcfca08413e19c1d5df83fc7c7c627d493492e009c2f52a80400a2fe82de87136fd2e8845888c4431b032ba29d9a29a804277e31002a8201fb8591a3e55c7a0d0881496caf8b9fb07544a5a4879291d0dc026a0ea9e5bd88eb4aa4947bbd694b25012e208a250d65ddc6f1eea59d3aed3b4ec15fcab85e2afaa23a40ab1ef9ce3e11e1bc1c34a0e758e7aa64deb8739276df0af7d4121f834a9b88e70418010200090502533127a0021b02005209104ef7e4beccde97f047200419110200060502533127a0000a0910dbce4ee19529437fe045009c0b32f5ead48ee8a7e98fac0dea3d3e6c0e2c552500a0ad71fadc5007cfaf842d9b7db3335a8cdad15d3d1a6404009b08e2c68fe8f3b45c1bb72a4b3278cdf3012aa0f229883ad74aa1f6000bb90b18301b2f85372ca5d6b9bf478d235b733b1b197d19ccca48e9daf8e890cb64546b4ce1b178faccfff07003c172a2d4f5ebaba9f57153955f3f61a9b80a4f5cb959908f8b211b03b7026a8a82fc612bfedd3794969bcf458c4ce92be215a1176ab88d045331d144010400a5063000c5aaf34953c1aa3bfc95045b3aab9882b9a8027fecfe2142dc6b47ba8aca667399990244d513dd0504716908c17d92c65e74219e004f7b83fc125e575dd58efec3ab6dd22e3580106998523dea42ec75bf9aa111734c82df54630bebdff20fe981cfc36c76f865eb1c2fb62c9e85bc3a6e5015a361a2eb1c8431578d0011010001889f04280102000905025331d433021d03000a09104ef7e4beccde97f02e5503ff5e0630d1b65291f4882b6d40a29da4616bb5088717d469fbcc3648b8276de04a04988b1f1b9f3e18f52265c1f8b6c85861691c1a6b8a3a25a1809a0b32ad330aec5667cb4262f4450649184e8113849b05e5ad06a316ea80c001e8e71838190339a6e48bbde30647bcf245134b9a97fa875c1d83a9862cae87ffd7e2c4ce3a1b89013d04180102000905025331d144021b0200a809104ef7e4beccde97f09d2004190102000605025331d144000a0910677815e371c2fd23522203fe22ab62b8e7a151383cea3edd3a12995693911426f8ccf125e1f6426388c0010f88d9ca7da2224aee8d1c12135998640c5e1813d55a93df472faae75bef858457248db41b4505827590aeccf6f9eb646da7f980655dd3050c6897feddddaca90676dee856d66db8923477d251712bb9b3186b4d0114daf7d6b59272b53218dd1da94a03ff64006fcbe71211e5daecd9961fba66cdb6de3f914882c58ba5beddeba7dcb950c1156d7fba18c19ea880dccc800eae335deec34e3b84ac75ffa24864f782f87815cda1c0f634b3dd2fa67cea30811d21723d21d9551fa12ccbcfa62b6d3a15d01307b99925707992556d50065505b090aadb8579083a20fe65bd2a270da9b011"
const missingCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Charset: UTF-8
mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAJcXQeP+NmuciE99YcJoffxv
2gVLU4ZXBNHEaP0mgaJ1+tmMD089vUQAcyGRvw8jfsNsVZQIOAuRxY94aHQhIRHR
bUzBN28ofo/AJJtfx62C15xt6fDKRV6HXYqAiygrHIpEoRLyiN69iScUsjIJeyFL
C8wa72e8pSL6dkHoaV1N9ZH/xmrJ+k0vsgkQaAh9CzYufncDxcwkoP+aOlGtX1gP
WwWoIbz0JwLEMPHBWvDDXQcQPQTYQyj+LGC9U6f9VZHN25E94subM1MjuT9OhN9Y
MLfWaaIc5WyhLFyQKW2Upofn9wSFi8ubyBnv640Dfd0rVmaWv7LNTZpoZ/GbJAMA
EQEAAYkBHwQYAQIACQUCU5ygeQIbAgAKCRDt1A0FCB6SP0zCB/sEzaVR38vpx+OQ
MMynCBJrakiqDmUZv9xtplY7zsHSQjpd6xGflbU2n+iX99Q+nav0ETQZifNUEd4N
1ljDGQejcTyKD6Pkg6wBL3x9/RJye7Zszazm4+toJXZ8xJ3800+BtaPoI39akYJm
+ijzbskvN0v/j5GOFJwQO0pPRAFtdHqRs9Kf4YanxhedB4dIUblzlIJuKsxFit6N
lgGRblagG3Vv2eBszbxzPbJjHCgVLR3RmrVezKOsZjr/2i7X+xLWIR0uD3IN1qOW
CXQxLBizEEmSNVNxsp7KPGTLnqO3bPtqFirxS9PJLIMPTPLNBY7ZYuPNTMqVIUWF
4artDmrG
=7FfJ
-----END PGP PUBLIC KEY BLOCK-----`
const invalidCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFMYynYBCACVOZ3/e8Bm2b9KH9QyIlHGo/i1bnkpqsgXj8tpJ2MIUOnXMMAY
ztW7kKFLCmgVdLIC0vSoLA4yhaLcMojznh/2CcUglZeb6Ao8Gtelr//Rd5DRfPpG
zqcfUo+m+eO1co2Orabw0tZDfGpg5p3AYl0hmxhUyYSc/xUq93xL1UJzBFgYXY54
QsM8dgeQgFseSk/YvdP5SMx1ev+eraUyiiUtWzWrWC1TdyRa5p4UZg6Rkoppf+WJ
QrW6BWrhAtqATHc8ozV7uJjeONjUEq24roRc/OFZdmQQGK6yrzKnnbA6MdHhqpdo
9kWDcXYb7pSE63Lc+OBa5X2GUVvXJLS/3nrtABEBAAG0F2ludmFsaWQtc2lnbmlu
Zy1zdWJrZXlziQEoBBMBAgASBQJTnKB5AhsBAgsHAhUIAh4BAAoJEO3UDQUIHpI/
dN4H/idX4FQ1LIZCnpHS/oxoWQWfpRgdKAEM0qCqjMgiipJeEwSQbqjTCynuh5/R
JlODDz85ABR06aoF4l5ebGLQWFCYifPnJZ/Yf5OYcMGtb7dIbqxWVFL9iLMO/oDL
ioI3dotjPui5e+2hI9pVH1UHB/bZ/GvMGo6Zg0XxLPolKQODMVjpjLAQ0YJ3spew
RAmOGre6tIvbDsMBnm8qREt7a07cBJ6XK7xjxYaZHQBiHVxyEWDa6gyANONx8duW
/fhQ/zDTnyVM/ik6VO0Ty9BhPpcEYLFwh5c1ilFari1ta3e6qKo6ZGa9YMk/REhu
yBHd9nTkI+0CiQUmbckUiVjDKKe5AQ0EUxjKdgEIAIINDqlj7X6jYKc6DjwrOkjQ
UIRWbQQar0LwmNilehmt70g5DCL1SYm9q4LcgJJ2Nhxj0/5qqsYib50OSWMcKeEe
iRXpXzv1ObpcQtI5ithp0gR53YPXBib80t3bUzomQ5UyZqAAHzMp3BKC54/vUrSK
FeRaxDzNLrCeyI00+LHNUtwghAqHvdNcsIf8VRumK8oTm3RmDh0TyjASWYbrt9c8
R1Um3zuoACOVy+mEIgIzsfHq0u7dwYwJB5+KeM7ZLx+HGIYdUYzHuUE1sLwVoELh
+SHIGHI1HDicOjzqgajShuIjj5hZTyQySVprrsLKiXS6NEwHAP20+XjayJ/R3tEA
EQEAAYkCPgQYAQIBKAUCU5ygeQIbAsBdIAQZAQIABgUCU5ygeQAKCRCpVlnFZmhO
52RJB/9uD1MSa0wjY6tHOIgquZcP3bHBvHmrHNMw9HR2wRCMO91ZkhrpdS3ZHtgb
u3/55etj0FdvDo1tb8P8FGSVtO5Vcwf5APM8sbbqoi8L951Q3i7qt847lfhu6sMl
w0LWFvPTOLHrliZHItPRjOltS1WAWfr2jUYhsU9ytaDAJmvf9DujxEOsN5G1YJep
54JCKVCkM/y585Zcnn+yxk/XwqoNQ0/iJUT9qRrZWvoeasxhl1PQcwihCwss44A+
YXaAt3hbk+6LEQuZoYS73yR3WHj+42tfm7YxRGeubXfgCEz/brETEWXMh4pe0vCL
bfWrmfSPq2rDegYcAybxRQz0lF8PAAoJEO3UDQUIHpI/exkH/0vQfdHA8g/N4T6E
i6b1CUVBAkvtdJpCATZjWPhXmShOw62gkDw306vHPilL4SCvEEi4KzG72zkp6VsB
DSRcpxCwT4mHue+duiy53/aRMtSJ+vDfiV1Vhq+3sWAck/yUtfDU9/u4eFaiNok1
8/Gd7reyuZt5CiJnpdPpjCwelK21l2w7sHAnJF55ITXdOxI8oG3BRKufz0z5lyDY
s2tXYmhhQIggdgelN8LbcMhWs/PBbtUr6uZlNJG2lW1yscD4aI529VjwJlCeo745
U7pO4eF05VViUJ2mmfoivL3tkhoTUWhx8xs8xCUcCg8DoEoSIhxtOmoTPR22Z9BL
6LCg2mg=
=Dhm4
-----END PGP PUBLIC KEY BLOCK-----`
const goodCrossSignatureKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1
mI0EVUqeVwEEAMufHRrMPWK3gyvi0O0tABCs/oON9zV9KDZlr1a1M91ShCSFwCPo
7r80PxdWVWcj0V5h50/CJYtpN3eE/mUIgW2z1uDYQF1OzrQ8ubrksfsJvpAhENom
lTQEppv9mV8qhcM278teb7TX0pgrUHLYF5CfPdp1L957JLLXoQR/lwLVABEBAAG0
E2dvb2Qtc2lnbmluZy1zdWJrZXmIuAQTAQIAIgUCVUqeVwIbAwYLCQgHAwIGFQgC
CQoLBBYCAwECHgECF4AACgkQNRjL95IRWP69XQQAlH6+eyXJN4DZTLX78KGjHrsw
6FCvxxClEPtPUjcJy/1KCRQmtLAt9PbbA78dvgzjDeZMZqRAwdjyJhjyg/fkU2OH
7wq4ktjUu+dLcOBb+BFMEY+YjKZhf6EJuVfxoTVr5f82XNPbYHfTho9/OABKH6kv
X70PaKZhbwnwij8Nts65AaIEVUqftREEAJ3WxZfqAX0bTDbQPf2CMT2IVMGDfhK7
GyubOZgDFFjwUJQvHNvsrbeGLZ0xOBumLINyPO1amIfTgJNm1iiWFWfmnHReGcDl
y5mpYG60Mb79Whdcer7CMm3AqYh/dW4g6IB02NwZMKoUHo3PXmFLxMKXnWyJ0clw
R0LI/Qn509yXAKDh1SO20rqrBM+EAP2c5bfI98kyNwQAi3buu94qo3RR1ZbvfxgW
CKXDVm6N99jdZGNK7FbRifXqzJJDLcXZKLnstnC4Sd3uyfyf1uFhmDLIQRryn5m+
LBYHfDBPN3kdm7bsZDDq9GbTHiFZUfm/tChVKXWxkhpAmHhU/tH6GGzNSMXuIWSO
aOz3Rqq0ED4NXyNKjdF9MiwD/i83S0ZBc0LmJYt4Z10jtH2B6tYdqnAK29uQaadx
yZCX2scE09UIm32/w7pV77CKr1Cp/4OzAXS1tmFzQ+bX7DR+Gl8t4wxr57VeEMvl
BGw4Vjh3X8//m3xynxycQU18Q1zJ6PkiMyPw2owZ/nss3hpSRKFJsxMLhW3fKmKr
Ey2KiOcEGAECAAkFAlVKn7UCGwIAUgkQNRjL95IRWP5HIAQZEQIABgUCVUqftQAK
CRD98VjDN10SqkWrAKDTpEY8D8HC02E/KVC5YUI01B30wgCgurpILm20kXEDCeHp
C5pygfXw1DJrhAP+NyPJ4um/bU1I+rXaHHJYroYJs8YSweiNcwiHDQn0Engh/mVZ
SqLHvbKh2dL/RXymC3+rjPvQf5cup9bPxNMa6WagdYBNAfzWGtkVISeaQW+cTEp/
MtgVijRGXR/lGLGETPg2X3Afwn9N9bLMBkBprKgbBqU7lpaoPupxT61bL70=
=vtbN
-----END PGP PUBLIC KEY BLOCK-----`
const revokedUserIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBFsgO5EBCADhREPmcjsPkXe1z7ctvyWL0S7oa9JaoGZ9oPDHFDlQxd0qlX2e
DZJZDg0qYvVixmaULIulApq1puEsaJCn3lHUbHlb4PYKwLEywYXM28JN91KtLsz/
uaEX2KC5WqeP40utmzkNLq+oRX/xnRMgwbO7yUNVG2UlEa6eI+xOXO3YtLdmJMBW
ClQ066ZnOIzEo1JxnIwha1CDBMWLLfOLrg6l8InUqaXbtEBbnaIYO6fXVXELUjkx
nmk7t/QOk0tXCy8muH9UDqJkwDUESY2l79XwBAcx9riX8vY7vwC34pm22fAUVLCJ
x1SJx0J8bkeNp38jKM2Zd9SUQqSbfBopQ4pPABEBAAG0I0dvbGFuZyBHb3BoZXIg
PG5vLXJlcGx5QGdvbGFuZy5jb20+iQFUBBMBCgA+FiEE5Ik5JLcNx6l6rZfw1oFy
9I6cUoMFAlsgO5ECGwMFCQPCZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQ
1oFy9I6cUoMIkwf8DNPeD23i4jRwd/pylbvxwZintZl1fSwTJW1xcOa1emXaEtX2
depuqhP04fjlRQGfsYAQh7X9jOJxAHjTmhqFBi5sD7QvKU00cPFYbJ/JTx0B41bl
aXnSbGhRPh63QtEZL7ACAs+shwvvojJqysx7kyVRu0EW2wqjXdHwR/SJO6nhNBa2
DXzSiOU/SUA42mmG+5kjF8Aabq9wPwT9wjraHShEweNerNMmOqJExBOy3yFeyDpa
XwEZFzBfOKoxFNkIaVf5GSdIUGhFECkGvBMB935khftmgR8APxdU4BE7XrXexFJU
8RCuPXonm4WQOwTWR0vQg64pb2WKAzZ8HhwTGbQiR29sYW5nIEdvcGhlciA8cmV2
b2tlZEBnb2xhbmcuY29tPokBNgQwAQoAIBYhBOSJOSS3Dcepeq2X8NaBcvSOnFKD
BQJbIDv3Ah0AAAoJENaBcvSOnFKDfWMIAKhI/Tvu3h8fSUxp/gSAcduT6bC1JttG
0lYQ5ilKB/58lBUA5CO3ZrKDKlzW3M8VEcvohVaqeTMKeoQd5rCZq8KxHn/KvN6N
s85REfXfniCKfAbnGgVXX3kDmZ1g63pkxrFu0fDZjVDXC6vy+I0sGyI/Inro0Pzb
tvn0QCsxjapKK15BtmSrpgHgzVqVg0cUp8vqZeKFxarYbYB2idtGRci4b9tObOK0
BSTVFy26+I/mrFGaPrySYiy2Kz5NMEcRhjmTxJ8jSwEr2O2sUR0yjbgUAXbTxDVE
/jg5fQZ1ACvBRQnB7LvMHcInbzjyeTM3FazkkSYQD6b97+dkWwb1iWG5AQ0EWyA7
kQEIALkg04REDZo1JgdYV4x8HJKFS4xAYWbIva1ZPqvDNmZRUbQZR2+gpJGEwn7z
VofGvnOYiGW56AS5j31SFf5kro1+1bZQ5iOONBng08OOo58/l1hRseIIVGB5TGSa
PCdChKKHreJI6hS3mShxH6hdfFtiZuB45rwoaArMMsYcjaezLwKeLc396cpUwwcZ
snLUNd1Xu5EWEF2OdFkZ2a1qYdxBvAYdQf4+1Nr+NRIx1u1NS9c8jp3PuMOkrQEi
bNtc1v6v0Jy52mKLG4y7mC/erIkvkQBYJdxPaP7LZVaPYc3/xskcyijrJ/5ufoD8
K71/ShtsZUXSQn9jlRaYR0EbojMAEQEAAYkBPAQYAQoAJhYhBOSJOSS3Dcepeq2X
8NaBcvSOnFKDBQJbIDuRAhsMBQkDwmcAAAoJENaBcvSOnFKDkFMIAIt64bVZ8x7+
TitH1bR4pgcNkaKmgKoZz6FXu80+SnbuEt2NnDyf1cLOSimSTILpwLIuv9Uft5Pb
OraQbYt3xi9yrqdKqGLv80bxqK0NuryNkvh9yyx5WoG1iKqMj9/FjGghuPrRaT4l
QinNAghGVkEy1+aXGFrG2DsOC1FFI51CC2WVTzZ5RwR2GpiNRfESsU1rZAUqf/2V
yJl9bD5R4SUNy8oQmhOxi+gbhD4Ao34e4W0ilibslI/uawvCiOwlu5NGd8zv5n+U
heiQvzkApQup5c+BhH5zFDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB
7qTZOahrETw=
=IKnw
-----END PGP PUBLIC KEY BLOCK-----`
const keyWithFirstUserIDRevoked = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: OpenPGP.js v4.10.10
Comment: https://openpgpjs.org
xsBNBFsgO5EBCADhREPmcjsPkXe1z7ctvyWL0S7oa9JaoGZ9oPDHFDlQxd0q
lX2eDZJZDg0qYvVixmaULIulApq1puEsaJCn3lHUbHlb4PYKwLEywYXM28JN
91KtLsz/uaEX2KC5WqeP40utmzkNLq+oRX/xnRMgwbO7yUNVG2UlEa6eI+xO
XO3YtLdmJMBWClQ066ZnOIzEo1JxnIwha1CDBMWLLfOLrg6l8InUqaXbtEBb
naIYO6fXVXELUjkxnmk7t/QOk0tXCy8muH9UDqJkwDUESY2l79XwBAcx9riX
8vY7vwC34pm22fAUVLCJx1SJx0J8bkeNp38jKM2Zd9SUQqSbfBopQ4pPABEB
AAHNIkdvbGFuZyBHb3BoZXIgPHJldm9rZWRAZ29sYW5nLmNvbT7CwI0EMAEK
ACAWIQTkiTkktw3HqXqtl/DWgXL0jpxSgwUCWyA79wIdAAAhCRDWgXL0jpxS
gxYhBOSJOSS3Dcepeq2X8NaBcvSOnFKDfWMIAKhI/Tvu3h8fSUxp/gSAcduT
6bC1JttG0lYQ5ilKB/58lBUA5CO3ZrKDKlzW3M8VEcvohVaqeTMKeoQd5rCZ
q8KxHn/KvN6Ns85REfXfniCKfAbnGgVXX3kDmZ1g63pkxrFu0fDZjVDXC6vy
+I0sGyI/Inro0Pzbtvn0QCsxjapKK15BtmSrpgHgzVqVg0cUp8vqZeKFxarY
bYB2idtGRci4b9tObOK0BSTVFy26+I/mrFGaPrySYiy2Kz5NMEcRhjmTxJ8j
SwEr2O2sUR0yjbgUAXbTxDVE/jg5fQZ1ACvBRQnB7LvMHcInbzjyeTM3Fazk
kSYQD6b97+dkWwb1iWHNI0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFu
Zy5jb20+wsCrBBMBCgA+FiEE5Ik5JLcNx6l6rZfw1oFy9I6cUoMFAlsgO5EC
GwMFCQPCZwAFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AAIQkQ1oFy9I6cUoMW
IQTkiTkktw3HqXqtl/DWgXL0jpxSgwiTB/wM094PbeLiNHB3+nKVu/HBmKe1
mXV9LBMlbXFw5rV6ZdoS1fZ16m6qE/Th+OVFAZ+xgBCHtf2M4nEAeNOaGoUG
LmwPtC8pTTRw8Vhsn8lPHQHjVuVpedJsaFE+HrdC0RkvsAICz6yHC++iMmrK
zHuTJVG7QRbbCqNd0fBH9Ik7qeE0FrYNfNKI5T9JQDjaaYb7mSMXwBpur3A/
BP3COtodKETB416s0yY6okTEE7LfIV7IOlpfARkXMF84qjEU2QhpV/kZJ0hQ
aEUQKQa8EwH3fmSF+2aBHwA/F1TgETtetd7EUlTxEK49eiebhZA7BNZHS9CD
rilvZYoDNnweHBMZzsBNBFsgO5EBCAC5INOERA2aNSYHWFeMfByShUuMQGFm
yL2tWT6rwzZmUVG0GUdvoKSRhMJ+81aHxr5zmIhluegEuY99UhX+ZK6NftW2
UOYjjjQZ4NPDjqOfP5dYUbHiCFRgeUxkmjwnQoSih63iSOoUt5kocR+oXXxb
YmbgeOa8KGgKzDLGHI2nsy8Cni3N/enKVMMHGbJy1DXdV7uRFhBdjnRZGdmt
amHcQbwGHUH+PtTa/jUSMdbtTUvXPI6dz7jDpK0BImzbXNb+r9CcudpiixuM
u5gv3qyJL5EAWCXcT2j+y2VWj2HN/8bJHMoo6yf+bn6A/Cu9f0obbGVF0kJ/
Y5UWmEdBG6IzABEBAAHCwJMEGAEKACYWIQTkiTkktw3HqXqtl/DWgXL0jpxS
gwUCWyA7kQIbDAUJA8JnAAAhCRDWgXL0jpxSgxYhBOSJOSS3Dcepeq2X8NaB
cvSOnFKDkFMIAIt64bVZ8x7+TitH1bR4pgcNkaKmgKoZz6FXu80+SnbuEt2N
nDyf1cLOSimSTILpwLIuv9Uft5PbOraQbYt3xi9yrqdKqGLv80bxqK0NuryN
kvh9yyx5WoG1iKqMj9/FjGghuPrRaT4lQinNAghGVkEy1+aXGFrG2DsOC1FF
I51CC2WVTzZ5RwR2GpiNRfESsU1rZAUqf/2VyJl9bD5R4SUNy8oQmhOxi+gb
hD4Ao34e4W0ilibslI/uawvCiOwlu5NGd8zv5n+UheiQvzkApQup5c+BhH5z
FDFdKJ2CBByxw9+7QjMFI/wgLixKuE0Ob2kAokXf7RlB7qTZOahrETw=
=+2T8
-----END PGP PUBLIC KEY BLOCK-----
`
const keyWithOnlyUserIDRevoked = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEYYwB7RYJKwYBBAHaRw8BAQdARimqhPPzyGAXmfQJjcqM1QVPzLtURJSzNVll
JV4tEaW0KVJldm9rZWQgUHJpbWFyeSBVc2VyIElEIDxyZXZva2VkQGtleS5jb20+
iHgEMBYIACAWIQSpyJZAXYqVEFkjyKutFcS0yeB0LQUCYYwCtgIdAAAKCRCtFcS0
yeB0LbSsAQD8OYMaaBjrdzzpwIkP1stgmPd4/kzN/ZG28Ywl6a5F5QEA5Xg7aq4e
/t6Fsb4F5iqB956kSPe6YJrikobD/tBbMwSIkAQTFggAOBYhBKnIlkBdipUQWSPI
q60VxLTJ4HQtBQJhjAHtAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEK0V
xLTJ4HQtBaoBAPZL7luTCji+Tqhn7XNfFE/0QIahCt8k9wfO1cGlB3inAQDf8Tzw
ZGR5fNluUcNoVxQT7bUSFStbaGo3k0BaOYPbCLg4BGGMAe0SCisGAQQBl1UBBQEB
B0DLwSpveSrbIO/IVZD13yrs1XuB3FURZUnafGrRq7+jUAMBCAeIeAQYFggAIBYh
BKnIlkBdipUQWSPIq60VxLTJ4HQtBQJhjAHtAhsMAAoJEK0VxLTJ4HQtZ1oA/j9u
8+p3xTNzsmabTL6BkNbMeB/RUKCrlm6woM6AV+vxAQCcXTn3JC2sNoNrLoXuVzaA
mcG3/TwG5GSQUUPkrDsGDA==
=mFWy
-----END PGP PUBLIC KEY BLOCK-----
`
const keyWithSubKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mI0EWyKwKQEEALwXhKBnyaaNFeK3ljfc/qn9X/QFw+28EUfgZPHjRmHubuXLE2uR
s3ZoSXY2z7Dkv+NyHYMt8p+X8q5fR7JvUjK2XbPyKoiJVnHINll83yl67DaWfKNL
EjNoO0kIfbXfCkZ7EG6DL+iKtuxniGTcnGT47e+HJSqb/STpLMnWwXjBABEBAAG0
I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQQ/
lRafP/p9PytHbwxMvYJsOQdOOAUCWyKwKQIbAwULCQgHAwUVCgkICwUWAgMBAAIe
AQIXgAAKCRBMvYJsOQdOOOsFBAC62mXww8XuqvYLcVOvHkWLT6mhxrQOJXnlfpn7
2uBV9CMhoG/Ycd43NONsJrB95Apr9TDIqWnVszNbqPCuBhZQSGLdbiDKjxnCWBk0
69qv4RNtkpOhYB7jK4s8F5oQZqId6JasT/PmJTH92mhBYhhTQr0GYFuPX2UJdkw9
Sn9C67iNBFsisDUBBAC3A+Yo9lgCnxi/pfskyLrweYif6kIXWLAtLTsM6g/6jt7b
wTrknuCPyTv0QKGXsAEe/cK/Xq3HvX9WfXPGIHc/X56ZIsHQ+RLowbZV/Lhok1IW
FAuQm8axr/by80cRwFnzhfPc/ukkAq2Qyj4hLsGblu6mxeAhzcp8aqmWOO2H9QAR
AQABiLYEKAEKACAWIQQ/lRafP/p9PytHbwxMvYJsOQdOOAUCWyK16gIdAAAKCRBM
vYJsOQdOOB1vA/4u4uLONsE+2GVOyBsHyy7uTdkuxaR9b54A/cz6jT/tzUbeIzgx
22neWhgvIEghnUZd0vEyK9k1wy5vbDlEo6nKzHso32N1QExGr5upRERAxweDxGOj
7luDwNypI7QcifE64lS/JmlnunwRCdRWMKc0Fp+7jtRc5mpwyHN/Suf5RokBagQY
AQoAIBYhBD+VFp8/+n0/K0dvDEy9gmw5B044BQJbIrA1AhsCAL8JEEy9gmw5B044
tCAEGQEKAB0WIQSNdnkaWY6t62iX336UXbGvYdhXJwUCWyKwNQAKCRCUXbGvYdhX
JxJSA/9fCPHP6sUtGF1o3G1a3yvOUDGr1JWcct9U+QpbCt1mZoNopCNDDQAJvDWl
mvDgHfuogmgNJRjOMznvahbF+wpTXmB7LS0SK412gJzl1fFIpK4bgnhu0TwxNsO1
8UkCZWqxRMgcNUn9z6XWONK8dgt5JNvHSHrwF4CxxwjL23AAtK+FA/UUoi3U4kbC
0XnSr1Sl+mrzQi1+H7xyMe7zjqe+gGANtskqexHzwWPUJCPZ5qpIa2l8ghiUim6b
4ymJ+N8/T8Yva1FaPEqfMzzqJr8McYFm0URioXJPvOAlRxdHPteZ0qUopt/Jawxl
Xt6B9h1YpeLoJwjwsvbi98UTRs0jXwoY
=3fWu
-----END PGP PUBLIC KEY BLOCK-----`
const keyWithSubKeyAndBadSelfSigOrder = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mI0EWyLLDQEEAOqIOpJ/ha1OYAGduu9tS3rBz5vyjbNgJO4sFveEM0mgsHQ0X9/L
plonW+d0gRoO1dhJ8QICjDAc6+cna1DE3tEb5m6JtQ30teLZuqrR398Cf6w7NNVz
r3lrlmnH9JaKRuXl7tZciwyovneBfZVCdtsRZjaLI1uMQCz/BToiYe3DABEBAAG0
I0dvbGFuZyBHb3BoZXIgPG5vLXJlcGx5QGdvbGFuZy5jb20+iM4EEwEKADgWIQRZ
sixZOfQcZdW0wUqmgmdsv1O9xgUCWyLLDQIbAwULCQgHAwUVCgkICwUWAgMBAAIe
AQIXgAAKCRCmgmdsv1O9xql2A/4pix98NxjhdsXtazA9agpAKeADf9tG4Za27Gj+
3DCww/E4iP2X35jZimSm/30QRB6j08uGCqd9vXkkJxtOt63y/IpVOtWX6vMWSTUm
k8xKkaYMP0/IzKNJ1qC/qYEUYpwERBKg9Z+k99E2Ql4kRHdxXUHq6OzY79H18Y+s
GdeM/riNBFsiyxsBBAC54Pxg/8ZWaZX1phGdwfe5mek27SOYpC0AxIDCSOdMeQ6G
HPk38pywl1d+S+KmF/F4Tdi+kWro62O4eG2uc/T8JQuRDUhSjX0Qa51gPzJrUOVT
CFyUkiZ/3ZDhtXkgfuso8ua2ChBgR9Ngr4v43tSqa9y6AK7v0qjxD1x+xMrjXQAR
AQABiQFxBBgBCgAmAhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsizTIFCQAN
MRcAv7QgBBkBCgAdFiEEJcoVUVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62j
UpRPICQq5gQApoWIigZxXFoM0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBS
YnjyA4+n1D+zB2VqliD2QrsX12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZs
nRJmXV+bsvD4sidLZLjdwOVa3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/
U73GGi0D/i20VW8AWYAPACm2zMlzExKTOAV01YTQH/3vW0WLrOse53WcIVZga6es
HuO4So0SOEAvxKMe5HpRIu2dJxTvd99Bo9xk9xJU0AoFrO0vNCRnL+5y68xMlODK
lEw5/kl0jeaTBp6xX0HDQOEVOpPGUwWV4Ij2EnvfNDXaE1vK1kffiQFrBBgBCgAg
AhsCFiEEWbIsWTn0HGXVtMFKpoJnbL9TvcYFAlsi0AYAv7QgBBkBCgAdFiEEJcoV
UVJIk5RWj1c/o62jUpRPICQFAlsiyxsACgkQo62jUpRPICQq5gQApoWIigZxXFoM
0uw4uJBS5JFZtirTANvirZV5RhndwHeMN6JttaBSYnjyA4+n1D+zB2VqliD2QrsX
12KJN6rGOehCtEIClQ1Hodo9nC6kMzzAwW1O8bZsnRJmXV+bsvD4sidLZLjdwOVa
3Cxh6pvq4Uur6a7/UYx121hEY0Qx0s8JEKaCZ2y/U73GRl0EAJokkXmy4zKDHWWi
wvK9gi2gQgRkVnu2AiONxJb5vjeLhM/07BRmH6K1o+w3fOeEQp4FjXj1eQ5fPSM6
Hhwx2CTl9SDnPSBMiKXsEFRkmwQ2AAsQZLmQZvKBkLZYeBiwf+IY621eYDhZfo+G
1dh1WoUCyREZsJQg2YoIpWIcvw+a
=bNRo
-----END PGP PUBLIC KEY BLOCK-----
`
const onlySubkeyNoPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1
lQCVBFggvocBBAC7vBsHn7MKmS6IiiZNTXdciplVgS9cqVd+RTdIAoyNTcsiV1H0
GQ3QtodOPeDlQDNoqinqaobd7R9g3m3hS53Nor7yBZkCWQ5x9v9JxRtoAq0sklh1
I1X2zEqZk2l6YrfBF/64zWrhjnW3j23szkrAIVu0faQXbQ4z56tmZrw11wARAQAB
/gdlAkdOVQG0CUdOVSBEdW1teYi4BBMBAgAiBQJYIL6HAhsDBgsJCAcDAgYVCAIJ
CgsEFgIDAQIeAQIXgAAKCRCd1xxWp1CYAnjGA/9synn6ZXJUKAXQzySgmCZvCIbl
rqBfEpxwLG4Q/lONhm5vthAE0z49I8hj5Gc5e2tLYUtq0o0OCRdCrYHa/efOYWpJ
6RsK99bePOisVzmOABLIgZkcr022kHoMCmkPgv9CUGKP1yqbGl+zzAwQfUjRUmvD
ZIcWLHi2ge4GzPMPi50B2ARYIL6cAQQAxWHnicKejAFcFcF1/3gUSgSH7eiwuBPX
M7vDdgGzlve1o1jbV4tzrjN9jsCl6r0nJPDMfBSzgLr1auNTRG6HpJ4abcOx86ED
Ad+avDcQPZb7z3dPhH/gb2lQejZsHh7bbeOS8WMSzHV3RqCLd8J/xwWPNR5zKn1f
yp4IGfopidMAEQEAAQAD+wQOelnR82+dxyM2IFmZdOB9wSXQeCVOvxSaNMh6Y3lk
UOOkO8Nlic4x0ungQRvjoRs4wBmCuwFK/MII6jKui0B7dn/NDf51i7rGdNGuJXDH
e676By1sEY/NGkc74jr74T+5GWNU64W0vkpfgVmjSAzsUtpmhJMXsc7beBhJdnVl
AgDKCb8hZqj1alcdmLoNvb7ibA3K/V8J462CPD7bMySPBa/uayoFhNxibpoXml2r
oOtHa5izF3b0/9JY97F6rqkdAgD6GdTJ+xmlCoz1Sewoif1I6krq6xoa7gOYpIXo
UL1Afr+LiJeyAnF/M34j/kjIVmPanZJjry0kkjHE5ILjH3uvAf4/6n9np+Th8ujS
YDCIzKwR7639+H+qccOaddCep8Y6KGUMVdD/vTKEx1rMtK+hK/CDkkkxnFslifMJ
kqoqv3WUqCWJAT0EGAECAAkFAlggvpwCGwIAqAkQndccVqdQmAKdIAQZAQIABgUC
WCC+nAAKCRDmGUholQPwvQk+A/9latnSsR5s5/1A9TFki11GzSEnfLbx46FYOdkW
n3YBxZoPQGxNA1vIn8GmouxZInw9CF4jdOJxEdzLlYQJ9YLTLtN5tQEMl/19/bR8
/qLacAZ9IOezYRWxxZsyn6//jfl7A0Y+FV59d4YajKkEfItcIIlgVBSW6T+TNQT3
R+EH5HJ/A/4/AN0CmBhhE2vGzTnVU0VPrE4V64pjn1rufFdclgpixNZCuuqpKpoE
VVHn6mnBf4njKjZrAGPs5kfQ+H4NsM7v3Zz4yV6deu9FZc4O6E+V1WJ38rO8eBix
7G2jko106CC6vtxsCPVIzY7aaG3H5pjRtomw+pX7SzrQ7FUg2PGumg==
=F/T0
-----END PGP PRIVATE KEY BLOCK-----`
const ecdsaPrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
xaUEX1KsSRMIKoZIzj0DAQcCAwTpYqJsnJiFhKKh+8TulWD+lVmerBFNS+Ii
B+nlG3T0xQQ4Sy5eIjJ0CExIQQzi3EElF/Z2l4F3WC5taFA11NgA/gkDCHSS
PThf1M2K4LN8F1MRcvR+sb7i0nH55ojkwuVB1DE6jqIT9m9i+mX1tzjSAS+6
lPQiweCJvG7xTC7Hs3AzRapf/r1At4TB+v+5G2/CKynNFEJpbGwgPGJpbGxA
aG9tZS5jb20+wncEEBMIAB8FAl9SrEkGCwkHCAMCBBUICgIDFgIBAhkBAhsD
Ah4BAAoJEMpwT3+q3+xqw5UBAMebZN9isEZ1ML+R/jWAAWMwa/knMugrEZ1v
Bl9+ZwM0AQCZdf80/wYY4Nve01qSRFv8OmKswLli3TvDv6FKc4cLz8epBF9S
rEkSCCqGSM49AwEHAgMEAjKnT9b5wY2bf9TpAV3d7OUfPOxKj9c4VzeVzSrH
AtQgo/MuI1cdYVURicV4i76DNjFhQHQFTk7BrC+C2u1yqQMBCAf+CQMIHImA
iYfzQtjgQWSFZYUkCFpbbwhNF0ch+3HNaZkaHCnZRIsWsRnc6FCb6lRQyK9+
Dq59kHlduE5QgY40894jfmP2JdJHU6nBdYrivbEdbMJhBBgTCAAJBQJfUqxJ
AhsMAAoJEMpwT3+q3+xqUI0BAMykhV08kQ4Ip9Qlbss6Jdufv7YrU0Vd5hou
b5TmiPd0APoDBh3qIic+aLLUcAuG3+Gt1P1AbUlmqV61ozn1WfHxfw==
=KLN8
-----END PGP PRIVATE KEY BLOCK-----`
const dsaPrivateKeyWithElGamalSubkey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
lQOBBF9/MLsRCACeaF6BI0jTgDAs86t8/kXPfwlPvR2MCYzB0BCqAdcq1hV/GTYd
oNmJRna/ZJfsI/vf+d8Nv+EYOQkPheFS1MJVBitkAXjQPgm8i1tQWen1FCWZxqGk
/vwZYF4yo8GhZ+Wxi3w09W9Cp9QM/CTmyE1Xe7wpPBGe+oD+me8Zxjyt8JBS4Qx+
gvWbfHxfHnggh4pz7U8QkItlLsBNQEdX4R5+zwRN66g2ZSX/shaa/EkVnihUhD7r
njP9I51ORWucTQD6OvgooaNQZCkQ/Se9TzdakwWKS2XSIFXiY/e2E5ZgKI/pfKDU
iA/KessxddPb7nP/05OIJqg9AoDrD4vmehLzAQD+zsUS3LDU1m9/cG4LMsQbT2VK
Te4HqbGIAle+eu/asQf8DDJMrbZpiJZvADum9j0TJ0oep6VdMbzo9RSDKvlLKT9m
kG63H8oDWnCZm1a+HmGq9YIX+JHWmsLXXsFLeEouLzHO+mZo0X28eji3V2T87hyR
MmUM0wFo4k7jK8uVmkDXv3XwNp2uByWxUKZd7EnWmcEZWqIiexJ7XpCS0Pg3tRaI
zxve0SRe/dxfUPnTk/9KQ9hS6DWroBKquL182zx1Fggh4LIWWE2zq+UYn8BI0E8A
rmIDFJdF8ymFQGRrEy6g79NnkPmkrZWsgMRYY65P6v4zLVmqohJKkpm3/Uxa6QAP
CCoPh/JTOvPeCP2bOJH8z4Z9Py3ouMIjofQW8sXqRgf/RIHbh0KsINHrwwZ4gVIr
MK3RofpaYxw1ztPIWb4cMWoWZHH1Pxh7ggTGSBpAhKXkiWw2Rxat8QF5aA7e962c
bLvVv8dqsPrD/RnVJHag89cbPTzjn7gY9elE8EM8ithV3oQkwHTr4avYlpDZsgNd
hUW3YgRwGo31tdzxoG04AcpV2t+07P8XMPr9hsfWs4rHohXPi38Hseu1Ji+dBoWQ
3+1w/HH3o55s+jy4Ruaz78AIrjbmAJq+6rA2mIcCgrhw3DnzuwQAKeBvSeqn9zfS
ZC812osMBVmkycwelpaIh64WZ0vWL3GvdXDctV2kXM+qVpDTLEny0LuiXxrwCKQL
Ev4HAwK9uQBcreDEEud7pfRb8EYP5lzO2ZA7RaIvje6EWAGBvJGMRT0QQE5SGqc7
Fw5geigBdt+vVyRuNNhg3c2fdn/OBQaYu0J/8AiOogG8EaM8tCFlbGdhbWFsQGRz
YS5jb20gPGVsZ2FtYWxAZHNhLmNvbT6IkAQTEQgAOBYhBI+gnfiHQxB35/Dp0XAQ
aE/rsWC5BQJffzC7AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEHAQaE/r
sWC5A4EA/0GcJmyPtN+Klc7b9sVT3JgKTRnB/URxOJfYJofP0hZLAQCkqyMO+adV
JvbgDH0zaITQWZSSXPqpgMpCA6juTrDsd50CawRffzC7EAgAxFFFSAAEQzWTgKU5
EBtpxxoPzHqcChawTHRxHxjcELXzmUBS5PzfA1HXSPnNqK/x3Ut5ycC3CsW41Fnt
Gm3706Wu9VFbFZVn55F9lPiplUo61n5pqMvOr1gmuQsdXiTa0t5FRa4TZ2VSiHFw
vdAVSPTUsT4ZxJ1rPyFYRtq1n3pQcvdZowd07r0JnzTMjLLMFYCKhwIowoOC4zqJ
iB8enjwOlpaqBATRm9xpVF7SJkroPF6/B1vdhj7E3c1aJyHlo0PYBAg756sSHWHg
UuLyUQ4TA0hcCVenn/L/aSY2LnbdZB1EBhlYjA7dTCgwIqsQhfQmPkjz6g64A7+Y
HbbrLwADBQgAk14QIEQ+J/VHetpQV/jt2pNsFK1kVK7mXK0spTExaC2yj2sXlHjL
Ie3bO5T/KqmIaBEB5db5fA5xK9cZt79qrQHDKsEqUetUeMUWLBx77zBsus3grIgy
bwDZKseRzQ715pwxquxQlScGoDIBKEh08HpwHkq140eIj3w+MAIfndaZaSCNaxaP
Snky7BQmJ7Wc7qrIwoQP6yrnUqyW2yNi81nJYUhxjChqaFSlwzLs/iNGryBKo0ic
BqVIRjikKHBlwBng6WyrltQo/Vt9GG8w+lqaAVXbJRlaBZJUR+2NKi/YhP3qQse3
v8fi4kns0gh5LK+2C01RvdX4T49QSExuIf4HAwLJqYIGwadA2uem5v7/765ZtFWV
oL0iZ0ueTJDby4wTFDpLVzzDi/uVcB0ZRFrGOp7w6OYcNYTtV8n3xmli2Q5Trw0c
wZVzvg+ABKWiv7faBjMczIFF8y6WZKOIeAQYEQgAIBYhBI+gnfiHQxB35/Dp0XAQ
aE/rsWC5BQJffzC7AhsMAAoJEHAQaE/rsWC5ZmIA/jhS4r4lClbvjuPWt0Yqdn7R
fss2SPMYvMrrDh42aE0OAQD8xn4G6CN8UtW9xihXOY6FpxiJ/sMc2VaneeUd34oa
4g==
=XZm8
-----END PGP PRIVATE KEY BLOCK-----`
// https://tests.sequoia-pgp.org/#Certificate_expiration
// P _ U p
const expiringPrimaryUIDKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
vLIwa3T4CyshfT0AEQEAAc0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1w
bGU+wsFcBBMBCgCQBYJhesp/BYkEWQPJBQsJCAcCCRD7/MgqAV5zMEcUAAAAAAAe
ACBzYWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmeEOQlNyTLFkc9I/elp+BpY
495V7KatqtDmsyDr+zDAdwYVCgkICwIEFgIDAQIXgAIbAwIeARYhBNGmbhojsYLJ
mA94jPv8yCoBXnMwAABSCQv/av8hKyynMtXVKFuWOGJw0mR8auDm84WdhMFRZg8t
yTJ1L88+Ny4WUAFeqo2j7DU2yPGrm5rmuvzlEedFYFeOWt+A4adz+oumgRd0nsgG
Lf3QYUWQhLWVlz+H7zubgKqSB2A2RqV65S7mTTVro42nb2Mng6rvGWiqeKG5nrXN
/01p1mIBQGR/KnZSqYLzA2Pw2PiJoSkXT26PDz/kiEMXpjKMR6sicV4bKVlEdUvm
pIImIPBHZq1EsKXEyWtWC41w/pc+FofGE+uSFs2aef1vvEHFkj3BHSK8gRcH3kfR
eFroTET8C2q9V1AOELWm+Ys6PzGzF72URK1MKXlThuL4t4LjvXWGNA78IKW+/RQH
DzK4U0jqSO0mL6qxqVS5Ij6jjL6OTrVEGdtDf5n0vI8tcUTBKtVqYAYk+t2YGT05
ayxALtb7viVKo8f10WEcCuKshn0gdsEFMRZQzJ89uQIY3R3FbsdRCaE6OEaDgKMQ
UTFROyfhthgzRKbRxfcplMUCzsDNBF2lnPIBDADWML9cbGMrp12CtF9b2P6z9TTT
74S8iyBOzaSvdGDQY/sUtZXRg21HWamXnn9sSXvIDEINOQ6A9QxdxoqWdCHrOuW3
ofneYXoG+zeKc4dC86wa1TR2q9vW+RMXSO4uImA+Uzula/6k1DogDf28qhCxMwG/
i/m9g1c/0aApuDyKdQ1PXsHHNlgd/Dn6rrd5y2AObaifV7wIhEJnvqgFXDN2RXGj
LeCOHV4Q2WTYPg/S4k1nMXVDwZXrvIsA0YwIMgIT86Rafp1qKlgPNbiIlC1g9RY/
iFaGN2b4Ir6GDohBQSfZW2+LXoPZuVE/wGlQ01rh827KVZW4lXvqsge+wtnWlszc
selGATyzqOK9LdHPdZGzROZYI2e8c+paLNDdVPL6vdRBUnkCaEkOtl1mr2JpQi5n
TU+gTX4IeInC7E+1a9UDF/Y85ybUz8XV8rUnR76UqVC7KidNepdHbZjjXCt8/Zo+
Tec9JNbYNQB/e9ExmDntmlHEsSEQzFwzj8sxH48AEQEAAcLA9gQYAQoAIBYhBNGm
bhojsYLJmA94jPv8yCoBXnMwBQJdpZzyAhsMAAoJEPv8yCoBXnMw6f8L/26C34dk
jBffTzMj5Bdzm8MtF67OYneJ4TQMw7+41IL4rVcSKhIhk/3Ud5knaRtP2ef1+5F6
6h9/RPQOJ5+tvBwhBAcUWSupKnUrdVaZQanYmtSxcVV2PL9+QEiNN3tzluhaWO//
rACxJ+K/ZXQlIzwQVTpNhfGzAaMVV9zpf3u0k14itcv6alKY8+rLZvO1wIIeRZLm
U0tZDD5HtWDvUV7rIFI1WuoLb+KZgbYn3OWjCPHVdTrdZ2CqnZbG3SXw6awH9bzR
LV9EXkbhIMez0deCVdeo+wFFklh8/5VK2b0vk/+wqMJxfpa1lHvJLobzOP9fvrsw
sr92MA2+k901WeISR7qEzcI0Fdg8AyFAExaEK6VyjP7SXGLwvfisw34OxuZr3qmx
1Sufu4toH3XrB7QJN8XyqqbsGxUCBqWif9RSK4xjzRTe56iPeiSJJOIciMP9i2ld
I+KgLycyeDvGoBj0HCLO3gVaBe4ubVrj5KjhX2PVNEJd3XZRzaXZE2aAMQ==
=AmgT
-----END PGP PUBLIC KEY BLOCK-----`
const rsa2048PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4
lQPGBGL07P0BCADL0etN8efyAXA6sL2WfQvHe5wEKYXPWeN2+jiqSppfeRZAOlzP
kZ3U+cloeJriplYvVJwI3ID2aw52Z/TRn8iKRP5eOUFrEgcgl06lazLtOndK7o7p
oBV5mLtHEirFHm6W61fNt10jzM0jx0PV6nseLhFB2J42F1cmU/aBgFo41wjLSZYr
owR+v+O9S5sUXblQF6sEDcY01sBEu09zrIgT49VFwQ1Cvdh9XZEOTQBfdiugoj5a
DS3fAqAka3r1VoQK4eR7/upnYSgSACGeaQ4pUelKku5rpm50gdWTY8ppq0k9e1eT
y2x0OQcW3hWE+j4os1ca0ZEADMdqr/99MOxrABEBAAH+BwMCJWxU4VOZOJ7/I6vX
FxdfBhIBEXlJ52FM3S/oYtXqLhkGyrtmZOeEazVvUtuCe3M3ScHI8xCthcmE8E0j
bi+ZEHPS2NiBZtgHFF27BLn7zZuTc+oD5WKduZdK3463egnyThTqIIMl25WZBuab
k5ycwYrWwBH0jfA4gwJ13ai4pufKC2RM8qIu6YAVPglYBKFLKGvvJHa5vI+LuA0E
K+k35hIic7yVUcQneNnAF2598X5yWiieYnOZpmHlRw1zfbMwOJr3ZNj2v94u7b+L
sTa/1Uv9887Vb6sJp0c2Sh4cwEccoPYkvMqFn3ZrJUr3UdDu1K2vWohPtswzhrYV
+RdPZE5RLoCQufKvlPezk0Pzhzb3bBU7XjUbdGY1nH/EyQeBNp+Gw6qldKvzcBaB
cyOK1c6hPSszpJX93m5UxCN55IeifmcNjmbDh8vGCCdajy6d56qV2n4F3k7vt1J1
0UlxIGhqijJoaTCX66xjLMC6VXkSz6aHQ35rnXosm/cqPcQshsZTdlfSyWkorfdr
4Hj8viBER26mjYurTMLBKDtUN724ZrR0Ev5jorX9uoKlgl87bDZHty2Ku2S+vR68
VAvnj6Fi1BYNclnDoqxdRB2z5T9JbWE52HuG83/QsplhEqXxESDxriTyTHMbNxEe
88soVCDh4tgflZFa2ucUr6gEKJKij7jgahARnyaXfPZlQBUAS1YUeILYmN+VR+M/
sHENpwDWc7TInn8VN638nJV+ScZGMih3AwWZTIoiLju3MMt1K0YZ3NuiqwGH4Jwg
/BbEdTWeCci9y3NEQHQ3uZZ5p6j2CwFVlK11idemCMvAiTVxF+gKdaLMkeCwKxru
J3YzhKEo+iDVYbPYBYizx/EHBn2U5kITQ5SBXzjTaaFMNZJEf9JYsL1ybPB6HOFY
VNVB2KT8CGVwtCJHb2xhbmcgR29waGVyIDxnb2xhbmdAZXhhbXBsZS5vcmc+iQFO
BBMBCgA4FiEEC6K7U7f4qesybTnqSkra7gHusm0FAmL07P0CGwMFCwkIBwIGFQoJ
CAsCBBYCAwECHgECF4AACgkQSkra7gHusm1MvwgAxpClWkeSqIhMQfbiuz0+lOkE
89y1DCFw8bHjZoUf4/4K8hFA3dGkk+q72XFgiyaCpfXxMt6Gi+dN47t+tTv9NIqC
sukbaoJBmJDhN6+djmJOgOYy+FWsW2LAk2LOwKYulpnBZdcA5rlMAhBg7gevQpF+
ruSU69P7UUaFJl/DC7hDmaIcj+4cjBE/HO26SnVQjoTfjZT82rDh1Wsuf8LnkJUk
b3wezBLpXKjDvdHikdv4gdlR4AputVM38aZntYYglh/EASo5TneyZ7ZscdLNRdcF
r5O2fKqrOJLOdaoYRFZZWOvP5GtEVFDU7WGivOSVfiszBE0wZR3dgZRJipHCXJ0D
xgRi9Oz9AQgAtMJcJqLLVANJHl90tWuoizDkm+Imcwq2ubQAjpclnNrODnDK+7o4
pBsWmXbZSdkC4gY+LhOQA6bPDD0JEHM58DOnrm49BddxXAyK0HPsk4sGGt2SS86B
OawWNdfJVyqw4bAiHWDmQg4PcjBbt3ocOIxAR6I5kBSiQVxuGQs9T+Zvg3G1r3Or
fS6DzlgY3HFUML5YsGH4lOxNSOoKAP68GIH/WNdUZ+feiRg9knIib6I3Hgtf5eO8
JRH7aWE/TD7eNu36bLLjT5TZPq5r6xaD2plbtPOyXbNPWs9qI1yG+VnErfaLY0w8
Qo0aqzbgID+CTZVomXSOpOcQseaFKw8ZfQARAQAB/gcDArha6+/+d4OY/w9N32K9
hFNYt4LufTETMQ+k/sBeaMuAVzmT47DlAXzkrZhGW4dZOtXMu1rXaUwHlqkhEyzL
L4MYEWVXfD+LbZNEK3MEFss6RK+UAMeT/PTV9aA8cXQVPcSJYzfBXHQ1U1hnOgrO
apn92MN8RmkhX8wJLyeWTMMuP4lXByJMmmGo8WvifeRD2kFY4y0WVBDAXJAV4Ljf
Di/bBiwoc5a+gxHuZT2W9ZSxBQJNXdt4Un2IlyZuo58s5MLx2N0EaNJ8PwRUE6fM
RZYO8aZCEPUtINE4njbvsWOMCtrblsMPwZ1B0SiIaWmLaNyGdCNKea+fCIW7kasC
JYMhnLumpUTXg5HNexkCsl7ABWj0PYBflOE61h8EjWpnQ7JBBVKS2ua4lMjwHRX7
5o5yxym9k5UZNFdGoXVL7xpizCcdGawxTJvwhs3vBqu1ZWYCegOAZWDrOkCyhUpq
8uKMROZFbn+FwE+7tjt+v2ed62FVEvD6g4V3ThCA6mQqeOARfJWN8GZY8BDm8lht
crOXriUkrx+FlrgGtm2CkwjW5/9Xd7AhFpHnQdFeozOHyq1asNSgJF9sNi9Lz94W
skQSVRi0IExxSXYGI3Y0nnAZUe2BAQflYPJdEveSr3sKlUqXiETTA1VXsTPK3kOC
92CbLzj/Hz199jZvywwyu53I+GKMpF42rMq7zxr2oa61YWY4YE/GDezwwys/wLx/
QpCW4X3ppI7wJjCSSqEV0baYZSSli1ayheS6dxi8QnSpX1Bmpz6gU7m/M9Sns+hl
J7ZvgpjCAiV7KJTjtclr5/S02zP78LTVkoTWoz/6MOTROwaP63VBUXX8pbJhf/vu
DLmNnDk8joMJxoDXWeNU0EnNl4hP7Z/jExRBOEO4oAnUf/Sf6gCWQhL5qcajtg6w
tGv7vx3f2IkBNgQYAQoAIBYhBAuiu1O3+KnrMm056kpK2u4B7rJtBQJi9Oz9AhsM
AAoJEEpK2u4B7rJt6lgIAMBWqP4BCOGnQXBbgJ0+ACVghpkFUXZTb/tXJc8UUvTM
8uov6k/RsqDGZrvhhufD7Wwt7j9v7dD7VPp7bPyjVWyimglQzWguTUUqLDGlstYH
5uYv1pzma0ZsAGNqFeGlTLsKOSGKFMH4rB2KfN2n51L8POvtp1y7GKZQbWIWneaB
cZr3BINU5GMvYYU7pAYcoR+mJPdJx5Up3Ocn+bn8Tu1sy9C/ArtCQucazGnoE9u1
HhNLrh0CdzzX7TNH6TQ8LwPOvq0K5l/WqbN9lE0WBBhMv2HydxhluO8AhU+A5GqC
C+wET7nVDnhoOm/fstIeb7/LN7OYejKPeHdFBJEL9GA=
=u442
-----END PGP PRIVATE KEY BLOCK-----`
const curve25519PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: gpg (GnuPG) 2.2.27 with libgcrypt 1.9.4
lFgEYvTtQBYJKwYBBAHaRw8BAQdAxsNXLbrk5xOjpO24VhOMvQ0/F+JcyIkckMDH
X3FIGxcAAQDFOlunZWYuPsCx5JLp78vKqUTfgef9TGG4oD6I/Sa0zBMstCJHb2xh
bmcgR29waGVyIDxnb2xhbmdAZXhhbXBsZS5vcmc+iJAEExYIADgWIQSFQHEOazmo
h1ldII4MvfnLQ4JBNwUCYvTtQAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAK
CRAMvfnLQ4JBN5yeAQCKdry8B5ScCPrev2+UByMCss7Sdu5RhomCFsHdNPLcKAEA
8ugei+1owHsV+3cGwWWzKk6sLa8ZN87i3SKuOGp9DQycXQRi9O1AEgorBgEEAZdV
AQUBAQdA5CubPp8l7lrVQ25h7Hx5XN2C8xanRnnpcjzEooCaEA0DAQgHAAD/Rpc+
sOZUXrFk9HOWB1XU41LoWbDBoG8sP8RWAVYwD5AQRYh4BBgWCAAgFiEEhUBxDms5
qIdZXSCODL35y0OCQTcFAmL07UACGwwACgkQDL35y0OCQTcvdwEA7lb5g/YisrEf
iq660uwMGoepLUfvtqKzuQ6heYe83y0BAN65Ffg5HYOJzUEi0kZQRf7OhdtuL2kJ
SRXn8DmCTfEB
=cELM
-----END PGP PRIVATE KEY BLOCK-----`
const curve448PrivateKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: C1DB 65D5 80D7 B922 7254 4B1E A699 9895 FABA CE52
xYUEYV2UmRYDK2VxAc9AFyxgh5xnSbyt50TWl558mw9xdMN+/UBLr5+UMP8IsrvV
MdXuTIE8CyaUQKSotHtH2RkYEXj5nsMAAAHPQIbTMSzjIWug8UFECzAex5FHgAgH
gYF3RK+TS8D24wX8kOu2C/NoVxwGY+p+i0JHaB+7yljriSKAGxs6wsBEBB8WCgCD
BYJhXZSZBYkFpI+9AwsJBwkQppmYlfq6zlJHFAAAAAAAHgAgc2FsdEBub3RhdGlv
bnMuc2VxdW9pYS1wZ3Aub3Jn5wSpIutJ5HncJWk4ruUV8GzQF390rR5+qWEAnAoY
akcDFQoIApsBAh4BFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAALzdA5dA/fsgYg/J
qaQriYKaPUkyHL7EB3BXhV2d1h/gk+qJLvXQuU2WEJ/XSs3GrsBRiiZwvPH4o+7b
mleAxjy5wpS523vqrrBR2YZ5FwIku7WS4litSdn4AtVam/TlLdMNIf41CtFeZKBe
c5R5VNdQy8y7qy8AAADNEUN1cnZlNDQ4IE9wdGlvbiA4wsBHBBMWCgCGBYJhXZSZ
BYkFpI+9AwsJBwkQppmYlfq6zlJHFAAAAAAAHgAgc2FsdEBub3RhdGlvbnMuc2Vx
dW9pYS1wZ3Aub3JnD55UsYMzE6OACP+mgw5zvT+BBgol8/uFQjHg4krjUCMDFQoI
ApkBApsBAh4BFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAAPQJA5dA0Xqwzn/0uwCq
RlsOVCB3f5NOj1exKnlBvRw0xT1VBee1yxvlUt5eIAoCxWoRlWBJob3TTkhm9AEA
8dyhwPmyGfWHzPw5NFG3xsXrZdNXNvit9WMVAPcmsyR7teXuDlJItxRAdJJc/qfJ
YVbBFoaNrhYAAADHhQRhXZSZFgMrZXEBz0BL7THZ9MnCLfSPJ1FMLim9eGkQ3Bfn
M3he5rOwO3t14QI1LjI96OjkeJipMgcFAmEP1Bq/ZHGO7oAAAc9AFnE8iNBaT3OU
EFtxkmWHXtdaYMmGGRdopw9JPXr/UxuunDln5o9dxPxf7q7z26zXrZen+qed/Isa
HsDCwSwEGBYKAWsFgmFdlJkFiQWkj70JEKaZmJX6us5SRxQAAAAAAB4AIHNhbHRA
bm90YXRpb25zLnNlcXVvaWEtcGdwLm9yZxREUizdTcepBzgSMOv2VWQCWbl++3CZ
EbgAWDryvSsyApsCwDGgBBkWCgBvBYJhXZSZCRBKo3SL4S5djkcUAAAAAAAeACBz
YWx0QG5vdGF0aW9ucy5zZXF1b2lhLXBncC5vcmemoGTDjmNQiIzw6HOEddvS0OB7
UZ/P07jM/EVmnYxTlBYhBAxsnkGpx1UCiH6gUUqjdIvhLl2OAAALYQOXQAMB1oKq
OWxSFmvmgCKNcbAAyA3piF5ERIqs4z07oJvqDYrOWt75UsEIH/04gU/vHc4EmfG2
JDLJgOLlyTUPkL/08f0ydGZPofFQBhn8HkuFFjnNtJ5oz3GIP4cdWMQFaUw0uvjb
PM9Tm3ptENGd6Ts1AAAAFiEEwdtl1YDXuSJyVEseppmYlfq6zlIAAGpTA5dATR6i
U2GrpUcQgpG+JqfAsGmF4yAOhgFxc1UfidFk3nTup3fLgjipkYY170WLRNbyKkVO
Sodx93GAs58rizO1acDAWiLq3cyEPBFXbyFThbcNPcLl+/77Uk/mgkYrPQFAQWdK
1kSRm4SizDBK37K8ChAAAADHhwRhXZSZEgMrZW8Bx0DMhzvhQo+OsXeqQ6QVw4sF
CaexHh6rLohh7TzL3hQSjoJ27fV6JBkIWdn0LfrMlJIDbSv2SLdlgQMBCgkAAcdA
MO7Dc1myF6Co1fAH+EuP+OxhxP/7V6ljuSCZENDfA49tQkzTta+PniG+pOVB2LHb
huyaKBkqiaogo8LAOQQYFgoAeAWCYV2UmQWJBaSPvQkQppmYlfq6zlJHFAAAAAAA
HgAgc2FsdEBub3RhdGlvbnMuc2VxdW9pYS1wZ3Aub3JnEjBMQAmc/2u45u5FQGmB
QAytjSG2LM3JQN+PPVl5vEkCmwwWIQTB22XVgNe5InJUSx6mmZiV+rrOUgAASdYD
l0DXEHQ9ykNP2rZP35ET1dmiFagFtTj/hLQcWlg16LqvJNGqOgYXuqTerbiOOt02
XLCBln+wdewpU4ChEffMUDRBfqfQco/YsMqWV7bHJHAO0eC/DMKCjyU90xdH7R/d
QgqsfguR1PqPuJxpXV4bSr6CGAAAAA==
=MSvh
-----END PGP PRIVATE KEY BLOCK-----`
const keyWithNotation = `-----BEGIN PGP PRIVATE KEY BLOCK-----
xVgEY9gIshYJKwYBBAHaRw8BAQdAF25fSM8OpFlXZhop4Qpqo5ywGZ4jgWlR
ppjhIKDthREAAQC+LFpzFcMJYcjxGKzBGHN0Px2jU4d04YSRnFAik+lVVQ6u
zRdUZXN0IDx0ZXN0QGV4YW1wbGUuY29tPsLACgQQFgoAfAUCY9gIsgQLCQcI
CRD/utJOCym8pR0UgAAAAAAQAAR0ZXh0QGV4YW1wbGUuY29tdGVzdB8UAAAA
AAASAARiaW5hcnlAZXhhbXBsZS5jb20AAQIDAxUICgQWAAIBAhkBAhsDAh4B
FiEEEMCQTUVGKgCX5rDQ/7rSTgspvKUAAPl5AP9Npz90LxzrB97Qr2DrGwfG
wuYn4FSYwtuPfZHHeoIabwD/QEbvpQJ/NBb9EAZuow4Rirlt1yv19mmnF+j5
8yUzhQjHXQRj2AiyEgorBgEEAZdVAQUBAQdARXAo30DmKcyUg6co7OUm0RNT
z9iqFbDBzA8A47JEt1MDAQgHAAD/XKK3lBm0SqMR558HLWdBrNG6NqKuqb5X
joCML987ZNgRD8J4BBgWCAAqBQJj2AiyCRD/utJOCym8pQIbDBYhBBDAkE1F
RioAl+aw0P+60k4LKbylAADRxgEAg7UfBDiDPp5LHcW9D+SgFHk6+GyEU4ev
VppQxdtxPvAA/34snHBX7Twnip1nMt7P4e2hDiw/hwQ7oqioOvc6jMkP
=Z8YJ
-----END PGP PRIVATE KEY BLOCK-----
`
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_config.go
================================================
// Copyright (C) 2019 ProtonTech AG
package packet
import "math/bits"
// CipherSuite contains a combination of Cipher and Mode
type CipherSuite struct {
// The cipher function
Cipher CipherFunction
// The AEAD mode of operation.
Mode AEADMode
}
// AEADConfig collects a number of AEAD parameters along with sensible defaults.
// A nil AEADConfig is valid and results in all default values.
type AEADConfig struct {
// The AEAD mode of operation.
DefaultMode AEADMode
// Amount of octets in each chunk of data
ChunkSize uint64
}
// Mode returns the AEAD mode of operation.
func (conf *AEADConfig) Mode() AEADMode {
// If no preference is specified, OCB is used (which is mandatory to implement).
if conf == nil || conf.DefaultMode == 0 {
return AEADModeOCB
}
mode := conf.DefaultMode
if mode != AEADModeEAX && mode != AEADModeOCB && mode != AEADModeGCM {
panic("AEAD mode unsupported")
}
return mode
}
// ChunkSizeByte returns the byte indicating the chunk size. The effective
// chunk size is computed with the formula uint64(1) << (chunkSizeByte + 6)
// limit to 16 = 4 MiB
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func (conf *AEADConfig) ChunkSizeByte() byte {
if conf == nil || conf.ChunkSize == 0 {
return 12 // 1 << (12 + 6) == 262144 bytes
}
chunkSize := conf.ChunkSize
exponent := bits.Len64(chunkSize) - 1
switch {
case exponent < 6:
exponent = 6
case exponent > 16:
exponent = 16
}
return byte(exponent - 6)
}
// decodeAEADChunkSize returns the effective chunk size. In 32-bit systems, the
// maximum returned value is 1 << 30.
func decodeAEADChunkSize(c byte) int {
size := uint64(1 << (c + 6))
if size != uint64(int(size)) {
return 1 << 30
}
return int(size)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_crypter.go
================================================
// Copyright (C) 2019 ProtonTech AG
package packet
import (
"crypto/cipher"
"encoding/binary"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// aeadCrypter is an AEAD opener/sealer, its configuration, and data for en/decryption.
type aeadCrypter struct {
aead cipher.AEAD
chunkSize int
nonce []byte
associatedData []byte // Chunk-independent associated data
chunkIndex []byte // Chunk counter
packetTag packetType // SEIP packet (v2) or AEAD Encrypted Data packet
bytesProcessed int // Amount of plaintext bytes encrypted/decrypted
}
// computeNonce takes the incremental index and computes an eXclusive OR with
// the least significant 8 bytes of the receivers' initial nonce (see sec.
// 5.16.1 and 5.16.2). It returns the resulting nonce.
func (wo *aeadCrypter) computeNextNonce() (nonce []byte) {
if wo.packetTag == packetTypeSymmetricallyEncryptedIntegrityProtected {
return wo.nonce
}
nonce = make([]byte, len(wo.nonce))
copy(nonce, wo.nonce)
offset := len(wo.nonce) - 8
for i := 0; i < 8; i++ {
nonce[i+offset] ^= wo.chunkIndex[i]
}
return
}
// incrementIndex performs an integer increment by 1 of the integer represented by the
// slice, modifying it accordingly.
func (wo *aeadCrypter) incrementIndex() error {
index := wo.chunkIndex
if len(index) == 0 {
return errors.AEADError("Index has length 0")
}
for i := len(index) - 1; i >= 0; i-- {
if index[i] < 255 {
index[i]++
return nil
}
index[i] = 0
}
return errors.AEADError("cannot further increment index")
}
// aeadDecrypter reads and decrypts bytes. It buffers extra decrypted bytes when
// necessary, similar to aeadEncrypter.
type aeadDecrypter struct {
aeadCrypter // Embedded ciphertext opener
reader io.Reader // 'reader' is a partialLengthReader
chunkBytes []byte
peekedBytes []byte // Used to detect last chunk
buffer []byte // Buffered decrypted bytes
}
// Read decrypts bytes and reads them into dst. It decrypts when necessary and
// buffers extra decrypted bytes. It returns the number of bytes copied into dst
// and an error.
func (ar *aeadDecrypter) Read(dst []byte) (n int, err error) {
// Return buffered plaintext bytes from previous calls
if len(ar.buffer) > 0 {
n = copy(dst, ar.buffer)
ar.buffer = ar.buffer[n:]
return
}
// Read a chunk
tagLen := ar.aead.Overhead()
copy(ar.chunkBytes, ar.peekedBytes) // Copy bytes peeked in previous chunk or in initialization
bytesRead, errRead := io.ReadFull(ar.reader, ar.chunkBytes[tagLen:])
if errRead != nil && errRead != io.EOF && errRead != io.ErrUnexpectedEOF {
return 0, errRead
}
if bytesRead > 0 {
ar.peekedBytes = ar.chunkBytes[bytesRead:bytesRead+tagLen]
decrypted, errChunk := ar.openChunk(ar.chunkBytes[:bytesRead])
if errChunk != nil {
return 0, errChunk
}
// Return decrypted bytes, buffering if necessary
n = copy(dst, decrypted)
ar.buffer = decrypted[n:]
return
}
return 0, io.EOF
}
// Close checks the final authentication tag of the stream.
// In the future, this function could also be used to wipe the reader
// and peeked & decrypted bytes, if necessary.
func (ar *aeadDecrypter) Close() (err error) {
errChunk := ar.validateFinalTag(ar.peekedBytes)
if errChunk != nil {
return errChunk
}
return nil
}
// openChunk decrypts and checks integrity of an encrypted chunk, returning
// the underlying plaintext and an error. It accesses peeked bytes from next
// chunk, to identify the last chunk and decrypt/validate accordingly.
func (ar *aeadDecrypter) openChunk(data []byte) ([]byte, error) {
adata := ar.associatedData
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
adata = append(ar.associatedData, ar.chunkIndex...)
}
nonce := ar.computeNextNonce()
plainChunk, err := ar.aead.Open(data[:0:len(data)], nonce, data, adata)
if err != nil {
return nil, errors.ErrAEADTagVerification
}
ar.bytesProcessed += len(plainChunk)
if err = ar.aeadCrypter.incrementIndex(); err != nil {
return nil, err
}
return plainChunk, nil
}
// Checks the summary tag. It takes into account the total decrypted bytes into
// the associated data. It returns an error, or nil if the tag is valid.
func (ar *aeadDecrypter) validateFinalTag(tag []byte) error {
// Associated: tag, version, cipher, aead, chunk size, ...
amountBytes := make([]byte, 8)
binary.BigEndian.PutUint64(amountBytes, uint64(ar.bytesProcessed))
adata := ar.associatedData
if ar.aeadCrypter.packetTag == packetTypeAEADEncrypted {
// ... index ...
adata = append(ar.associatedData, ar.chunkIndex...)
}
// ... and total number of encrypted octets
adata = append(adata, amountBytes...)
nonce := ar.computeNextNonce()
if _, err := ar.aead.Open(nil, nonce, tag, adata); err != nil {
return errors.ErrAEADTagVerification
}
return nil
}
// aeadEncrypter encrypts and writes bytes. It encrypts when necessary according
// to the AEAD block size, and buffers the extra encrypted bytes for next write.
type aeadEncrypter struct {
aeadCrypter // Embedded plaintext sealer
writer io.WriteCloser // 'writer' is a partialLengthWriter
chunkBytes []byte
offset int
}
// Write encrypts and writes bytes. It encrypts when necessary and buffers extra
// plaintext bytes for next call. When the stream is finished, Close() MUST be
// called to append the final tag.
func (aw *aeadEncrypter) Write(plaintextBytes []byte) (n int, err error) {
for n != len(plaintextBytes) {
copied := copy(aw.chunkBytes[aw.offset:aw.chunkSize], plaintextBytes[n:])
n += copied
aw.offset += copied
if aw.offset == aw.chunkSize {
encryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset])
if err != nil {
return n, err
}
_, err = aw.writer.Write(encryptedChunk)
if err != nil {
return n, err
}
aw.offset = 0
}
}
return
}
// Close encrypts and writes the remaining buffered plaintext if any, appends
// the final authentication tag, and closes the embedded writer. This function
// MUST be called at the end of a stream.
func (aw *aeadEncrypter) Close() (err error) {
// Encrypt and write a chunk if there's buffered data left, or if we haven't
// written any chunks yet.
if aw.offset > 0 || aw.bytesProcessed == 0 {
lastEncryptedChunk, err := aw.sealChunk(aw.chunkBytes[:aw.offset])
if err != nil {
return err
}
_, err = aw.writer.Write(lastEncryptedChunk)
if err != nil {
return err
}
}
// Compute final tag (associated data: packet tag, version, cipher, aead,
// chunk size...
adata := aw.associatedData
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
// ... index ...
adata = append(aw.associatedData, aw.chunkIndex...)
}
// ... and total number of encrypted octets
amountBytes := make([]byte, 8)
binary.BigEndian.PutUint64(amountBytes, uint64(aw.bytesProcessed))
adata = append(adata, amountBytes...)
nonce := aw.computeNextNonce()
finalTag := aw.aead.Seal(nil, nonce, nil, adata)
_, err = aw.writer.Write(finalTag)
if err != nil {
return err
}
return aw.writer.Close()
}
// sealChunk Encrypts and authenticates the given chunk.
func (aw *aeadEncrypter) sealChunk(data []byte) ([]byte, error) {
if len(data) > aw.chunkSize {
return nil, errors.AEADError("chunk exceeds maximum length")
}
if aw.associatedData == nil {
return nil, errors.AEADError("can't seal without headers")
}
adata := aw.associatedData
if aw.aeadCrypter.packetTag == packetTypeAEADEncrypted {
adata = append(aw.associatedData, aw.chunkIndex...)
}
nonce := aw.computeNextNonce()
encrypted := aw.aead.Seal(data[:0], nonce, data, adata)
aw.bytesProcessed += len(data)
if err := aw.aeadCrypter.incrementIndex(); err != nil {
return nil, err
}
return encrypted, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/aead_encrypted.go
================================================
// Copyright (C) 2019 ProtonTech AG
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// AEADEncrypted represents an AEAD Encrypted Packet.
// See https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
type AEADEncrypted struct {
cipher CipherFunction
mode AEADMode
chunkSizeByte byte
Contents io.Reader // Encrypted chunks and tags
initialNonce []byte // Referred to as IV in RFC4880-bis
}
// Only currently defined version
const aeadEncryptedVersion = 1
func (ae *AEADEncrypted) parse(buf io.Reader) error {
headerData := make([]byte, 4)
if n, err := io.ReadFull(buf, headerData); n < 4 {
return errors.AEADError("could not read aead header:" + err.Error())
}
// Read initial nonce
mode := AEADMode(headerData[2])
nonceLen := mode.IvLength()
// This packet supports only EAX and OCB
// https://www.ietf.org/archive/id/draft-koch-openpgp-2015-rfc4880bis-00.html#name-aead-encrypted-data-packet-t
if nonceLen == 0 || mode > AEADModeOCB {
return errors.AEADError("unknown mode")
}
initialNonce := make([]byte, nonceLen)
if n, err := io.ReadFull(buf, initialNonce); n < nonceLen {
return errors.AEADError("could not read aead nonce:" + err.Error())
}
ae.Contents = buf
ae.initialNonce = initialNonce
c := headerData[1]
if _, ok := algorithm.CipherById[c]; !ok {
return errors.UnsupportedError("unknown cipher: " + string(c))
}
ae.cipher = CipherFunction(c)
ae.mode = mode
ae.chunkSizeByte = headerData[3]
return nil
}
// Decrypt returns a io.ReadCloser from which decrypted bytes can be read, or
// an error.
func (ae *AEADEncrypted) Decrypt(ciph CipherFunction, key []byte) (io.ReadCloser, error) {
return ae.decrypt(key)
}
// decrypt prepares an aeadCrypter and returns a ReadCloser from which
// decrypted bytes can be read (see aeadDecrypter.Read()).
func (ae *AEADEncrypted) decrypt(key []byte) (io.ReadCloser, error) {
blockCipher := ae.cipher.new(key)
aead := ae.mode.new(blockCipher)
// Carry the first tagLen bytes
chunkSize := decodeAEADChunkSize(ae.chunkSizeByte)
tagLen := ae.mode.TagLength()
chunkBytes := make([]byte, chunkSize+tagLen*2)
peekedBytes := chunkBytes[chunkSize+tagLen:]
n, err := io.ReadFull(ae.Contents, peekedBytes)
if n < tagLen || (err != nil && err != io.EOF) {
return nil, errors.AEADError("Not enough data to decrypt:" + err.Error())
}
return &aeadDecrypter{
aeadCrypter: aeadCrypter{
aead: aead,
chunkSize: chunkSize,
nonce: ae.initialNonce,
associatedData: ae.associatedData(),
chunkIndex: make([]byte, 8),
packetTag: packetTypeAEADEncrypted,
},
reader: ae.Contents,
chunkBytes: chunkBytes,
peekedBytes: peekedBytes,
}, nil
}
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
func (ae *AEADEncrypted) associatedData() []byte {
return []byte{
0xD4,
aeadEncryptedVersion,
byte(ae.cipher),
byte(ae.mode),
ae.chunkSizeByte}
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/compressed.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"compress/bzip2"
"compress/flate"
"compress/zlib"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// Compressed represents a compressed OpenPGP packet. The decompressed contents
// will contain more OpenPGP packets. See RFC 4880, section 5.6.
type Compressed struct {
Body io.Reader
}
const (
NoCompression = flate.NoCompression
BestSpeed = flate.BestSpeed
BestCompression = flate.BestCompression
DefaultCompression = flate.DefaultCompression
)
// CompressionConfig contains compressor configuration settings.
type CompressionConfig struct {
// Level is the compression level to use. It must be set to
// between -1 and 9, with -1 causing the compressor to use the
// default compression level, 0 causing the compressor to use
// no compression and 1 to 9 representing increasing (better,
// slower) compression levels. If Level is less than -1 or
// more then 9, a non-nil error will be returned during
// encryption. See the constants above for convenient common
// settings for Level.
Level int
}
// decompressionReader ensures that the whole compression packet is read.
type decompressionReader struct {
compressed io.Reader
decompressed io.ReadCloser
readAll bool
}
func newDecompressionReader(r io.Reader, decompressor io.ReadCloser) *decompressionReader {
return &decompressionReader{
compressed: r,
decompressed: decompressor,
}
}
func (dr *decompressionReader) Read(data []byte) (n int, err error) {
if dr.readAll {
return 0, io.EOF
}
n, err = dr.decompressed.Read(data)
if err == io.EOF {
dr.readAll = true
// Close the decompressor.
if errDec := dr.decompressed.Close(); errDec != nil {
return n, errDec
}
// Consume all remaining data from the compressed packet.
consumeAll(dr.compressed)
}
return n, err
}
func (c *Compressed) parse(r io.Reader) error {
var buf [1]byte
_, err := readFull(r, buf[:])
if err != nil {
return err
}
switch buf[0] {
case 0:
c.Body = r
case 1:
c.Body = newDecompressionReader(r, flate.NewReader(r))
case 2:
decompressor, err := zlib.NewReader(r)
if err != nil {
return err
}
c.Body = newDecompressionReader(r, decompressor)
case 3:
c.Body = newDecompressionReader(r, io.NopCloser(bzip2.NewReader(r)))
default:
err = errors.UnsupportedError("unknown compression algorithm: " + strconv.Itoa(int(buf[0])))
}
return err
}
// compressedWriterCloser represents the serialized compression stream
// header and the compressor. Its Close() method ensures that both the
// compressor and serialized stream header are closed. Its Write()
// method writes to the compressor.
type compressedWriteCloser struct {
sh io.Closer // Stream Header
c io.WriteCloser // Compressor
}
func (cwc compressedWriteCloser) Write(p []byte) (int, error) {
return cwc.c.Write(p)
}
func (cwc compressedWriteCloser) Close() (err error) {
err = cwc.c.Close()
if err != nil {
return err
}
return cwc.sh.Close()
}
// SerializeCompressed serializes a compressed data packet to w and
// returns a WriteCloser to which the literal data packets themselves
// can be written and which MUST be closed on completion. If cc is
// nil, sensible defaults will be used to configure the compression
// algorithm.
func SerializeCompressed(w io.WriteCloser, algo CompressionAlgo, cc *CompressionConfig) (literaldata io.WriteCloser, err error) {
compressed, err := serializeStreamHeader(w, packetTypeCompressed)
if err != nil {
return
}
_, err = compressed.Write([]byte{uint8(algo)})
if err != nil {
return
}
level := DefaultCompression
if cc != nil {
level = cc.Level
}
var compressor io.WriteCloser
switch algo {
case CompressionZIP:
compressor, err = flate.NewWriter(compressed, level)
case CompressionZLIB:
compressor, err = zlib.NewWriterLevel(compressed, level)
default:
s := strconv.Itoa(int(algo))
err = errors.UnsupportedError("Unsupported compression algorithm: " + s)
}
if err != nil {
return
}
literaldata = compressedWriteCloser{compressed, compressor}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config.go
================================================
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto"
"crypto/rand"
"io"
"math/big"
"time"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
)
var (
defaultRejectPublicKeyAlgorithms = map[PublicKeyAlgorithm]bool{
PubKeyAlgoElGamal: true,
PubKeyAlgoDSA: true,
}
defaultRejectHashAlgorithms = map[crypto.Hash]bool{
crypto.MD5: true,
crypto.RIPEMD160: true,
}
defaultRejectMessageHashAlgorithms = map[crypto.Hash]bool{
crypto.SHA1: true,
crypto.MD5: true,
crypto.RIPEMD160: true,
}
defaultRejectCurves = map[Curve]bool{
CurveSecP256k1: true,
}
)
// A global feature flag to indicate v5 support.
// Can be set via a build tag, e.g.: `go build -tags v5 ./...`
// If the build tag is missing config_v5.go will set it to true.
//
// Disables parsing of v5 keys and v5 signatures.
// These are non-standard entities, which in the crypto-refresh have been superseded
// by v6 keys, v6 signatures and SEIPDv2 encrypted data, respectively.
var V5Disabled = false
// Config collects a number of parameters along with sensible defaults.
// A nil *Config is valid and results in all default values.
type Config struct {
// Rand provides the source of entropy.
// If nil, the crypto/rand Reader is used.
Rand io.Reader
// DefaultHash is the default hash function to be used.
// If zero, SHA-256 is used.
DefaultHash crypto.Hash
// DefaultCipher is the cipher to be used.
// If zero, AES-128 is used.
DefaultCipher CipherFunction
// Time returns the current time as the number of seconds since the
// epoch. If Time is nil, time.Now is used.
Time func() time.Time
// DefaultCompressionAlgo is the compression algorithm to be
// applied to the plaintext before encryption. If zero, no
// compression is done.
DefaultCompressionAlgo CompressionAlgo
// CompressionConfig configures the compression settings.
CompressionConfig *CompressionConfig
// S2K (String to Key) config, used for key derivation in the context of secret key encryption
// and password-encrypted data.
// If nil, the default configuration is used
S2KConfig *s2k.Config
// Iteration count for Iterated S2K (String to Key).
// Only used if sk2.Mode is nil.
// This value is duplicated here from s2k.Config for backwards compatibility.
// It determines the strength of the passphrase stretching when
// the said passphrase is hashed to produce a key. S2KCount
// should be between 65536 and 65011712, inclusive. If Config
// is nil or S2KCount is 0, the value 16777216 used. Not all
// values in the above range can be represented. S2KCount will
// be rounded up to the next representable value if it cannot
// be encoded exactly. When set, it is strongly encrouraged to
// use a value that is at least 65536. See RFC 4880 Section
// 3.7.1.3.
//
// Deprecated: SK2Count should be configured in S2KConfig instead.
S2KCount int
// RSABits is the number of bits in new RSA keys made with NewEntity.
// If zero, then 2048 bit keys are created.
RSABits int
// The public key algorithm to use - will always create a signing primary
// key and encryption subkey.
Algorithm PublicKeyAlgorithm
// Some known primes that are optionally prepopulated by the caller
RSAPrimes []*big.Int
// Curve configures the desired packet.Curve if the Algorithm is PubKeyAlgoECDSA,
// PubKeyAlgoEdDSA, or PubKeyAlgoECDH. If empty Curve25519 is used.
Curve Curve
// AEADConfig configures the use of the new AEAD Encrypted Data Packet,
// defined in the draft of the next version of the OpenPGP specification.
// If a non-nil AEADConfig is passed, usage of this packet is enabled. By
// default, it is disabled. See the documentation of AEADConfig for more
// configuration options related to AEAD.
// **Note: using this option may break compatibility with other OpenPGP
// implementations, as well as future versions of this library.**
AEADConfig *AEADConfig
// V6Keys configures version 6 key generation. If false, this package still
// supports version 6 keys, but produces version 4 keys.
V6Keys bool
// Minimum RSA key size allowed for key generation and message signing, verification and encryption.
MinRSABits uint16
// Reject insecure algorithms, only works with v2 api
RejectPublicKeyAlgorithms map[PublicKeyAlgorithm]bool
RejectHashAlgorithms map[crypto.Hash]bool
RejectMessageHashAlgorithms map[crypto.Hash]bool
RejectCurves map[Curve]bool
// "The validity period of the key. This is the number of seconds after
// the key creation time that the key expires. If this is not present
// or has a value of zero, the key never expires. This is found only on
// a self-signature.""
// https://tools.ietf.org/html/rfc4880#section-5.2.3.6
KeyLifetimeSecs uint32
// "The validity period of the signature. This is the number of seconds
// after the signature creation time that the signature expires. If
// this is not present or has a value of zero, it never expires."
// https://tools.ietf.org/html/rfc4880#section-5.2.3.10
SigLifetimeSecs uint32
// SigningKeyId is used to specify the signing key to use (by Key ID).
// By default, the signing key is selected automatically, preferring
// signing subkeys if available.
SigningKeyId uint64
// SigningIdentity is used to specify a user ID (packet Signer's User ID, type 28)
// when producing a generic certification signature onto an existing user ID.
// The identity must be present in the signer Entity.
SigningIdentity string
// InsecureAllowUnauthenticatedMessages controls, whether it is tolerated to read
// encrypted messages without Modification Detection Code (MDC).
// MDC is mandated by the IETF OpenPGP Crypto Refresh draft and has long been implemented
// in most OpenPGP implementations. Messages without MDC are considered unnecessarily
// insecure and should be prevented whenever possible.
// In case one needs to deal with messages from very old OpenPGP implementations, there
// might be no other way than to tolerate the missing MDC. Setting this flag, allows this
// mode of operation. It should be considered a measure of last resort.
InsecureAllowUnauthenticatedMessages bool
// InsecureAllowDecryptionWithSigningKeys allows decryption with keys marked as signing keys in the v2 API.
// This setting is potentially insecure, but it is needed as some libraries
// ignored key flags when selecting a key for encryption.
// Not relevant for the v1 API, as all keys were allowed in decryption.
InsecureAllowDecryptionWithSigningKeys bool
// KnownNotations is a map of Notation Data names to bools, which controls
// the notation names that are allowed to be present in critical Notation Data
// signature subpackets.
KnownNotations map[string]bool
// SignatureNotations is a list of Notations to be added to any signatures.
SignatureNotations []*Notation
// CheckIntendedRecipients controls, whether the OpenPGP Intended Recipient Fingerprint feature
// should be enabled for encryption and decryption.
// (See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-12.html#name-intended-recipient-fingerpr).
// When the flag is set, encryption produces Intended Recipient Fingerprint signature sub-packets and decryption
// checks whether the key it was encrypted to is one of the included fingerprints in the signature.
// If the flag is disabled, no Intended Recipient Fingerprint sub-packets are created or checked.
// The default behavior, when the config or flag is nil, is to enable the feature.
CheckIntendedRecipients *bool
// CacheSessionKey controls if decryption should return the session key used for decryption.
// If the flag is set, the session key is cached in the message details struct.
CacheSessionKey bool
// CheckPacketSequence is a flag that controls if the pgp message reader should strictly check
// that the packet sequence conforms with the grammar mandated by rfc4880.
// The default behavior, when the config or flag is nil, is to check the packet sequence.
CheckPacketSequence *bool
// NonDeterministicSignaturesViaNotation is a flag to enable randomization of signatures.
// If true, a salt notation is used to randomize signatures generated by v4 and v5 keys
// (v6 signatures are always non-deterministic, by design).
// This protects EdDSA signatures from potentially leaking the secret key in case of faults (i.e. bitflips) which, in principle, could occur
// during the signing computation. It is added to signatures of any algo for simplicity, and as it may also serve as protection in case of
// weaknesses in the hash algo, potentially hindering e.g. some chosen-prefix attacks.
// The default behavior, when the config or flag is nil, is to enable the feature.
NonDeterministicSignaturesViaNotation *bool
}
func (c *Config) Random() io.Reader {
if c == nil || c.Rand == nil {
return rand.Reader
}
return c.Rand
}
func (c *Config) Hash() crypto.Hash {
if c == nil || uint(c.DefaultHash) == 0 {
return crypto.SHA256
}
return c.DefaultHash
}
func (c *Config) Cipher() CipherFunction {
if c == nil || uint8(c.DefaultCipher) == 0 {
return CipherAES128
}
return c.DefaultCipher
}
func (c *Config) Now() time.Time {
if c == nil || c.Time == nil {
return time.Now().Truncate(time.Second)
}
return c.Time().Truncate(time.Second)
}
// KeyLifetime returns the validity period of the key.
func (c *Config) KeyLifetime() uint32 {
if c == nil {
return 0
}
return c.KeyLifetimeSecs
}
// SigLifetime returns the validity period of the signature.
func (c *Config) SigLifetime() uint32 {
if c == nil {
return 0
}
return c.SigLifetimeSecs
}
func (c *Config) Compression() CompressionAlgo {
if c == nil {
return CompressionNone
}
return c.DefaultCompressionAlgo
}
func (c *Config) RSAModulusBits() int {
if c == nil || c.RSABits == 0 {
return 2048
}
return c.RSABits
}
func (c *Config) PublicKeyAlgorithm() PublicKeyAlgorithm {
if c == nil || c.Algorithm == 0 {
return PubKeyAlgoRSA
}
return c.Algorithm
}
func (c *Config) CurveName() Curve {
if c == nil || c.Curve == "" {
return Curve25519
}
return c.Curve
}
// Deprecated: The hash iterations should now be queried via the S2K() method.
func (c *Config) PasswordHashIterations() int {
if c == nil || c.S2KCount == 0 {
return 0
}
return c.S2KCount
}
func (c *Config) S2K() *s2k.Config {
if c == nil {
return nil
}
// for backwards compatibility
if c.S2KCount > 0 && c.S2KConfig == nil {
return &s2k.Config{
S2KCount: c.S2KCount,
}
}
return c.S2KConfig
}
func (c *Config) AEAD() *AEADConfig {
if c == nil {
return nil
}
return c.AEADConfig
}
func (c *Config) SigningKey() uint64 {
if c == nil {
return 0
}
return c.SigningKeyId
}
func (c *Config) SigningUserId() string {
if c == nil {
return ""
}
return c.SigningIdentity
}
func (c *Config) AllowUnauthenticatedMessages() bool {
if c == nil {
return false
}
return c.InsecureAllowUnauthenticatedMessages
}
func (c *Config) AllowDecryptionWithSigningKeys() bool {
if c == nil {
return false
}
return c.InsecureAllowDecryptionWithSigningKeys
}
func (c *Config) KnownNotation(notationName string) bool {
if c == nil {
return false
}
return c.KnownNotations[notationName]
}
func (c *Config) Notations() []*Notation {
if c == nil {
return nil
}
return c.SignatureNotations
}
func (c *Config) V6() bool {
if c == nil {
return false
}
return c.V6Keys
}
func (c *Config) IntendedRecipients() bool {
if c == nil || c.CheckIntendedRecipients == nil {
return true
}
return *c.CheckIntendedRecipients
}
func (c *Config) RetrieveSessionKey() bool {
if c == nil {
return false
}
return c.CacheSessionKey
}
func (c *Config) MinimumRSABits() uint16 {
if c == nil || c.MinRSABits == 0 {
return 2047
}
return c.MinRSABits
}
func (c *Config) RejectPublicKeyAlgorithm(alg PublicKeyAlgorithm) bool {
var rejectedAlgorithms map[PublicKeyAlgorithm]bool
if c == nil || c.RejectPublicKeyAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectPublicKeyAlgorithms
} else {
rejectedAlgorithms = c.RejectPublicKeyAlgorithms
}
return rejectedAlgorithms[alg]
}
func (c *Config) RejectHashAlgorithm(hash crypto.Hash) bool {
var rejectedAlgorithms map[crypto.Hash]bool
if c == nil || c.RejectHashAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectHashAlgorithms
} else {
rejectedAlgorithms = c.RejectHashAlgorithms
}
return rejectedAlgorithms[hash]
}
func (c *Config) RejectMessageHashAlgorithm(hash crypto.Hash) bool {
var rejectedAlgorithms map[crypto.Hash]bool
if c == nil || c.RejectMessageHashAlgorithms == nil {
// Default
rejectedAlgorithms = defaultRejectMessageHashAlgorithms
} else {
rejectedAlgorithms = c.RejectMessageHashAlgorithms
}
return rejectedAlgorithms[hash]
}
func (c *Config) RejectCurve(curve Curve) bool {
var rejectedCurve map[Curve]bool
if c == nil || c.RejectCurves == nil {
// Default
rejectedCurve = defaultRejectCurves
} else {
rejectedCurve = c.RejectCurves
}
return rejectedCurve[curve]
}
func (c *Config) StrictPacketSequence() bool {
if c == nil || c.CheckPacketSequence == nil {
return true
}
return *c.CheckPacketSequence
}
func (c *Config) RandomizeSignaturesViaNotation() bool {
if c == nil || c.NonDeterministicSignaturesViaNotation == nil {
return true
}
return *c.NonDeterministicSignaturesViaNotation
}
// BoolPointer is a helper function to set a boolean pointer in the Config.
// e.g., config.CheckPacketSequence = BoolPointer(true)
func BoolPointer(value bool) *bool {
return &value
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/config_v5.go
================================================
//go:build !v5
package packet
func init() {
V5Disabled = true
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/encrypted_key.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"crypto"
"crypto/rsa"
"encoding/binary"
"encoding/hex"
"io"
"math/big"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
"github.com/ProtonMail/go-crypto/openpgp/x25519"
"github.com/ProtonMail/go-crypto/openpgp/x448"
)
// EncryptedKey represents a public-key encrypted session key. See RFC 4880,
// section 5.1.
type EncryptedKey struct {
Version int
KeyId uint64
KeyVersion int // v6
KeyFingerprint []byte // v6
Algo PublicKeyAlgorithm
CipherFunc CipherFunction // only valid after a successful Decrypt for a v3 packet
Key []byte // only valid after a successful Decrypt
encryptedMPI1, encryptedMPI2 encoding.Field
ephemeralPublicX25519 *x25519.PublicKey // used for x25519
ephemeralPublicX448 *x448.PublicKey // used for x448
encryptedSession []byte // used for x25519 and x448
}
func (e *EncryptedKey) parse(r io.Reader) (err error) {
var buf [8]byte
_, err = readFull(r, buf[:versionSize])
if err != nil {
return
}
e.Version = int(buf[0])
if e.Version != 3 && e.Version != 6 {
return errors.UnsupportedError("unknown EncryptedKey version " + strconv.Itoa(int(buf[0])))
}
if e.Version == 6 {
//Read a one-octet size of the following two fields.
if _, err = readFull(r, buf[:1]); err != nil {
return
}
// The size may also be zero, and the key version and
// fingerprint omitted for an "anonymous recipient"
if buf[0] != 0 {
// non-anonymous case
_, err = readFull(r, buf[:versionSize])
if err != nil {
return
}
e.KeyVersion = int(buf[0])
if e.KeyVersion != 4 && e.KeyVersion != 6 {
return errors.UnsupportedError("unknown public key version " + strconv.Itoa(e.KeyVersion))
}
var fingerprint []byte
if e.KeyVersion == 6 {
fingerprint = make([]byte, fingerprintSizeV6)
} else if e.KeyVersion == 4 {
fingerprint = make([]byte, fingerprintSize)
}
_, err = readFull(r, fingerprint)
if err != nil {
return
}
e.KeyFingerprint = fingerprint
if e.KeyVersion == 6 {
e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[:keyIdSize])
} else if e.KeyVersion == 4 {
e.KeyId = binary.BigEndian.Uint64(e.KeyFingerprint[fingerprintSize-keyIdSize : fingerprintSize])
}
}
} else {
_, err = readFull(r, buf[:8])
if err != nil {
return
}
e.KeyId = binary.BigEndian.Uint64(buf[:keyIdSize])
}
_, err = readFull(r, buf[:1])
if err != nil {
return
}
e.Algo = PublicKeyAlgorithm(buf[0])
var cipherFunction byte
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
e.encryptedMPI1 = new(encoding.MPI)
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
return
}
case PubKeyAlgoElGamal:
e.encryptedMPI1 = new(encoding.MPI)
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
return
}
e.encryptedMPI2 = new(encoding.MPI)
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
return
}
case PubKeyAlgoECDH:
e.encryptedMPI1 = new(encoding.MPI)
if _, err = e.encryptedMPI1.ReadFrom(r); err != nil {
return
}
e.encryptedMPI2 = new(encoding.OID)
if _, err = e.encryptedMPI2.ReadFrom(r); err != nil {
return
}
case PubKeyAlgoX25519:
e.ephemeralPublicX25519, e.encryptedSession, cipherFunction, err = x25519.DecodeFields(r, e.Version == 6)
if err != nil {
return
}
case PubKeyAlgoX448:
e.ephemeralPublicX448, e.encryptedSession, cipherFunction, err = x448.DecodeFields(r, e.Version == 6)
if err != nil {
return
}
}
if e.Version < 6 {
switch e.Algo {
case PubKeyAlgoX25519, PubKeyAlgoX448:
e.CipherFunc = CipherFunction(cipherFunction)
// Check for validiy is in the Decrypt method
}
}
_, err = consumeAll(r)
return
}
// Decrypt decrypts an encrypted session key with the given private key. The
// private key must have been decrypted first.
// If config is nil, sensible defaults will be used.
func (e *EncryptedKey) Decrypt(priv *PrivateKey, config *Config) error {
if e.Version < 6 && e.KeyId != 0 && e.KeyId != priv.KeyId {
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key id " + strconv.FormatUint(e.KeyId, 16) + " with private key id " + strconv.FormatUint(priv.KeyId, 16))
}
if e.Version == 6 && e.KeyVersion != 0 && !bytes.Equal(e.KeyFingerprint, priv.Fingerprint) {
return errors.InvalidArgumentError("cannot decrypt encrypted session key for key fingerprint " + hex.EncodeToString(e.KeyFingerprint) + " with private key fingerprint " + hex.EncodeToString(priv.Fingerprint))
}
if e.Algo != priv.PubKeyAlgo {
return errors.InvalidArgumentError("cannot decrypt encrypted session key of type " + strconv.Itoa(int(e.Algo)) + " with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
}
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
var err error
var b []byte
// TODO(agl): use session key decryption routines here to avoid
// padding oracle attacks.
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
// Supports both *rsa.PrivateKey and crypto.Decrypter
k := priv.PrivateKey.(crypto.Decrypter)
b, err = k.Decrypt(config.Random(), padToKeySize(k.Public().(*rsa.PublicKey), e.encryptedMPI1.Bytes()), nil)
case PubKeyAlgoElGamal:
c1 := new(big.Int).SetBytes(e.encryptedMPI1.Bytes())
c2 := new(big.Int).SetBytes(e.encryptedMPI2.Bytes())
b, err = elgamal.Decrypt(priv.PrivateKey.(*elgamal.PrivateKey), c1, c2)
case PubKeyAlgoECDH:
vsG := e.encryptedMPI1.Bytes()
m := e.encryptedMPI2.Bytes()
oid := priv.PublicKey.oid.EncodedBytes()
fp := priv.PublicKey.Fingerprint[:]
if priv.PublicKey.Version == 5 {
// For v5 the, the fingerprint must be restricted to 20 bytes
fp = fp[:20]
}
b, err = ecdh.Decrypt(priv.PrivateKey.(*ecdh.PrivateKey), vsG, m, oid, fp)
case PubKeyAlgoX25519:
b, err = x25519.Decrypt(priv.PrivateKey.(*x25519.PrivateKey), e.ephemeralPublicX25519, e.encryptedSession)
case PubKeyAlgoX448:
b, err = x448.Decrypt(priv.PrivateKey.(*x448.PrivateKey), e.ephemeralPublicX448, e.encryptedSession)
default:
err = errors.InvalidArgumentError("cannot decrypt encrypted session key with private key of type " + strconv.Itoa(int(priv.PubKeyAlgo)))
}
if err != nil {
return err
}
var key []byte
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
keyOffset := 0
if e.Version < 6 {
e.CipherFunc = CipherFunction(b[0])
keyOffset = 1
if !e.CipherFunc.IsSupported() {
return errors.UnsupportedError("unsupported encryption function")
}
}
key, err = decodeChecksumKey(b[keyOffset:])
if err != nil {
return err
}
case PubKeyAlgoX25519, PubKeyAlgoX448:
if e.Version < 6 {
switch e.CipherFunc {
case CipherAES128, CipherAES192, CipherAES256:
break
default:
return errors.StructuralError("v3 PKESK mandates AES as cipher function for x25519 and x448")
}
}
key = b[:]
default:
return errors.UnsupportedError("unsupported algorithm for decryption")
}
e.Key = key
return nil
}
// Serialize writes the encrypted key packet, e, to w.
func (e *EncryptedKey) Serialize(w io.Writer) error {
var encodedLength int
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
encodedLength = int(e.encryptedMPI1.EncodedLength())
case PubKeyAlgoElGamal:
encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
case PubKeyAlgoECDH:
encodedLength = int(e.encryptedMPI1.EncodedLength()) + int(e.encryptedMPI2.EncodedLength())
case PubKeyAlgoX25519:
encodedLength = x25519.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
case PubKeyAlgoX448:
encodedLength = x448.EncodedFieldsLength(e.encryptedSession, e.Version == 6)
default:
return errors.InvalidArgumentError("don't know how to serialize encrypted key type " + strconv.Itoa(int(e.Algo)))
}
packetLen := versionSize /* version */ + keyIdSize /* key id */ + algorithmSize /* algo */ + encodedLength
if e.Version == 6 {
packetLen = versionSize /* version */ + algorithmSize /* algo */ + encodedLength + keyVersionSize /* key version */
if e.KeyVersion == 6 {
packetLen += fingerprintSizeV6
} else if e.KeyVersion == 4 {
packetLen += fingerprintSize
}
}
err := serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write([]byte{byte(e.Version)})
if err != nil {
return err
}
if e.Version == 6 {
_, err = w.Write([]byte{byte(e.KeyVersion)})
if err != nil {
return err
}
// The key version number may also be zero,
// and the fingerprint omitted
if e.KeyVersion != 0 {
_, err = w.Write(e.KeyFingerprint)
if err != nil {
return err
}
}
} else {
// Write KeyID
err = binary.Write(w, binary.BigEndian, e.KeyId)
if err != nil {
return err
}
}
_, err = w.Write([]byte{byte(e.Algo)})
if err != nil {
return err
}
switch e.Algo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
_, err := w.Write(e.encryptedMPI1.EncodedBytes())
return err
case PubKeyAlgoElGamal:
if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil {
return err
}
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
return err
case PubKeyAlgoECDH:
if _, err := w.Write(e.encryptedMPI1.EncodedBytes()); err != nil {
return err
}
_, err := w.Write(e.encryptedMPI2.EncodedBytes())
return err
case PubKeyAlgoX25519:
err := x25519.EncodeFields(w, e.ephemeralPublicX25519, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
return err
case PubKeyAlgoX448:
err := x448.EncodeFields(w, e.ephemeralPublicX448, e.encryptedSession, byte(e.CipherFunc), e.Version == 6)
return err
default:
panic("internal error")
}
}
// SerializeEncryptedKeyAEAD serializes an encrypted key packet to w that contains
// key, encrypted to pub.
// If aeadSupported is set, PKESK v6 is used, otherwise v3.
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
func SerializeEncryptedKeyAEAD(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, config *Config) error {
return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, aeadSupported, key, false, config)
}
// SerializeEncryptedKeyAEADwithHiddenOption serializes an encrypted key packet to w that contains
// key, encrypted to pub.
// Offers the hidden flag option to indicated if the PKESK packet should include a wildcard KeyID.
// If aeadSupported is set, PKESK v6 is used, otherwise v3.
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
func SerializeEncryptedKeyAEADwithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, aeadSupported bool, key []byte, hidden bool, config *Config) error {
var buf [36]byte // max possible header size is v6
lenHeaderWritten := versionSize
version := 3
if aeadSupported {
version = 6
}
// An implementation MUST NOT generate ElGamal v6 PKESKs.
if version == 6 && pub.PubKeyAlgo == PubKeyAlgoElGamal {
return errors.InvalidArgumentError("ElGamal v6 PKESK are not allowed")
}
// In v3 PKESKs, for x25519 and x448, mandate using AES
if version == 3 && (pub.PubKeyAlgo == PubKeyAlgoX25519 || pub.PubKeyAlgo == PubKeyAlgoX448) {
switch cipherFunc {
case CipherAES128, CipherAES192, CipherAES256:
break
default:
return errors.InvalidArgumentError("v3 PKESK mandates AES for x25519 and x448")
}
}
buf[0] = byte(version)
// If hidden is set, the key should be hidden
// An implementation MAY accept or use a Key ID of all zeros,
// or a key version of zero and no key fingerprint, to hide the intended decryption key.
// See Section 5.1.8. in the open pgp crypto refresh
if version == 6 {
if !hidden {
// A one-octet size of the following two fields.
buf[1] = byte(keyVersionSize + len(pub.Fingerprint))
// A one octet key version number.
buf[2] = byte(pub.Version)
lenHeaderWritten += keyVersionSize + 1
// The fingerprint of the public key
copy(buf[lenHeaderWritten:lenHeaderWritten+len(pub.Fingerprint)], pub.Fingerprint)
lenHeaderWritten += len(pub.Fingerprint)
} else {
// The size may also be zero, and the key version
// and fingerprint omitted for an "anonymous recipient"
buf[1] = 0
lenHeaderWritten += 1
}
} else {
if !hidden {
binary.BigEndian.PutUint64(buf[versionSize:(versionSize+keyIdSize)], pub.KeyId)
}
lenHeaderWritten += keyIdSize
}
buf[lenHeaderWritten] = byte(pub.PubKeyAlgo)
lenHeaderWritten += algorithmSize
var keyBlock []byte
switch pub.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH:
lenKeyBlock := len(key) + 2
if version < 6 {
lenKeyBlock += 1 // cipher type included
}
keyBlock = make([]byte, lenKeyBlock)
keyOffset := 0
if version < 6 {
keyBlock[0] = byte(cipherFunc)
keyOffset = 1
}
encodeChecksumKey(keyBlock[keyOffset:], key)
case PubKeyAlgoX25519, PubKeyAlgoX448:
// algorithm is added in plaintext below
keyBlock = key
}
switch pub.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly:
return serializeEncryptedKeyRSA(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*rsa.PublicKey), keyBlock)
case PubKeyAlgoElGamal:
return serializeEncryptedKeyElGamal(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*elgamal.PublicKey), keyBlock)
case PubKeyAlgoECDH:
return serializeEncryptedKeyECDH(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*ecdh.PublicKey), keyBlock, pub.oid, pub.Fingerprint)
case PubKeyAlgoX25519:
return serializeEncryptedKeyX25519(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x25519.PublicKey), keyBlock, byte(cipherFunc), version)
case PubKeyAlgoX448:
return serializeEncryptedKeyX448(w, config.Random(), buf[:lenHeaderWritten], pub.PublicKey.(*x448.PublicKey), keyBlock, byte(cipherFunc), version)
case PubKeyAlgoDSA, PubKeyAlgoRSASignOnly:
return errors.InvalidArgumentError("cannot encrypt to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
}
return errors.UnsupportedError("encrypting a key to public key of type " + strconv.Itoa(int(pub.PubKeyAlgo)))
}
// SerializeEncryptedKey serializes an encrypted key packet to w that contains
// key, encrypted to pub.
// PKESKv6 is used if config.AEAD() is not nil.
// If config is nil, sensible defaults will be used.
// Deprecated: Use SerializeEncryptedKeyAEAD instead.
func SerializeEncryptedKey(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, config *Config) error {
return SerializeEncryptedKeyAEAD(w, pub, cipherFunc, config.AEAD() != nil, key, config)
}
// SerializeEncryptedKeyWithHiddenOption serializes an encrypted key packet to w that contains
// key, encrypted to pub. PKESKv6 is used if config.AEAD() is not nil.
// The hidden option controls if the packet should be anonymous, i.e., omit key metadata.
// If config is nil, sensible defaults will be used.
// Deprecated: Use SerializeEncryptedKeyAEADwithHiddenOption instead.
func SerializeEncryptedKeyWithHiddenOption(w io.Writer, pub *PublicKey, cipherFunc CipherFunction, key []byte, hidden bool, config *Config) error {
return SerializeEncryptedKeyAEADwithHiddenOption(w, pub, cipherFunc, config.AEAD() != nil, key, hidden, config)
}
func serializeEncryptedKeyRSA(w io.Writer, rand io.Reader, header []byte, pub *rsa.PublicKey, keyBlock []byte) error {
cipherText, err := rsa.EncryptPKCS1v15(rand, pub, keyBlock)
if err != nil {
return errors.InvalidArgumentError("RSA encryption failed: " + err.Error())
}
cipherMPI := encoding.NewMPI(cipherText)
packetLen := len(header) /* header length */ + int(cipherMPI.EncodedLength())
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write(header[:])
if err != nil {
return err
}
_, err = w.Write(cipherMPI.EncodedBytes())
return err
}
func serializeEncryptedKeyElGamal(w io.Writer, rand io.Reader, header []byte, pub *elgamal.PublicKey, keyBlock []byte) error {
c1, c2, err := elgamal.Encrypt(rand, pub, keyBlock)
if err != nil {
return errors.InvalidArgumentError("ElGamal encryption failed: " + err.Error())
}
packetLen := len(header) /* header length */
packetLen += 2 /* mpi size */ + (c1.BitLen()+7)/8
packetLen += 2 /* mpi size */ + (c2.BitLen()+7)/8
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write(header[:])
if err != nil {
return err
}
if _, err = w.Write(new(encoding.MPI).SetBig(c1).EncodedBytes()); err != nil {
return err
}
_, err = w.Write(new(encoding.MPI).SetBig(c2).EncodedBytes())
return err
}
func serializeEncryptedKeyECDH(w io.Writer, rand io.Reader, header []byte, pub *ecdh.PublicKey, keyBlock []byte, oid encoding.Field, fingerprint []byte) error {
vsG, c, err := ecdh.Encrypt(rand, pub, keyBlock, oid.EncodedBytes(), fingerprint)
if err != nil {
return errors.InvalidArgumentError("ECDH encryption failed: " + err.Error())
}
g := encoding.NewMPI(vsG)
m := encoding.NewOID(c)
packetLen := len(header) /* header length */
packetLen += int(g.EncodedLength()) + int(m.EncodedLength())
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write(header[:])
if err != nil {
return err
}
if _, err = w.Write(g.EncodedBytes()); err != nil {
return err
}
_, err = w.Write(m.EncodedBytes())
return err
}
func serializeEncryptedKeyX25519(w io.Writer, rand io.Reader, header []byte, pub *x25519.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
ephemeralPublicX25519, ciphertext, err := x25519.Encrypt(rand, pub, keyBlock)
if err != nil {
return errors.InvalidArgumentError("x25519 encryption failed: " + err.Error())
}
packetLen := len(header) /* header length */
packetLen += x25519.EncodedFieldsLength(ciphertext, version == 6)
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write(header[:])
if err != nil {
return err
}
return x25519.EncodeFields(w, ephemeralPublicX25519, ciphertext, cipherFunc, version == 6)
}
func serializeEncryptedKeyX448(w io.Writer, rand io.Reader, header []byte, pub *x448.PublicKey, keyBlock []byte, cipherFunc byte, version int) error {
ephemeralPublicX448, ciphertext, err := x448.Encrypt(rand, pub, keyBlock)
if err != nil {
return errors.InvalidArgumentError("x448 encryption failed: " + err.Error())
}
packetLen := len(header) /* header length */
packetLen += x448.EncodedFieldsLength(ciphertext, version == 6)
err = serializeHeader(w, packetTypeEncryptedKey, packetLen)
if err != nil {
return err
}
_, err = w.Write(header[:])
if err != nil {
return err
}
return x448.EncodeFields(w, ephemeralPublicX448, ciphertext, cipherFunc, version == 6)
}
func checksumKeyMaterial(key []byte) uint16 {
var checksum uint16
for _, v := range key {
checksum += uint16(v)
}
return checksum
}
func decodeChecksumKey(msg []byte) (key []byte, err error) {
key = msg[:len(msg)-2]
expectedChecksum := uint16(msg[len(msg)-2])<<8 | uint16(msg[len(msg)-1])
checksum := checksumKeyMaterial(key)
if checksum != expectedChecksum {
err = errors.StructuralError("session key checksum is incorrect")
}
return
}
func encodeChecksumKey(buffer []byte, key []byte) {
copy(buffer, key)
checksum := checksumKeyMaterial(key)
buffer[len(key)] = byte(checksum >> 8)
buffer[len(key)+1] = byte(checksum)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/literal.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"encoding/binary"
"io"
)
// LiteralData represents an encrypted file. See RFC 4880, section 5.9.
type LiteralData struct {
Format uint8
IsBinary bool
FileName string
Time uint32 // Unix epoch time. Either creation time or modification time. 0 means undefined.
Body io.Reader
}
// ForEyesOnly returns whether the contents of the LiteralData have been marked
// as especially sensitive.
func (l *LiteralData) ForEyesOnly() bool {
return l.FileName == "_CONSOLE"
}
func (l *LiteralData) parse(r io.Reader) (err error) {
var buf [256]byte
_, err = readFull(r, buf[:2])
if err != nil {
return
}
l.Format = buf[0]
l.IsBinary = l.Format == 'b'
fileNameLen := int(buf[1])
_, err = readFull(r, buf[:fileNameLen])
if err != nil {
return
}
l.FileName = string(buf[:fileNameLen])
_, err = readFull(r, buf[:4])
if err != nil {
return
}
l.Time = binary.BigEndian.Uint32(buf[:4])
l.Body = r
return
}
// SerializeLiteral serializes a literal data packet to w and returns a
// WriteCloser to which the data itself can be written and which MUST be closed
// on completion. The fileName is truncated to 255 bytes.
func SerializeLiteral(w io.WriteCloser, isBinary bool, fileName string, time uint32) (plaintext io.WriteCloser, err error) {
var buf [4]byte
buf[0] = 'b'
if !isBinary {
buf[0] = 'u'
}
if len(fileName) > 255 {
fileName = fileName[:255]
}
buf[1] = byte(len(fileName))
inner, err := serializeStreamHeader(w, packetTypeLiteralData)
if err != nil {
return
}
_, err = inner.Write(buf[:2])
if err != nil {
return
}
_, err = inner.Write([]byte(fileName))
if err != nil {
return
}
binary.BigEndian.PutUint32(buf[:], time)
_, err = inner.Write(buf[:])
if err != nil {
return
}
plaintext = inner
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/marker.go
================================================
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
type Marker struct{}
const markerString = "PGP"
// parse just checks if the packet contains "PGP".
func (m *Marker) parse(reader io.Reader) error {
var buffer [3]byte
if _, err := io.ReadFull(reader, buffer[:]); err != nil {
return err
}
if string(buffer[:]) != markerString {
return errors.StructuralError("invalid marker packet")
}
return nil
}
// SerializeMarker writes a marker packet to writer.
func SerializeMarker(writer io.Writer) error {
err := serializeHeader(writer, packetTypeMarker, len(markerString))
if err != nil {
return err
}
_, err = writer.Write([]byte(markerString))
return err
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/notation.go
================================================
package packet
// Notation type represents a Notation Data subpacket
// see https://tools.ietf.org/html/rfc4880#section-5.2.3.16
type Notation struct {
Name string
Value []byte
IsCritical bool
IsHumanReadable bool
}
func (notation *Notation) getData() []byte {
nameData := []byte(notation.Name)
nameLen := len(nameData)
valueLen := len(notation.Value)
data := make([]byte, 8+nameLen+valueLen)
if notation.IsHumanReadable {
data[0] = 0x80
}
data[4] = byte(nameLen >> 8)
data[5] = byte(nameLen)
data[6] = byte(valueLen >> 8)
data[7] = byte(valueLen)
copy(data[8:8+nameLen], nameData)
copy(data[8+nameLen:], notation.Value)
return data
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/ocfb.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// OpenPGP CFB Mode. http://tools.ietf.org/html/rfc4880#section-13.9
package packet
import (
"crypto/cipher"
)
type ocfbEncrypter struct {
b cipher.Block
fre []byte
outUsed int
}
// An OCFBResyncOption determines if the "resynchronization step" of OCFB is
// performed.
type OCFBResyncOption bool
const (
OCFBResync OCFBResyncOption = true
OCFBNoResync OCFBResyncOption = false
)
// NewOCFBEncrypter returns a cipher.Stream which encrypts data with OpenPGP's
// cipher feedback mode using the given cipher.Block, and an initial amount of
// ciphertext. randData must be random bytes and be the same length as the
// cipher.Block's block size. Resync determines if the "resynchronization step"
// from RFC 4880, 13.9 step 7 is performed. Different parts of OpenPGP vary on
// this point.
func NewOCFBEncrypter(block cipher.Block, randData []byte, resync OCFBResyncOption) (cipher.Stream, []byte) {
blockSize := block.BlockSize()
if len(randData) != blockSize {
return nil, nil
}
x := &ocfbEncrypter{
b: block,
fre: make([]byte, blockSize),
outUsed: 0,
}
prefix := make([]byte, blockSize+2)
block.Encrypt(x.fre, x.fre)
for i := 0; i < blockSize; i++ {
prefix[i] = randData[i] ^ x.fre[i]
}
block.Encrypt(x.fre, prefix[:blockSize])
prefix[blockSize] = x.fre[0] ^ randData[blockSize-2]
prefix[blockSize+1] = x.fre[1] ^ randData[blockSize-1]
if resync {
block.Encrypt(x.fre, prefix[2:])
} else {
x.fre[0] = prefix[blockSize]
x.fre[1] = prefix[blockSize+1]
x.outUsed = 2
}
return x, prefix
}
func (x *ocfbEncrypter) XORKeyStream(dst, src []byte) {
for i := 0; i < len(src); i++ {
if x.outUsed == len(x.fre) {
x.b.Encrypt(x.fre, x.fre)
x.outUsed = 0
}
x.fre[x.outUsed] ^= src[i]
dst[i] = x.fre[x.outUsed]
x.outUsed++
}
}
type ocfbDecrypter struct {
b cipher.Block
fre []byte
outUsed int
}
// NewOCFBDecrypter returns a cipher.Stream which decrypts data with OpenPGP's
// cipher feedback mode using the given cipher.Block. Prefix must be the first
// blockSize + 2 bytes of the ciphertext, where blockSize is the cipher.Block's
// block size. On successful exit, blockSize+2 bytes of decrypted data are written into
// prefix. Resync determines if the "resynchronization step" from RFC 4880,
// 13.9 step 7 is performed. Different parts of OpenPGP vary on this point.
func NewOCFBDecrypter(block cipher.Block, prefix []byte, resync OCFBResyncOption) cipher.Stream {
blockSize := block.BlockSize()
if len(prefix) != blockSize+2 {
return nil
}
x := &ocfbDecrypter{
b: block,
fre: make([]byte, blockSize),
outUsed: 0,
}
prefixCopy := make([]byte, len(prefix))
copy(prefixCopy, prefix)
block.Encrypt(x.fre, x.fre)
for i := 0; i < blockSize; i++ {
prefixCopy[i] ^= x.fre[i]
}
block.Encrypt(x.fre, prefix[:blockSize])
prefixCopy[blockSize] ^= x.fre[0]
prefixCopy[blockSize+1] ^= x.fre[1]
if resync {
block.Encrypt(x.fre, prefix[2:])
} else {
x.fre[0] = prefix[blockSize]
x.fre[1] = prefix[blockSize+1]
x.outUsed = 2
}
copy(prefix, prefixCopy)
return x
}
func (x *ocfbDecrypter) XORKeyStream(dst, src []byte) {
for i := 0; i < len(src); i++ {
if x.outUsed == len(x.fre) {
x.b.Encrypt(x.fre, x.fre)
x.outUsed = 0
}
c := src[i]
dst[i] = x.fre[x.outUsed] ^ src[i]
x.fre[x.outUsed] = c
x.outUsed++
}
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/one_pass_signature.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto"
"encoding/binary"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// OnePassSignature represents a one-pass signature packet. See RFC 4880,
// section 5.4.
type OnePassSignature struct {
Version int
SigType SignatureType
Hash crypto.Hash
PubKeyAlgo PublicKeyAlgorithm
KeyId uint64
IsLast bool
Salt []byte // v6 only
KeyFingerprint []byte // v6 only
}
func (ops *OnePassSignature) parse(r io.Reader) (err error) {
var buf [8]byte
// Read: version | signature type | hash algorithm | public-key algorithm
_, err = readFull(r, buf[:4])
if err != nil {
return
}
if buf[0] != 3 && buf[0] != 6 {
return errors.UnsupportedError("one-pass-signature packet version " + strconv.Itoa(int(buf[0])))
}
ops.Version = int(buf[0])
var ok bool
ops.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
if !ok {
return errors.UnsupportedError("hash function: " + strconv.Itoa(int(buf[2])))
}
ops.SigType = SignatureType(buf[1])
ops.PubKeyAlgo = PublicKeyAlgorithm(buf[3])
if ops.Version == 6 {
// Only for v6, a variable-length field containing the salt
_, err = readFull(r, buf[:1])
if err != nil {
return
}
saltLength := int(buf[0])
var expectedSaltLength int
expectedSaltLength, err = SaltLengthForHash(ops.Hash)
if err != nil {
return
}
if saltLength != expectedSaltLength {
err = errors.StructuralError("unexpected salt size for the given hash algorithm")
return
}
salt := make([]byte, expectedSaltLength)
_, err = readFull(r, salt)
if err != nil {
return
}
ops.Salt = salt
// Only for v6 packets, 32 octets of the fingerprint of the signing key.
fingerprint := make([]byte, 32)
_, err = readFull(r, fingerprint)
if err != nil {
return
}
ops.KeyFingerprint = fingerprint
ops.KeyId = binary.BigEndian.Uint64(ops.KeyFingerprint[:8])
} else {
_, err = readFull(r, buf[:8])
if err != nil {
return
}
ops.KeyId = binary.BigEndian.Uint64(buf[:8])
}
_, err = readFull(r, buf[:1])
if err != nil {
return
}
ops.IsLast = buf[0] != 0
return
}
// Serialize marshals the given OnePassSignature to w.
func (ops *OnePassSignature) Serialize(w io.Writer) error {
//v3 length 1+1+1+1+8+1 =
packetLength := 13
if ops.Version == 6 {
// v6 length 1+1+1+1+1+len(salt)+32+1 =
packetLength = 38 + len(ops.Salt)
}
if err := serializeHeader(w, packetTypeOnePassSignature, packetLength); err != nil {
return err
}
var buf [8]byte
buf[0] = byte(ops.Version)
buf[1] = uint8(ops.SigType)
var ok bool
buf[2], ok = algorithm.HashToHashIdWithSha1(ops.Hash)
if !ok {
return errors.UnsupportedError("hash type: " + strconv.Itoa(int(ops.Hash)))
}
buf[3] = uint8(ops.PubKeyAlgo)
_, err := w.Write(buf[:4])
if err != nil {
return err
}
if ops.Version == 6 {
// write salt for v6 signatures
_, err := w.Write([]byte{uint8(len(ops.Salt))})
if err != nil {
return err
}
_, err = w.Write(ops.Salt)
if err != nil {
return err
}
// write fingerprint v6 signatures
_, err = w.Write(ops.KeyFingerprint)
if err != nil {
return err
}
} else {
binary.BigEndian.PutUint64(buf[:8], ops.KeyId)
_, err := w.Write(buf[:8])
if err != nil {
return err
}
}
isLast := []byte{byte(0)}
if ops.IsLast {
isLast[0] = 1
}
_, err = w.Write(isLast)
return err
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/opaque.go
================================================
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// OpaquePacket represents an OpenPGP packet as raw, unparsed data. This is
// useful for splitting and storing the original packet contents separately,
// handling unsupported packet types or accessing parts of the packet not yet
// implemented by this package.
type OpaquePacket struct {
// Packet type
Tag uint8
// Reason why the packet was parsed opaquely
Reason error
// Binary contents of the packet data
Contents []byte
}
func (op *OpaquePacket) parse(r io.Reader) (err error) {
op.Contents, err = io.ReadAll(r)
return
}
// Serialize marshals the packet to a writer in its original form, including
// the packet header.
func (op *OpaquePacket) Serialize(w io.Writer) (err error) {
err = serializeHeader(w, packetType(op.Tag), len(op.Contents))
if err == nil {
_, err = w.Write(op.Contents)
}
return
}
// Parse attempts to parse the opaque contents into a structure supported by
// this package. If the packet is not known then the result will be another
// OpaquePacket.
func (op *OpaquePacket) Parse() (p Packet, err error) {
hdr := bytes.NewBuffer(nil)
err = serializeHeader(hdr, packetType(op.Tag), len(op.Contents))
if err != nil {
op.Reason = err
return op, err
}
p, err = Read(io.MultiReader(hdr, bytes.NewBuffer(op.Contents)))
if err != nil {
op.Reason = err
p = op
}
return
}
// OpaqueReader reads OpaquePackets from an io.Reader.
type OpaqueReader struct {
r io.Reader
}
func NewOpaqueReader(r io.Reader) *OpaqueReader {
return &OpaqueReader{r: r}
}
// Read the next OpaquePacket.
func (or *OpaqueReader) Next() (op *OpaquePacket, err error) {
tag, _, contents, err := readHeader(or.r)
if err != nil {
return
}
op = &OpaquePacket{Tag: uint8(tag), Reason: err}
err = op.parse(contents)
if err != nil {
consumeAll(contents)
}
return
}
// OpaqueSubpacket represents an unparsed OpenPGP subpacket,
// as found in signature and user attribute packets.
type OpaqueSubpacket struct {
SubType uint8
EncodedLength []byte // Store the original encoded length for signature verifications.
Contents []byte
}
// OpaqueSubpackets extracts opaque, unparsed OpenPGP subpackets from
// their byte representation.
func OpaqueSubpackets(contents []byte) (result []*OpaqueSubpacket, err error) {
var (
subHeaderLen int
subPacket *OpaqueSubpacket
)
for len(contents) > 0 {
subHeaderLen, subPacket, err = nextSubpacket(contents)
if err != nil {
break
}
result = append(result, subPacket)
contents = contents[subHeaderLen+len(subPacket.Contents):]
}
return
}
func nextSubpacket(contents []byte) (subHeaderLen int, subPacket *OpaqueSubpacket, err error) {
// RFC 4880, section 5.2.3.1
var subLen uint32
var encodedLength []byte
if len(contents) < 1 {
goto Truncated
}
subPacket = &OpaqueSubpacket{}
switch {
case contents[0] < 192:
subHeaderLen = 2 // 1 length byte, 1 subtype byte
if len(contents) < subHeaderLen {
goto Truncated
}
encodedLength = contents[0:1]
subLen = uint32(contents[0])
contents = contents[1:]
case contents[0] < 255:
subHeaderLen = 3 // 2 length bytes, 1 subtype
if len(contents) < subHeaderLen {
goto Truncated
}
encodedLength = contents[0:2]
subLen = uint32(contents[0]-192)<<8 + uint32(contents[1]) + 192
contents = contents[2:]
default:
subHeaderLen = 6 // 5 length bytes, 1 subtype
if len(contents) < subHeaderLen {
goto Truncated
}
encodedLength = contents[0:5]
subLen = uint32(contents[1])<<24 |
uint32(contents[2])<<16 |
uint32(contents[3])<<8 |
uint32(contents[4])
contents = contents[5:]
}
if subLen > uint32(len(contents)) || subLen == 0 {
goto Truncated
}
subPacket.SubType = contents[0]
subPacket.EncodedLength = encodedLength
subPacket.Contents = contents[1:subLen]
return
Truncated:
err = errors.StructuralError("subpacket truncated")
return
}
func (osp *OpaqueSubpacket) Serialize(w io.Writer) (err error) {
buf := make([]byte, 6)
copy(buf, osp.EncodedLength)
n := len(osp.EncodedLength)
buf[n] = osp.SubType
if _, err = w.Write(buf[:n+1]); err != nil {
return
}
_, err = w.Write(osp.Contents)
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package packet implements parsing and serialization of OpenPGP packets, as
// specified in RFC 4880.
package packet // import "github.com/ProtonMail/go-crypto/openpgp/packet"
import (
"bytes"
"crypto/cipher"
"crypto/rsa"
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
)
// readFull is the same as io.ReadFull except that reading zero bytes returns
// ErrUnexpectedEOF rather than EOF.
func readFull(r io.Reader, buf []byte) (n int, err error) {
n, err = io.ReadFull(r, buf)
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// readLength reads an OpenPGP length from r. See RFC 4880, section 4.2.2.
func readLength(r io.Reader) (length int64, isPartial bool, err error) {
var buf [4]byte
_, err = readFull(r, buf[:1])
if err != nil {
return
}
switch {
case buf[0] < 192:
length = int64(buf[0])
case buf[0] < 224:
length = int64(buf[0]-192) << 8
_, err = readFull(r, buf[0:1])
if err != nil {
return
}
length += int64(buf[0]) + 192
case buf[0] < 255:
length = int64(1) << (buf[0] & 0x1f)
isPartial = true
default:
_, err = readFull(r, buf[0:4])
if err != nil {
return
}
length = int64(buf[0])<<24 |
int64(buf[1])<<16 |
int64(buf[2])<<8 |
int64(buf[3])
}
return
}
// partialLengthReader wraps an io.Reader and handles OpenPGP partial lengths.
// The continuation lengths are parsed and removed from the stream and EOF is
// returned at the end of the packet. See RFC 4880, section 4.2.2.4.
type partialLengthReader struct {
r io.Reader
remaining int64
isPartial bool
}
func (r *partialLengthReader) Read(p []byte) (n int, err error) {
for r.remaining == 0 {
if !r.isPartial {
return 0, io.EOF
}
r.remaining, r.isPartial, err = readLength(r.r)
if err != nil {
return 0, err
}
}
toRead := int64(len(p))
if toRead > r.remaining {
toRead = r.remaining
}
n, err = r.r.Read(p[:int(toRead)])
r.remaining -= int64(n)
if n < int(toRead) && err == io.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// partialLengthWriter writes a stream of data using OpenPGP partial lengths.
// See RFC 4880, section 4.2.2.4.
type partialLengthWriter struct {
w io.WriteCloser
buf bytes.Buffer
lengthByte [1]byte
}
func (w *partialLengthWriter) Write(p []byte) (n int, err error) {
bufLen := w.buf.Len()
if bufLen > 512 {
for power := uint(30); ; power-- {
l := 1 << power
if bufLen >= l {
w.lengthByte[0] = 224 + uint8(power)
_, err = w.w.Write(w.lengthByte[:])
if err != nil {
return
}
var m int
m, err = w.w.Write(w.buf.Next(l))
if err != nil {
return
}
if m != l {
return 0, io.ErrShortWrite
}
break
}
}
}
return w.buf.Write(p)
}
func (w *partialLengthWriter) Close() (err error) {
len := w.buf.Len()
err = serializeLength(w.w, len)
if err != nil {
return err
}
_, err = w.buf.WriteTo(w.w)
if err != nil {
return err
}
return w.w.Close()
}
// A spanReader is an io.LimitReader, but it returns ErrUnexpectedEOF if the
// underlying Reader returns EOF before the limit has been reached.
type spanReader struct {
r io.Reader
n int64
}
func (l *spanReader) Read(p []byte) (n int, err error) {
if l.n <= 0 {
return 0, io.EOF
}
if int64(len(p)) > l.n {
p = p[0:l.n]
}
n, err = l.r.Read(p)
l.n -= int64(n)
if l.n > 0 && err == io.EOF {
err = io.ErrUnexpectedEOF
}
return
}
// readHeader parses a packet header and returns an io.Reader which will return
// the contents of the packet. See RFC 4880, section 4.2.
func readHeader(r io.Reader) (tag packetType, length int64, contents io.Reader, err error) {
var buf [4]byte
_, err = io.ReadFull(r, buf[:1])
if err != nil {
return
}
if buf[0]&0x80 == 0 {
err = errors.StructuralError("tag byte does not have MSB set")
return
}
if buf[0]&0x40 == 0 {
// Old format packet
tag = packetType((buf[0] & 0x3f) >> 2)
lengthType := buf[0] & 3
if lengthType == 3 {
length = -1
contents = r
return
}
lengthBytes := 1 << lengthType
_, err = readFull(r, buf[0:lengthBytes])
if err != nil {
return
}
for i := 0; i < lengthBytes; i++ {
length <<= 8
length |= int64(buf[i])
}
contents = &spanReader{r, length}
return
}
// New format packet
tag = packetType(buf[0] & 0x3f)
length, isPartial, err := readLength(r)
if err != nil {
return
}
if isPartial {
contents = &partialLengthReader{
remaining: length,
isPartial: true,
r: r,
}
length = -1
} else {
contents = &spanReader{r, length}
}
return
}
// serializeHeader writes an OpenPGP packet header to w. See RFC 4880, section
// 4.2.
func serializeHeader(w io.Writer, ptype packetType, length int) (err error) {
err = serializeType(w, ptype)
if err != nil {
return
}
return serializeLength(w, length)
}
// serializeType writes an OpenPGP packet type to w. See RFC 4880, section
// 4.2.
func serializeType(w io.Writer, ptype packetType) (err error) {
var buf [1]byte
buf[0] = 0x80 | 0x40 | byte(ptype)
_, err = w.Write(buf[:])
return
}
// serializeLength writes an OpenPGP packet length to w. See RFC 4880, section
// 4.2.2.
func serializeLength(w io.Writer, length int) (err error) {
var buf [5]byte
var n int
if length < 192 {
buf[0] = byte(length)
n = 1
} else if length < 8384 {
length -= 192
buf[0] = 192 + byte(length>>8)
buf[1] = byte(length)
n = 2
} else {
buf[0] = 255
buf[1] = byte(length >> 24)
buf[2] = byte(length >> 16)
buf[3] = byte(length >> 8)
buf[4] = byte(length)
n = 5
}
_, err = w.Write(buf[:n])
return
}
// serializeStreamHeader writes an OpenPGP packet header to w where the
// length of the packet is unknown. It returns a io.WriteCloser which can be
// used to write the contents of the packet. See RFC 4880, section 4.2.
func serializeStreamHeader(w io.WriteCloser, ptype packetType) (out io.WriteCloser, err error) {
err = serializeType(w, ptype)
if err != nil {
return
}
out = &partialLengthWriter{w: w}
return
}
// Packet represents an OpenPGP packet. Users are expected to try casting
// instances of this interface to specific packet types.
type Packet interface {
parse(io.Reader) error
}
// consumeAll reads from the given Reader until error, returning the number of
// bytes read.
func consumeAll(r io.Reader) (n int64, err error) {
var m int
var buf [1024]byte
for {
m, err = r.Read(buf[:])
n += int64(m)
if err == io.EOF {
err = nil
return
}
if err != nil {
return
}
}
}
// packetType represents the numeric ids of the different OpenPGP packet types. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-2
type packetType uint8
const (
packetTypeEncryptedKey packetType = 1
packetTypeSignature packetType = 2
packetTypeSymmetricKeyEncrypted packetType = 3
packetTypeOnePassSignature packetType = 4
packetTypePrivateKey packetType = 5
packetTypePublicKey packetType = 6
packetTypePrivateSubkey packetType = 7
packetTypeCompressed packetType = 8
packetTypeSymmetricallyEncrypted packetType = 9
packetTypeMarker packetType = 10
packetTypeLiteralData packetType = 11
packetTypeTrust packetType = 12
packetTypeUserId packetType = 13
packetTypePublicSubkey packetType = 14
packetTypeUserAttribute packetType = 17
packetTypeSymmetricallyEncryptedIntegrityProtected packetType = 18
packetTypeAEADEncrypted packetType = 20
packetPadding packetType = 21
)
// EncryptedDataPacket holds encrypted data. It is currently implemented by
// SymmetricallyEncrypted and AEADEncrypted.
type EncryptedDataPacket interface {
Decrypt(CipherFunction, []byte) (io.ReadCloser, error)
}
// Read reads a single OpenPGP packet from the given io.Reader. If there is an
// error parsing a packet, the whole packet is consumed from the input.
func Read(r io.Reader) (p Packet, err error) {
tag, len, contents, err := readHeader(r)
if err != nil {
return
}
switch tag {
case packetTypeEncryptedKey:
p = new(EncryptedKey)
case packetTypeSignature:
p = new(Signature)
case packetTypeSymmetricKeyEncrypted:
p = new(SymmetricKeyEncrypted)
case packetTypeOnePassSignature:
p = new(OnePassSignature)
case packetTypePrivateKey, packetTypePrivateSubkey:
pk := new(PrivateKey)
if tag == packetTypePrivateSubkey {
pk.IsSubkey = true
}
p = pk
case packetTypePublicKey, packetTypePublicSubkey:
isSubkey := tag == packetTypePublicSubkey
p = &PublicKey{IsSubkey: isSubkey}
case packetTypeCompressed:
p = new(Compressed)
case packetTypeSymmetricallyEncrypted:
p = new(SymmetricallyEncrypted)
case packetTypeLiteralData:
p = new(LiteralData)
case packetTypeUserId:
p = new(UserId)
case packetTypeUserAttribute:
p = new(UserAttribute)
case packetTypeSymmetricallyEncryptedIntegrityProtected:
se := new(SymmetricallyEncrypted)
se.IntegrityProtected = true
p = se
case packetTypeAEADEncrypted:
p = new(AEADEncrypted)
case packetPadding:
p = Padding(len)
case packetTypeMarker:
p = new(Marker)
case packetTypeTrust:
// Not implemented, just consume
err = errors.UnknownPacketTypeError(tag)
default:
// Packet Tags from 0 to 39 are critical.
// Packet Tags from 40 to 63 are non-critical.
if tag < 40 {
err = errors.CriticalUnknownPacketTypeError(tag)
} else {
err = errors.UnknownPacketTypeError(tag)
}
}
if p != nil {
err = p.parse(contents)
}
if err != nil {
consumeAll(contents)
}
return
}
// ReadWithCheck reads a single OpenPGP message packet from the given io.Reader. If there is an
// error parsing a packet, the whole packet is consumed from the input.
// ReadWithCheck additionally checks if the OpenPGP message packet sequence adheres
// to the packet composition rules in rfc4880, if not throws an error.
func ReadWithCheck(r io.Reader, sequence *SequenceVerifier) (p Packet, msgErr error, err error) {
tag, len, contents, err := readHeader(r)
if err != nil {
return
}
switch tag {
case packetTypeEncryptedKey:
msgErr = sequence.Next(ESKSymbol)
p = new(EncryptedKey)
case packetTypeSignature:
msgErr = sequence.Next(SigSymbol)
p = new(Signature)
case packetTypeSymmetricKeyEncrypted:
msgErr = sequence.Next(ESKSymbol)
p = new(SymmetricKeyEncrypted)
case packetTypeOnePassSignature:
msgErr = sequence.Next(OPSSymbol)
p = new(OnePassSignature)
case packetTypeCompressed:
msgErr = sequence.Next(CompSymbol)
p = new(Compressed)
case packetTypeSymmetricallyEncrypted:
msgErr = sequence.Next(EncSymbol)
p = new(SymmetricallyEncrypted)
case packetTypeLiteralData:
msgErr = sequence.Next(LDSymbol)
p = new(LiteralData)
case packetTypeSymmetricallyEncryptedIntegrityProtected:
msgErr = sequence.Next(EncSymbol)
se := new(SymmetricallyEncrypted)
se.IntegrityProtected = true
p = se
case packetTypeAEADEncrypted:
msgErr = sequence.Next(EncSymbol)
p = new(AEADEncrypted)
case packetPadding:
p = Padding(len)
case packetTypeMarker:
p = new(Marker)
case packetTypeTrust:
// Not implemented, just consume
err = errors.UnknownPacketTypeError(tag)
case packetTypePrivateKey,
packetTypePrivateSubkey,
packetTypePublicKey,
packetTypePublicSubkey,
packetTypeUserId,
packetTypeUserAttribute:
msgErr = sequence.Next(UnknownSymbol)
consumeAll(contents)
default:
// Packet Tags from 0 to 39 are critical.
// Packet Tags from 40 to 63 are non-critical.
if tag < 40 {
err = errors.CriticalUnknownPacketTypeError(tag)
} else {
err = errors.UnknownPacketTypeError(tag)
}
}
if p != nil {
err = p.parse(contents)
}
if err != nil {
consumeAll(contents)
}
return
}
// SignatureType represents the different semantic meanings of an OpenPGP
// signature. See RFC 4880, section 5.2.1.
type SignatureType uint8
const (
SigTypeBinary SignatureType = 0x00
SigTypeText SignatureType = 0x01
SigTypeGenericCert SignatureType = 0x10
SigTypePersonaCert SignatureType = 0x11
SigTypeCasualCert SignatureType = 0x12
SigTypePositiveCert SignatureType = 0x13
SigTypeSubkeyBinding SignatureType = 0x18
SigTypePrimaryKeyBinding SignatureType = 0x19
SigTypeDirectSignature SignatureType = 0x1F
SigTypeKeyRevocation SignatureType = 0x20
SigTypeSubkeyRevocation SignatureType = 0x28
SigTypeCertificationRevocation SignatureType = 0x30
)
// PublicKeyAlgorithm represents the different public key system specified for
// OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-12
type PublicKeyAlgorithm uint8
const (
PubKeyAlgoRSA PublicKeyAlgorithm = 1
PubKeyAlgoElGamal PublicKeyAlgorithm = 16
PubKeyAlgoDSA PublicKeyAlgorithm = 17
// RFC 6637, Section 5.
PubKeyAlgoECDH PublicKeyAlgorithm = 18
PubKeyAlgoECDSA PublicKeyAlgorithm = 19
// https://www.ietf.org/archive/id/draft-koch-eddsa-for-openpgp-04.txt
PubKeyAlgoEdDSA PublicKeyAlgorithm = 22
// https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh
PubKeyAlgoX25519 PublicKeyAlgorithm = 25
PubKeyAlgoX448 PublicKeyAlgorithm = 26
PubKeyAlgoEd25519 PublicKeyAlgorithm = 27
PubKeyAlgoEd448 PublicKeyAlgorithm = 28
// Deprecated in RFC 4880, Section 13.5. Use key flags instead.
PubKeyAlgoRSAEncryptOnly PublicKeyAlgorithm = 2
PubKeyAlgoRSASignOnly PublicKeyAlgorithm = 3
)
// CanEncrypt returns true if it's possible to encrypt a message to a public
// key of the given type.
func (pka PublicKeyAlgorithm) CanEncrypt() bool {
switch pka {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoElGamal, PubKeyAlgoECDH, PubKeyAlgoX25519, PubKeyAlgoX448:
return true
}
return false
}
// CanSign returns true if it's possible for a public key of the given type to
// sign a message.
func (pka PublicKeyAlgorithm) CanSign() bool {
switch pka {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448:
return true
}
return false
}
// CipherFunction represents the different block ciphers specified for OpenPGP. See
// http://www.iana.org/assignments/pgp-parameters/pgp-parameters.xhtml#pgp-parameters-13
type CipherFunction algorithm.CipherFunction
const (
Cipher3DES CipherFunction = 2
CipherCAST5 CipherFunction = 3
CipherAES128 CipherFunction = 7
CipherAES192 CipherFunction = 8
CipherAES256 CipherFunction = 9
)
// KeySize returns the key size, in bytes, of cipher.
func (cipher CipherFunction) KeySize() int {
return algorithm.CipherFunction(cipher).KeySize()
}
// IsSupported returns true if the cipher is supported from the library
func (cipher CipherFunction) IsSupported() bool {
return algorithm.CipherFunction(cipher).KeySize() > 0
}
// blockSize returns the block size, in bytes, of cipher.
func (cipher CipherFunction) blockSize() int {
return algorithm.CipherFunction(cipher).BlockSize()
}
// new returns a fresh instance of the given cipher.
func (cipher CipherFunction) new(key []byte) (block cipher.Block) {
return algorithm.CipherFunction(cipher).New(key)
}
// padToKeySize left-pads a MPI with zeroes to match the length of the
// specified RSA public.
func padToKeySize(pub *rsa.PublicKey, b []byte) []byte {
k := (pub.N.BitLen() + 7) / 8
if len(b) >= k {
return b
}
bb := make([]byte, k)
copy(bb[len(bb)-len(b):], b)
return bb
}
// CompressionAlgo Represents the different compression algorithms
// supported by OpenPGP (except for BZIP2, which is not currently
// supported). See Section 9.3 of RFC 4880.
type CompressionAlgo uint8
const (
CompressionNone CompressionAlgo = 0
CompressionZIP CompressionAlgo = 1
CompressionZLIB CompressionAlgo = 2
)
// AEADMode represents the different Authenticated Encryption with Associated
// Data specified for OpenPGP.
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6
type AEADMode algorithm.AEADMode
const (
AEADModeEAX AEADMode = 1
AEADModeOCB AEADMode = 2
AEADModeGCM AEADMode = 3
)
func (mode AEADMode) IvLength() int {
return algorithm.AEADMode(mode).NonceLength()
}
func (mode AEADMode) TagLength() int {
return algorithm.AEADMode(mode).TagLength()
}
// IsSupported returns true if the aead mode is supported from the library
func (mode AEADMode) IsSupported() bool {
return algorithm.AEADMode(mode).TagLength() > 0
}
// new returns a fresh instance of the given mode.
func (mode AEADMode) new(block cipher.Block) cipher.AEAD {
return algorithm.AEADMode(mode).New(block)
}
// ReasonForRevocation represents a revocation reason code as per RFC4880
// section 5.2.3.23.
type ReasonForRevocation uint8
const (
NoReason ReasonForRevocation = 0
KeySuperseded ReasonForRevocation = 1
KeyCompromised ReasonForRevocation = 2
KeyRetired ReasonForRevocation = 3
UserIDNotValid ReasonForRevocation = 32
Unknown ReasonForRevocation = 200
)
func NewReasonForRevocation(value byte) ReasonForRevocation {
if value < 4 || value == 32 {
return ReasonForRevocation(value)
}
return Unknown
}
// Curve is a mapping to supported ECC curves for key generation.
// See https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-06.html#name-curve-specific-wire-formats
type Curve string
const (
Curve25519 Curve = "Curve25519"
Curve448 Curve = "Curve448"
CurveNistP256 Curve = "P256"
CurveNistP384 Curve = "P384"
CurveNistP521 Curve = "P521"
CurveSecP256k1 Curve = "SecP256k1"
CurveBrainpoolP256 Curve = "BrainpoolP256"
CurveBrainpoolP384 Curve = "BrainpoolP384"
CurveBrainpoolP512 Curve = "BrainpoolP512"
)
// TrustLevel represents a trust level per RFC4880 5.2.3.13
type TrustLevel uint8
// TrustAmount represents a trust amount per RFC4880 5.2.3.13
type TrustAmount uint8
const (
// versionSize is the length in bytes of the version value.
versionSize = 1
// algorithmSize is the length in bytes of the key algorithm value.
algorithmSize = 1
// keyVersionSize is the length in bytes of the key version value
keyVersionSize = 1
// keyIdSize is the length in bytes of the key identifier value.
keyIdSize = 8
// timestampSize is the length in bytes of encoded timestamps.
timestampSize = 4
// fingerprintSizeV6 is the length in bytes of the key fingerprint in v6.
fingerprintSizeV6 = 32
// fingerprintSize is the length in bytes of the key fingerprint.
fingerprintSize = 20
)
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_sequence.go
================================================
package packet
// This file implements the pushdown automata (PDA) from PGPainless (Paul Schaub)
// to verify pgp packet sequences. See Paul's blogpost for more details:
// https://blog.jabberhead.tk/2022/10/26/implementing-packet-sequence-validation-using-pushdown-automata/
import (
"fmt"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
func NewErrMalformedMessage(from State, input InputSymbol, stackSymbol StackSymbol) errors.ErrMalformedMessage {
return errors.ErrMalformedMessage(fmt.Sprintf("state %d, input symbol %d, stack symbol %d ", from, input, stackSymbol))
}
// InputSymbol defines the input alphabet of the PDA
type InputSymbol uint8
const (
LDSymbol InputSymbol = iota
SigSymbol
OPSSymbol
CompSymbol
ESKSymbol
EncSymbol
EOSSymbol
UnknownSymbol
)
// StackSymbol defines the stack alphabet of the PDA
type StackSymbol int8
const (
MsgStackSymbol StackSymbol = iota
OpsStackSymbol
KeyStackSymbol
EndStackSymbol
EmptyStackSymbol
)
// State defines the states of the PDA
type State int8
const (
OpenPGPMessage State = iota
ESKMessage
LiteralMessage
CompressedMessage
EncryptedMessage
ValidMessage
)
// transition represents a state transition in the PDA
type transition func(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error)
// SequenceVerifier is a pushdown automata to verify
// PGP messages packet sequences according to rfc4880.
type SequenceVerifier struct {
stack []StackSymbol
state State
}
// Next performs a state transition with the given input symbol.
// If the transition fails a ErrMalformedMessage is returned.
func (sv *SequenceVerifier) Next(input InputSymbol) error {
for {
stackSymbol := sv.popStack()
transitionFunc := getTransition(sv.state)
nextState, newStackSymbols, redo, err := transitionFunc(input, stackSymbol)
if err != nil {
return err
}
if redo {
sv.pushStack(stackSymbol)
}
for _, newStackSymbol := range newStackSymbols {
sv.pushStack(newStackSymbol)
}
sv.state = nextState
if !redo {
break
}
}
return nil
}
// Valid returns true if RDA is in a valid state.
func (sv *SequenceVerifier) Valid() bool {
return sv.state == ValidMessage && len(sv.stack) == 0
}
func (sv *SequenceVerifier) AssertValid() error {
if !sv.Valid() {
return errors.ErrMalformedMessage("invalid message")
}
return nil
}
func NewSequenceVerifier() *SequenceVerifier {
return &SequenceVerifier{
stack: []StackSymbol{EndStackSymbol, MsgStackSymbol},
state: OpenPGPMessage,
}
}
func (sv *SequenceVerifier) popStack() StackSymbol {
if len(sv.stack) == 0 {
return EmptyStackSymbol
}
elemIndex := len(sv.stack) - 1
stackSymbol := sv.stack[elemIndex]
sv.stack = sv.stack[:elemIndex]
return stackSymbol
}
func (sv *SequenceVerifier) pushStack(stackSymbol StackSymbol) {
sv.stack = append(sv.stack, stackSymbol)
}
func getTransition(from State) transition {
switch from {
case OpenPGPMessage:
return fromOpenPGPMessage
case LiteralMessage:
return fromLiteralMessage
case CompressedMessage:
return fromCompressedMessage
case EncryptedMessage:
return fromEncryptedMessage
case ESKMessage:
return fromESKMessage
case ValidMessage:
return fromValidMessage
}
return nil
}
// fromOpenPGPMessage is the transition for the state OpenPGPMessage.
func fromOpenPGPMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
if stackSymbol != MsgStackSymbol {
return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
}
switch input {
case LDSymbol:
return LiteralMessage, nil, false, nil
case SigSymbol:
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, false, nil
case OPSSymbol:
return OpenPGPMessage, []StackSymbol{OpsStackSymbol, MsgStackSymbol}, false, nil
case CompSymbol:
return CompressedMessage, nil, false, nil
case ESKSymbol:
return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
case EncSymbol:
return EncryptedMessage, nil, false, nil
}
return 0, nil, false, NewErrMalformedMessage(OpenPGPMessage, input, stackSymbol)
}
// fromESKMessage is the transition for the state ESKMessage.
func fromESKMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
if stackSymbol != KeyStackSymbol {
return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
}
switch input {
case ESKSymbol:
return ESKMessage, []StackSymbol{KeyStackSymbol}, false, nil
case EncSymbol:
return EncryptedMessage, nil, false, nil
}
return 0, nil, false, NewErrMalformedMessage(ESKMessage, input, stackSymbol)
}
// fromLiteralMessage is the transition for the state LiteralMessage.
func fromLiteralMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
switch input {
case SigSymbol:
if stackSymbol == OpsStackSymbol {
return LiteralMessage, nil, false, nil
}
case EOSSymbol:
if stackSymbol == EndStackSymbol {
return ValidMessage, nil, false, nil
}
}
return 0, nil, false, NewErrMalformedMessage(LiteralMessage, input, stackSymbol)
}
// fromLiteralMessage is the transition for the state CompressedMessage.
func fromCompressedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
switch input {
case SigSymbol:
if stackSymbol == OpsStackSymbol {
return CompressedMessage, nil, false, nil
}
case EOSSymbol:
if stackSymbol == EndStackSymbol {
return ValidMessage, nil, false, nil
}
}
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
}
// fromEncryptedMessage is the transition for the state EncryptedMessage.
func fromEncryptedMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
switch input {
case SigSymbol:
if stackSymbol == OpsStackSymbol {
return EncryptedMessage, nil, false, nil
}
case EOSSymbol:
if stackSymbol == EndStackSymbol {
return ValidMessage, nil, false, nil
}
}
return OpenPGPMessage, []StackSymbol{MsgStackSymbol}, true, nil
}
// fromValidMessage is the transition for the state ValidMessage.
func fromValidMessage(input InputSymbol, stackSymbol StackSymbol) (State, []StackSymbol, bool, error) {
return 0, nil, false, NewErrMalformedMessage(ValidMessage, input, stackSymbol)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/packet_unsupported.go
================================================
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// UnsupportedPackage represents a OpenPGP packet with a known packet type
// but with unsupported content.
type UnsupportedPacket struct {
IncompletePacket Packet
Error errors.UnsupportedError
}
// Implements the Packet interface
func (up *UnsupportedPacket) parse(read io.Reader) error {
err := up.IncompletePacket.parse(read)
if castedErr, ok := err.(errors.UnsupportedError); ok {
up.Error = castedErr
return nil
}
return err
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/padding.go
================================================
package packet
import (
"io"
)
// Padding type represents a Padding Packet (Tag 21).
// The padding type is represented by the length of its padding.
// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-padding-packet-tag-21
type Padding int
// parse just ignores the padding content.
func (pad Padding) parse(reader io.Reader) error {
_, err := io.CopyN(io.Discard, reader, int64(pad))
return err
}
// SerializePadding writes the padding to writer.
func (pad Padding) SerializePadding(writer io.Writer, rand io.Reader) error {
err := serializeHeader(writer, packetPadding, int(pad))
if err != nil {
return err
}
_, err = io.CopyN(writer, rand, int64(pad))
return err
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"crypto"
"crypto/cipher"
"crypto/dsa"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/subtle"
"fmt"
"io"
"math/big"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/ed25519"
"github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
"github.com/ProtonMail/go-crypto/openpgp/x25519"
"github.com/ProtonMail/go-crypto/openpgp/x448"
"golang.org/x/crypto/hkdf"
)
// PrivateKey represents a possibly encrypted private key. See RFC 4880,
// section 5.5.3.
type PrivateKey struct {
PublicKey
Encrypted bool // if true then the private key is unavailable until Decrypt has been called.
encryptedData []byte
cipher CipherFunction
s2k func(out, in []byte)
aead AEADMode // only relevant if S2KAEAD is enabled
// An *{rsa|dsa|elgamal|ecdh|ecdsa|ed25519|ed448}.PrivateKey or
// crypto.Signer/crypto.Decrypter (Decryptor RSA only).
PrivateKey interface{}
iv []byte
// Type of encryption of the S2K packet
// Allowed values are 0 (Not encrypted), 253 (AEAD), 254 (SHA1), or
// 255 (2-byte checksum)
s2kType S2KType
// Full parameters of the S2K packet
s2kParams *s2k.Params
}
// S2KType s2k packet type
type S2KType uint8
const (
// S2KNON unencrypt
S2KNON S2KType = 0
// S2KAEAD use authenticated encryption
S2KAEAD S2KType = 253
// S2KSHA1 sha1 sum check
S2KSHA1 S2KType = 254
// S2KCHECKSUM sum check
S2KCHECKSUM S2KType = 255
)
func NewRSAPrivateKey(creationTime time.Time, priv *rsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewDSAPrivateKey(creationTime time.Time, priv *dsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewDSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewElGamalPrivateKey(creationTime time.Time, priv *elgamal.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewECDSAPrivateKey(creationTime time.Time, priv *ecdsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewECDSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewEdDSAPrivateKey(creationTime time.Time, priv *eddsa.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewECDHPrivateKey(creationTime time.Time, priv *ecdh.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewX25519PrivateKey(creationTime time.Time, priv *x25519.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewX448PrivateKey(creationTime time.Time, priv *x448.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewEd25519PrivateKey(creationTime time.Time, priv *ed25519.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewEd25519PublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
func NewEd448PrivateKey(creationTime time.Time, priv *ed448.PrivateKey) *PrivateKey {
pk := new(PrivateKey)
pk.PublicKey = *NewEd448PublicKey(creationTime, &priv.PublicKey)
pk.PrivateKey = priv
return pk
}
// NewSignerPrivateKey creates a PrivateKey from a crypto.Signer that
// implements RSA, ECDSA or EdDSA.
func NewSignerPrivateKey(creationTime time.Time, signer interface{}) *PrivateKey {
pk := new(PrivateKey)
// In general, the public Keys should be used as pointers. We still
// type-switch on the values, for backwards-compatibility.
switch pubkey := signer.(type) {
case *rsa.PrivateKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey)
case rsa.PrivateKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, &pubkey.PublicKey)
case *ecdsa.PrivateKey:
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey)
case ecdsa.PrivateKey:
pk.PublicKey = *NewECDSAPublicKey(creationTime, &pubkey.PublicKey)
case *eddsa.PrivateKey:
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
case eddsa.PrivateKey:
pk.PublicKey = *NewEdDSAPublicKey(creationTime, &pubkey.PublicKey)
case *ed25519.PrivateKey:
pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
case ed25519.PrivateKey:
pk.PublicKey = *NewEd25519PublicKey(creationTime, &pubkey.PublicKey)
case *ed448.PrivateKey:
pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
case ed448.PrivateKey:
pk.PublicKey = *NewEd448PublicKey(creationTime, &pubkey.PublicKey)
default:
panic("openpgp: unknown signer type in NewSignerPrivateKey")
}
pk.PrivateKey = signer
return pk
}
// NewDecrypterPrivateKey creates a PrivateKey from a *{rsa|elgamal|ecdh|x25519|x448}.PrivateKey.
func NewDecrypterPrivateKey(creationTime time.Time, decrypter interface{}) *PrivateKey {
pk := new(PrivateKey)
switch priv := decrypter.(type) {
case *rsa.PrivateKey:
pk.PublicKey = *NewRSAPublicKey(creationTime, &priv.PublicKey)
case *elgamal.PrivateKey:
pk.PublicKey = *NewElGamalPublicKey(creationTime, &priv.PublicKey)
case *ecdh.PrivateKey:
pk.PublicKey = *NewECDHPublicKey(creationTime, &priv.PublicKey)
case *x25519.PrivateKey:
pk.PublicKey = *NewX25519PublicKey(creationTime, &priv.PublicKey)
case *x448.PrivateKey:
pk.PublicKey = *NewX448PublicKey(creationTime, &priv.PublicKey)
default:
panic("openpgp: unknown decrypter type in NewDecrypterPrivateKey")
}
pk.PrivateKey = decrypter
return pk
}
func (pk *PrivateKey) parse(r io.Reader) (err error) {
err = (&pk.PublicKey).parse(r)
if err != nil {
return
}
v5 := pk.PublicKey.Version == 5
v6 := pk.PublicKey.Version == 6
if V5Disabled && v5 {
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
}
var buf [1]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
pk.s2kType = S2KType(buf[0])
var optCount [1]byte
if v5 || (v6 && pk.s2kType != S2KNON) {
if _, err = readFull(r, optCount[:]); err != nil {
return
}
}
switch pk.s2kType {
case S2KNON:
pk.s2k = nil
pk.Encrypted = false
case S2KSHA1, S2KCHECKSUM, S2KAEAD:
if (v5 || v6) && pk.s2kType == S2KCHECKSUM {
return errors.StructuralError(fmt.Sprintf("wrong s2k identifier for version %d", pk.Version))
}
_, err = readFull(r, buf[:])
if err != nil {
return
}
pk.cipher = CipherFunction(buf[0])
if pk.cipher != 0 && !pk.cipher.IsSupported() {
return errors.UnsupportedError("unsupported cipher function in private key")
}
// [Optional] If string-to-key usage octet was 253,
// a one-octet AEAD algorithm.
if pk.s2kType == S2KAEAD {
_, err = readFull(r, buf[:])
if err != nil {
return
}
pk.aead = AEADMode(buf[0])
if !pk.aead.IsSupported() {
return errors.UnsupportedError("unsupported aead mode in private key")
}
}
// [Optional] Only for a version 6 packet,
// and if string-to-key usage octet was 255, 254, or 253,
// an one-octet count of the following field.
if v6 {
_, err = readFull(r, buf[:])
if err != nil {
return
}
}
pk.s2kParams, err = s2k.ParseIntoParams(r)
if err != nil {
return
}
if pk.s2kParams.Dummy() {
return
}
if pk.s2kParams.Mode() == s2k.Argon2S2K && pk.s2kType != S2KAEAD {
return errors.StructuralError("using Argon2 S2K without AEAD is not allowed")
}
if pk.s2kParams.Mode() == s2k.SimpleS2K && pk.Version == 6 {
return errors.StructuralError("using Simple S2K with version 6 keys is not allowed")
}
pk.s2k, err = pk.s2kParams.Function()
if err != nil {
return
}
pk.Encrypted = true
default:
return errors.UnsupportedError("deprecated s2k function in private key")
}
if pk.Encrypted {
var ivSize int
// If the S2K usage octet was 253, the IV is of the size expected by the AEAD mode,
// unless it's a version 5 key, in which case it's the size of the symmetric cipher's block size.
// For all other S2K modes, it's always the block size.
if !v5 && pk.s2kType == S2KAEAD {
ivSize = pk.aead.IvLength()
} else {
ivSize = pk.cipher.blockSize()
}
if ivSize == 0 {
return errors.UnsupportedError("unsupported cipher in private key: " + strconv.Itoa(int(pk.cipher)))
}
pk.iv = make([]byte, ivSize)
_, err = readFull(r, pk.iv)
if err != nil {
return
}
if v5 && pk.s2kType == S2KAEAD {
pk.iv = pk.iv[:pk.aead.IvLength()]
}
}
var privateKeyData []byte
if v5 {
var n [4]byte /* secret material four octet count */
_, err = readFull(r, n[:])
if err != nil {
return
}
count := uint32(uint32(n[0])<<24 | uint32(n[1])<<16 | uint32(n[2])<<8 | uint32(n[3]))
if !pk.Encrypted {
count = count + 2 /* two octet checksum */
}
privateKeyData = make([]byte, count)
_, err = readFull(r, privateKeyData)
if err != nil {
return
}
} else {
privateKeyData, err = io.ReadAll(r)
if err != nil {
return
}
}
if !pk.Encrypted {
if len(privateKeyData) < 2 {
return errors.StructuralError("truncated private key data")
}
if pk.Version != 6 {
// checksum
var sum uint16
for i := 0; i < len(privateKeyData)-2; i++ {
sum += uint16(privateKeyData[i])
}
if privateKeyData[len(privateKeyData)-2] != uint8(sum>>8) ||
privateKeyData[len(privateKeyData)-1] != uint8(sum) {
return errors.StructuralError("private key checksum failure")
}
privateKeyData = privateKeyData[:len(privateKeyData)-2]
return pk.parsePrivateKey(privateKeyData)
} else {
// No checksum
return pk.parsePrivateKey(privateKeyData)
}
}
pk.encryptedData = privateKeyData
return
}
// Dummy returns true if the private key is a dummy key. This is a GNU extension.
func (pk *PrivateKey) Dummy() bool {
return pk.s2kParams.Dummy()
}
func mod64kHash(d []byte) uint16 {
var h uint16
for _, b := range d {
h += uint16(b)
}
return h
}
func (pk *PrivateKey) Serialize(w io.Writer) (err error) {
contents := bytes.NewBuffer(nil)
err = pk.PublicKey.serializeWithoutHeaders(contents)
if err != nil {
return
}
if _, err = contents.Write([]byte{uint8(pk.s2kType)}); err != nil {
return
}
optional := bytes.NewBuffer(nil)
if pk.Encrypted || pk.Dummy() {
// [Optional] If string-to-key usage octet was 255, 254, or 253,
// a one-octet symmetric encryption algorithm.
if _, err = optional.Write([]byte{uint8(pk.cipher)}); err != nil {
return
}
// [Optional] If string-to-key usage octet was 253,
// a one-octet AEAD algorithm.
if pk.s2kType == S2KAEAD {
if _, err = optional.Write([]byte{uint8(pk.aead)}); err != nil {
return
}
}
s2kBuffer := bytes.NewBuffer(nil)
if err := pk.s2kParams.Serialize(s2kBuffer); err != nil {
return err
}
// [Optional] Only for a version 6 packet, and if string-to-key
// usage octet was 255, 254, or 253, an one-octet
// count of the following field.
if pk.Version == 6 {
if _, err = optional.Write([]byte{uint8(s2kBuffer.Len())}); err != nil {
return
}
}
// [Optional] If string-to-key usage octet was 255, 254, or 253,
// a string-to-key (S2K) specifier. The length of the string-to-key specifier
// depends on its type
if _, err = io.Copy(optional, s2kBuffer); err != nil {
return
}
// IV
if pk.Encrypted {
if _, err = optional.Write(pk.iv); err != nil {
return
}
if pk.Version == 5 && pk.s2kType == S2KAEAD {
// Add padding for version 5
padding := make([]byte, pk.cipher.blockSize()-len(pk.iv))
if _, err = optional.Write(padding); err != nil {
return
}
}
}
}
if pk.Version == 5 || (pk.Version == 6 && pk.s2kType != S2KNON) {
contents.Write([]byte{uint8(optional.Len())})
}
if _, err := io.Copy(contents, optional); err != nil {
return err
}
if !pk.Dummy() {
l := 0
var priv []byte
if !pk.Encrypted {
buf := bytes.NewBuffer(nil)
err = pk.serializePrivateKey(buf)
if err != nil {
return err
}
l = buf.Len()
if pk.Version != 6 {
checksum := mod64kHash(buf.Bytes())
buf.Write([]byte{byte(checksum >> 8), byte(checksum)})
}
priv = buf.Bytes()
} else {
priv, l = pk.encryptedData, len(pk.encryptedData)
}
if pk.Version == 5 {
contents.Write([]byte{byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l)})
}
contents.Write(priv)
}
ptype := packetTypePrivateKey
if pk.IsSubkey {
ptype = packetTypePrivateSubkey
}
err = serializeHeader(w, ptype, contents.Len())
if err != nil {
return
}
_, err = io.Copy(w, contents)
if err != nil {
return
}
return
}
func serializeRSAPrivateKey(w io.Writer, priv *rsa.PrivateKey) error {
if _, err := w.Write(new(encoding.MPI).SetBig(priv.D).EncodedBytes()); err != nil {
return err
}
if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[1]).EncodedBytes()); err != nil {
return err
}
if _, err := w.Write(new(encoding.MPI).SetBig(priv.Primes[0]).EncodedBytes()); err != nil {
return err
}
_, err := w.Write(new(encoding.MPI).SetBig(priv.Precomputed.Qinv).EncodedBytes())
return err
}
func serializeDSAPrivateKey(w io.Writer, priv *dsa.PrivateKey) error {
_, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes())
return err
}
func serializeElGamalPrivateKey(w io.Writer, priv *elgamal.PrivateKey) error {
_, err := w.Write(new(encoding.MPI).SetBig(priv.X).EncodedBytes())
return err
}
func serializeECDSAPrivateKey(w io.Writer, priv *ecdsa.PrivateKey) error {
_, err := w.Write(encoding.NewMPI(priv.MarshalIntegerSecret()).EncodedBytes())
return err
}
func serializeEdDSAPrivateKey(w io.Writer, priv *eddsa.PrivateKey) error {
_, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes())
return err
}
func serializeECDHPrivateKey(w io.Writer, priv *ecdh.PrivateKey) error {
_, err := w.Write(encoding.NewMPI(priv.MarshalByteSecret()).EncodedBytes())
return err
}
func serializeX25519PrivateKey(w io.Writer, priv *x25519.PrivateKey) error {
_, err := w.Write(priv.Secret)
return err
}
func serializeX448PrivateKey(w io.Writer, priv *x448.PrivateKey) error {
_, err := w.Write(priv.Secret)
return err
}
func serializeEd25519PrivateKey(w io.Writer, priv *ed25519.PrivateKey) error {
_, err := w.Write(priv.MarshalByteSecret())
return err
}
func serializeEd448PrivateKey(w io.Writer, priv *ed448.PrivateKey) error {
_, err := w.Write(priv.MarshalByteSecret())
return err
}
// decrypt decrypts an encrypted private key using a decryption key.
func (pk *PrivateKey) decrypt(decryptionKey []byte) error {
if pk.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
if !pk.Encrypted {
return nil
}
block := pk.cipher.new(decryptionKey)
var data []byte
switch pk.s2kType {
case S2KAEAD:
aead := pk.aead.new(block)
additionalData, err := pk.additionalData()
if err != nil {
return err
}
// Decrypt the encrypted key material with aead
data, err = aead.Open(nil, pk.iv, pk.encryptedData, additionalData)
if err != nil {
return err
}
case S2KSHA1, S2KCHECKSUM:
cfb := cipher.NewCFBDecrypter(block, pk.iv)
data = make([]byte, len(pk.encryptedData))
cfb.XORKeyStream(data, pk.encryptedData)
if pk.s2kType == S2KSHA1 {
if len(data) < sha1.Size {
return errors.StructuralError("truncated private key data")
}
h := sha1.New()
h.Write(data[:len(data)-sha1.Size])
sum := h.Sum(nil)
if !bytes.Equal(sum, data[len(data)-sha1.Size:]) {
return errors.StructuralError("private key checksum failure")
}
data = data[:len(data)-sha1.Size]
} else {
if len(data) < 2 {
return errors.StructuralError("truncated private key data")
}
var sum uint16
for i := 0; i < len(data)-2; i++ {
sum += uint16(data[i])
}
if data[len(data)-2] != uint8(sum>>8) ||
data[len(data)-1] != uint8(sum) {
return errors.StructuralError("private key checksum failure")
}
data = data[:len(data)-2]
}
default:
return errors.InvalidArgumentError("invalid s2k type")
}
err := pk.parsePrivateKey(data)
if _, ok := err.(errors.KeyInvalidError); ok {
return errors.KeyInvalidError("invalid key parameters")
}
if err != nil {
return err
}
// Mark key as unencrypted
pk.s2kType = S2KNON
pk.s2k = nil
pk.Encrypted = false
pk.encryptedData = nil
return nil
}
func (pk *PrivateKey) decryptWithCache(passphrase []byte, keyCache *s2k.Cache) error {
if pk.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
if !pk.Encrypted {
return nil
}
key, err := keyCache.GetOrComputeDerivedKey(passphrase, pk.s2kParams, pk.cipher.KeySize())
if err != nil {
return err
}
if pk.s2kType == S2KAEAD {
key = pk.applyHKDF(key)
}
return pk.decrypt(key)
}
// Decrypt decrypts an encrypted private key using a passphrase.
func (pk *PrivateKey) Decrypt(passphrase []byte) error {
if pk.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
if !pk.Encrypted {
return nil
}
key := make([]byte, pk.cipher.KeySize())
pk.s2k(key, passphrase)
if pk.s2kType == S2KAEAD {
key = pk.applyHKDF(key)
}
return pk.decrypt(key)
}
// DecryptPrivateKeys decrypts all encrypted keys with the given config and passphrase.
// Avoids recomputation of similar s2k key derivations.
func DecryptPrivateKeys(keys []*PrivateKey, passphrase []byte) error {
// Create a cache to avoid recomputation of key derviations for the same passphrase.
s2kCache := &s2k.Cache{}
for _, key := range keys {
if key != nil && !key.Dummy() && key.Encrypted {
err := key.decryptWithCache(passphrase, s2kCache)
if err != nil {
return err
}
}
}
return nil
}
// encrypt encrypts an unencrypted private key.
func (pk *PrivateKey) encrypt(key []byte, params *s2k.Params, s2kType S2KType, cipherFunction CipherFunction, rand io.Reader) error {
if pk.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
if pk.Encrypted {
return nil
}
// check if encryptionKey has the correct size
if len(key) != cipherFunction.KeySize() {
return errors.InvalidArgumentError("supplied encryption key has the wrong size")
}
if params.Mode() == s2k.Argon2S2K && s2kType != S2KAEAD {
return errors.InvalidArgumentError("using Argon2 S2K without AEAD is not allowed")
}
if params.Mode() != s2k.Argon2S2K && params.Mode() != s2k.IteratedSaltedS2K &&
params.Mode() != s2k.SaltedS2K { // only allowed for high-entropy passphrases
return errors.InvalidArgumentError("insecure S2K mode")
}
priv := bytes.NewBuffer(nil)
err := pk.serializePrivateKey(priv)
if err != nil {
return err
}
pk.cipher = cipherFunction
pk.s2kParams = params
pk.s2k, err = pk.s2kParams.Function()
if err != nil {
return err
}
privateKeyBytes := priv.Bytes()
pk.s2kType = s2kType
block := pk.cipher.new(key)
switch s2kType {
case S2KAEAD:
if pk.aead == 0 {
return errors.StructuralError("aead mode is not set on key")
}
aead := pk.aead.new(block)
additionalData, err := pk.additionalData()
if err != nil {
return err
}
pk.iv = make([]byte, aead.NonceSize())
_, err = io.ReadFull(rand, pk.iv)
if err != nil {
return err
}
// Decrypt the encrypted key material with aead
pk.encryptedData = aead.Seal(nil, pk.iv, privateKeyBytes, additionalData)
case S2KSHA1, S2KCHECKSUM:
pk.iv = make([]byte, pk.cipher.blockSize())
_, err = io.ReadFull(rand, pk.iv)
if err != nil {
return err
}
cfb := cipher.NewCFBEncrypter(block, pk.iv)
if s2kType == S2KSHA1 {
h := sha1.New()
h.Write(privateKeyBytes)
sum := h.Sum(nil)
privateKeyBytes = append(privateKeyBytes, sum...)
} else {
var sum uint16
for _, b := range privateKeyBytes {
sum += uint16(b)
}
privateKeyBytes = append(privateKeyBytes, []byte{uint8(sum >> 8), uint8(sum)}...)
}
pk.encryptedData = make([]byte, len(privateKeyBytes))
cfb.XORKeyStream(pk.encryptedData, privateKeyBytes)
default:
return errors.InvalidArgumentError("invalid s2k type for encryption")
}
pk.Encrypted = true
pk.PrivateKey = nil
return err
}
// EncryptWithConfig encrypts an unencrypted private key using the passphrase and the config.
func (pk *PrivateKey) EncryptWithConfig(passphrase []byte, config *Config) error {
params, err := s2k.Generate(config.Random(), config.S2K())
if err != nil {
return err
}
// Derive an encryption key with the configured s2k function.
key := make([]byte, config.Cipher().KeySize())
s2k, err := params.Function()
if err != nil {
return err
}
s2k(key, passphrase)
s2kType := S2KSHA1
if config.AEAD() != nil {
s2kType = S2KAEAD
pk.aead = config.AEAD().Mode()
pk.cipher = config.Cipher()
key = pk.applyHKDF(key)
}
// Encrypt the private key with the derived encryption key.
return pk.encrypt(key, params, s2kType, config.Cipher(), config.Random())
}
// EncryptPrivateKeys encrypts all unencrypted keys with the given config and passphrase.
// Only derives one key from the passphrase, which is then used to encrypt each key.
func EncryptPrivateKeys(keys []*PrivateKey, passphrase []byte, config *Config) error {
params, err := s2k.Generate(config.Random(), config.S2K())
if err != nil {
return err
}
// Derive an encryption key with the configured s2k function.
encryptionKey := make([]byte, config.Cipher().KeySize())
s2k, err := params.Function()
if err != nil {
return err
}
s2k(encryptionKey, passphrase)
for _, key := range keys {
if key != nil && !key.Dummy() && !key.Encrypted {
s2kType := S2KSHA1
if config.AEAD() != nil {
s2kType = S2KAEAD
key.aead = config.AEAD().Mode()
key.cipher = config.Cipher()
derivedKey := key.applyHKDF(encryptionKey)
err = key.encrypt(derivedKey, params, s2kType, config.Cipher(), config.Random())
} else {
err = key.encrypt(encryptionKey, params, s2kType, config.Cipher(), config.Random())
}
if err != nil {
return err
}
}
}
return nil
}
// Encrypt encrypts an unencrypted private key using a passphrase.
func (pk *PrivateKey) Encrypt(passphrase []byte) error {
// Default config of private key encryption
config := &Config{
S2KConfig: &s2k.Config{
S2KMode: s2k.IteratedSaltedS2K,
S2KCount: 65536,
Hash: crypto.SHA256,
},
DefaultCipher: CipherAES256,
}
return pk.EncryptWithConfig(passphrase, config)
}
func (pk *PrivateKey) serializePrivateKey(w io.Writer) (err error) {
switch priv := pk.PrivateKey.(type) {
case *rsa.PrivateKey:
err = serializeRSAPrivateKey(w, priv)
case *dsa.PrivateKey:
err = serializeDSAPrivateKey(w, priv)
case *elgamal.PrivateKey:
err = serializeElGamalPrivateKey(w, priv)
case *ecdsa.PrivateKey:
err = serializeECDSAPrivateKey(w, priv)
case *eddsa.PrivateKey:
err = serializeEdDSAPrivateKey(w, priv)
case *ecdh.PrivateKey:
err = serializeECDHPrivateKey(w, priv)
case *x25519.PrivateKey:
err = serializeX25519PrivateKey(w, priv)
case *x448.PrivateKey:
err = serializeX448PrivateKey(w, priv)
case *ed25519.PrivateKey:
err = serializeEd25519PrivateKey(w, priv)
case *ed448.PrivateKey:
err = serializeEd448PrivateKey(w, priv)
default:
err = errors.InvalidArgumentError("unknown private key type")
}
return
}
func (pk *PrivateKey) parsePrivateKey(data []byte) (err error) {
switch pk.PublicKey.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoRSAEncryptOnly:
return pk.parseRSAPrivateKey(data)
case PubKeyAlgoDSA:
return pk.parseDSAPrivateKey(data)
case PubKeyAlgoElGamal:
return pk.parseElGamalPrivateKey(data)
case PubKeyAlgoECDSA:
return pk.parseECDSAPrivateKey(data)
case PubKeyAlgoECDH:
return pk.parseECDHPrivateKey(data)
case PubKeyAlgoEdDSA:
return pk.parseEdDSAPrivateKey(data)
case PubKeyAlgoX25519:
return pk.parseX25519PrivateKey(data)
case PubKeyAlgoX448:
return pk.parseX448PrivateKey(data)
case PubKeyAlgoEd25519:
return pk.parseEd25519PrivateKey(data)
case PubKeyAlgoEd448:
return pk.parseEd448PrivateKey(data)
default:
err = errors.StructuralError("unknown private key type")
return
}
}
func (pk *PrivateKey) parseRSAPrivateKey(data []byte) (err error) {
rsaPub := pk.PublicKey.PublicKey.(*rsa.PublicKey)
rsaPriv := new(rsa.PrivateKey)
rsaPriv.PublicKey = *rsaPub
buf := bytes.NewBuffer(data)
d := new(encoding.MPI)
if _, err := d.ReadFrom(buf); err != nil {
return err
}
p := new(encoding.MPI)
if _, err := p.ReadFrom(buf); err != nil {
return err
}
q := new(encoding.MPI)
if _, err := q.ReadFrom(buf); err != nil {
return err
}
rsaPriv.D = new(big.Int).SetBytes(d.Bytes())
rsaPriv.Primes = make([]*big.Int, 2)
rsaPriv.Primes[0] = new(big.Int).SetBytes(p.Bytes())
rsaPriv.Primes[1] = new(big.Int).SetBytes(q.Bytes())
if err := rsaPriv.Validate(); err != nil {
return errors.KeyInvalidError(err.Error())
}
rsaPriv.Precompute()
pk.PrivateKey = rsaPriv
return nil
}
func (pk *PrivateKey) parseDSAPrivateKey(data []byte) (err error) {
dsaPub := pk.PublicKey.PublicKey.(*dsa.PublicKey)
dsaPriv := new(dsa.PrivateKey)
dsaPriv.PublicKey = *dsaPub
buf := bytes.NewBuffer(data)
x := new(encoding.MPI)
if _, err := x.ReadFrom(buf); err != nil {
return err
}
dsaPriv.X = new(big.Int).SetBytes(x.Bytes())
if err := validateDSAParameters(dsaPriv); err != nil {
return err
}
pk.PrivateKey = dsaPriv
return nil
}
func (pk *PrivateKey) parseElGamalPrivateKey(data []byte) (err error) {
pub := pk.PublicKey.PublicKey.(*elgamal.PublicKey)
priv := new(elgamal.PrivateKey)
priv.PublicKey = *pub
buf := bytes.NewBuffer(data)
x := new(encoding.MPI)
if _, err := x.ReadFrom(buf); err != nil {
return err
}
priv.X = new(big.Int).SetBytes(x.Bytes())
if err := validateElGamalParameters(priv); err != nil {
return err
}
pk.PrivateKey = priv
return nil
}
func (pk *PrivateKey) parseECDSAPrivateKey(data []byte) (err error) {
ecdsaPub := pk.PublicKey.PublicKey.(*ecdsa.PublicKey)
ecdsaPriv := ecdsa.NewPrivateKey(*ecdsaPub)
buf := bytes.NewBuffer(data)
d := new(encoding.MPI)
if _, err := d.ReadFrom(buf); err != nil {
return err
}
if err := ecdsaPriv.UnmarshalIntegerSecret(d.Bytes()); err != nil {
return err
}
if err := ecdsa.Validate(ecdsaPriv); err != nil {
return err
}
pk.PrivateKey = ecdsaPriv
return nil
}
func (pk *PrivateKey) parseECDHPrivateKey(data []byte) (err error) {
ecdhPub := pk.PublicKey.PublicKey.(*ecdh.PublicKey)
ecdhPriv := ecdh.NewPrivateKey(*ecdhPub)
buf := bytes.NewBuffer(data)
d := new(encoding.MPI)
if _, err := d.ReadFrom(buf); err != nil {
return err
}
if err := ecdhPriv.UnmarshalByteSecret(d.Bytes()); err != nil {
return err
}
if err := ecdh.Validate(ecdhPriv); err != nil {
return err
}
pk.PrivateKey = ecdhPriv
return nil
}
func (pk *PrivateKey) parseX25519PrivateKey(data []byte) (err error) {
publicKey := pk.PublicKey.PublicKey.(*x25519.PublicKey)
privateKey := x25519.NewPrivateKey(*publicKey)
privateKey.PublicKey = *publicKey
privateKey.Secret = make([]byte, x25519.KeySize)
if len(data) != x25519.KeySize {
err = errors.StructuralError("wrong x25519 key size")
return err
}
subtle.ConstantTimeCopy(1, privateKey.Secret, data)
if err = x25519.Validate(privateKey); err != nil {
return err
}
pk.PrivateKey = privateKey
return nil
}
func (pk *PrivateKey) parseX448PrivateKey(data []byte) (err error) {
publicKey := pk.PublicKey.PublicKey.(*x448.PublicKey)
privateKey := x448.NewPrivateKey(*publicKey)
privateKey.PublicKey = *publicKey
privateKey.Secret = make([]byte, x448.KeySize)
if len(data) != x448.KeySize {
err = errors.StructuralError("wrong x448 key size")
return err
}
subtle.ConstantTimeCopy(1, privateKey.Secret, data)
if err = x448.Validate(privateKey); err != nil {
return err
}
pk.PrivateKey = privateKey
return nil
}
func (pk *PrivateKey) parseEd25519PrivateKey(data []byte) (err error) {
publicKey := pk.PublicKey.PublicKey.(*ed25519.PublicKey)
privateKey := ed25519.NewPrivateKey(*publicKey)
privateKey.PublicKey = *publicKey
if len(data) != ed25519.SeedSize {
err = errors.StructuralError("wrong ed25519 key size")
return err
}
err = privateKey.UnmarshalByteSecret(data)
if err != nil {
return err
}
err = ed25519.Validate(privateKey)
if err != nil {
return err
}
pk.PrivateKey = privateKey
return nil
}
func (pk *PrivateKey) parseEd448PrivateKey(data []byte) (err error) {
publicKey := pk.PublicKey.PublicKey.(*ed448.PublicKey)
privateKey := ed448.NewPrivateKey(*publicKey)
privateKey.PublicKey = *publicKey
if len(data) != ed448.SeedSize {
err = errors.StructuralError("wrong ed448 key size")
return err
}
err = privateKey.UnmarshalByteSecret(data)
if err != nil {
return err
}
err = ed448.Validate(privateKey)
if err != nil {
return err
}
pk.PrivateKey = privateKey
return nil
}
func (pk *PrivateKey) parseEdDSAPrivateKey(data []byte) (err error) {
eddsaPub := pk.PublicKey.PublicKey.(*eddsa.PublicKey)
eddsaPriv := eddsa.NewPrivateKey(*eddsaPub)
eddsaPriv.PublicKey = *eddsaPub
buf := bytes.NewBuffer(data)
d := new(encoding.MPI)
if _, err := d.ReadFrom(buf); err != nil {
return err
}
if err = eddsaPriv.UnmarshalByteSecret(d.Bytes()); err != nil {
return err
}
if err := eddsa.Validate(eddsaPriv); err != nil {
return err
}
pk.PrivateKey = eddsaPriv
return nil
}
func (pk *PrivateKey) additionalData() ([]byte, error) {
additionalData := bytes.NewBuffer(nil)
// Write additional data prefix based on packet type
var packetByte byte
if pk.PublicKey.IsSubkey {
packetByte = 0xc7
} else {
packetByte = 0xc5
}
// Write public key to additional data
_, err := additionalData.Write([]byte{packetByte})
if err != nil {
return nil, err
}
err = pk.PublicKey.serializeWithoutHeaders(additionalData)
if err != nil {
return nil, err
}
return additionalData.Bytes(), nil
}
func (pk *PrivateKey) applyHKDF(inputKey []byte) []byte {
var packetByte byte
if pk.PublicKey.IsSubkey {
packetByte = 0xc7
} else {
packetByte = 0xc5
}
associatedData := []byte{packetByte, byte(pk.Version), byte(pk.cipher), byte(pk.aead)}
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
encryptionKey := make([]byte, pk.cipher.KeySize())
_, _ = readFull(hkdfReader, encryptionKey)
return encryptionKey
}
func validateDSAParameters(priv *dsa.PrivateKey) error {
p := priv.P // group prime
q := priv.Q // subgroup order
g := priv.G // g has order q mod p
x := priv.X // secret
y := priv.Y // y == g**x mod p
one := big.NewInt(1)
// expect g, y >= 2 and g < p
if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 {
return errors.KeyInvalidError("dsa: invalid group")
}
// expect p > q
if p.Cmp(q) <= 0 {
return errors.KeyInvalidError("dsa: invalid group prime")
}
// q should be large enough and divide p-1
pSub1 := new(big.Int).Sub(p, one)
if q.BitLen() < 150 || new(big.Int).Mod(pSub1, q).Cmp(big.NewInt(0)) != 0 {
return errors.KeyInvalidError("dsa: invalid order")
}
// confirm that g has order q mod p
if !q.ProbablyPrime(32) || new(big.Int).Exp(g, q, p).Cmp(one) != 0 {
return errors.KeyInvalidError("dsa: invalid order")
}
// check y
if new(big.Int).Exp(g, x, p).Cmp(y) != 0 {
return errors.KeyInvalidError("dsa: mismatching values")
}
return nil
}
func validateElGamalParameters(priv *elgamal.PrivateKey) error {
p := priv.P // group prime
g := priv.G // g has order p-1 mod p
x := priv.X // secret
y := priv.Y // y == g**x mod p
one := big.NewInt(1)
// Expect g, y >= 2 and g < p
if g.Cmp(one) <= 0 || y.Cmp(one) <= 0 || g.Cmp(p) > 0 {
return errors.KeyInvalidError("elgamal: invalid group")
}
if p.BitLen() < 1024 {
return errors.KeyInvalidError("elgamal: group order too small")
}
pSub1 := new(big.Int).Sub(p, one)
if new(big.Int).Exp(g, pSub1, p).Cmp(one) != 0 {
return errors.KeyInvalidError("elgamal: invalid group")
}
// Since p-1 is not prime, g might have a smaller order that divides p-1.
// We cannot confirm the exact order of g, but we make sure it is not too small.
gExpI := new(big.Int).Set(g)
i := 1
threshold := 2 << 17 // we want order > threshold
for i < threshold {
i++ // we check every order to make sure key validation is not easily bypassed by guessing y'
gExpI.Mod(new(big.Int).Mul(gExpI, g), p)
if gExpI.Cmp(one) == 0 {
return errors.KeyInvalidError("elgamal: order too small")
}
}
// Check y
if new(big.Int).Exp(g, x, p).Cmp(y) != 0 {
return errors.KeyInvalidError("elgamal: mismatching values")
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/private_key_test_data.go
================================================
package packet
// Generated with `gpg --export-secret-keys "Test Key 2"`
const privKeyRSAHex = "9501fe044cc349a8010400b70ca0010e98c090008d45d1ee8f9113bd5861fd57b88bacb7c68658747663f1e1a3b5a98f32fda6472373c024b97359cd2efc88ff60f77751adfbf6af5e615e6a1408cfad8bf0cea30b0d5f53aa27ad59089ba9b15b7ebc2777a25d7b436144027e3bcd203909f147d0e332b240cf63d3395f5dfe0df0a6c04e8655af7eacdf0011010001fe0303024a252e7d475fd445607de39a265472aa74a9320ba2dac395faa687e9e0336aeb7e9a7397e511b5afd9dc84557c80ac0f3d4d7bfec5ae16f20d41c8c84a04552a33870b930420e230e179564f6d19bb153145e76c33ae993886c388832b0fa042ddda7f133924f3854481533e0ede31d51278c0519b29abc3bf53da673e13e3e1214b52413d179d7f66deee35cac8eacb060f78379d70ef4af8607e68131ff529439668fc39c9ce6dfef8a5ac234d234802cbfb749a26107db26406213ae5c06d4673253a3cbee1fcbae58d6ab77e38d6e2c0e7c6317c48e054edadb5a40d0d48acb44643d998139a8a66bb820be1f3f80185bc777d14b5954b60effe2448a036d565c6bc0b915fcea518acdd20ab07bc1529f561c58cd044f723109b93f6fd99f876ff891d64306b5d08f48bab59f38695e9109c4dec34013ba3153488ce070268381ba923ee1eb77125b36afcb4347ec3478c8f2735b06ef17351d872e577fa95d0c397c88c71b59629a36aec"
// Generated by `gpg --export-secret-keys` followed by a manual extraction of
// the ElGamal subkey from the packets.
const privKeyElGamalHex = "9d0157044df9ee1a100400eb8e136a58ec39b582629cdadf830bc64e0a94ed8103ca8bb247b27b11b46d1d25297ef4bcc3071785ba0c0bedfe89eabc5287fcc0edf81ab5896c1c8e4b20d27d79813c7aede75320b33eaeeaa586edc00fd1036c10133e6ba0ff277245d0d59d04b2b3421b7244aca5f4a8d870c6f1c1fbff9e1c26699a860b9504f35ca1d700030503fd1ededd3b840795be6d9ccbe3c51ee42e2f39233c432b831ddd9c4e72b7025a819317e47bf94f9ee316d7273b05d5fcf2999c3a681f519b1234bbfa6d359b4752bd9c3f77d6b6456cde152464763414ca130f4e91d91041432f90620fec0e6d6b5116076c2985d5aeaae13be492b9b329efcaf7ee25120159a0a30cd976b42d7afe030302dae7eb80db744d4960c4df930d57e87fe81412eaace9f900e6c839817a614ddb75ba6603b9417c33ea7b6c93967dfa2bcff3fa3c74a5ce2c962db65b03aece14c96cbd0038fc"
// pkcs1PrivKeyHex is a PKCS#1, RSA private key.
// Generated by `openssl genrsa 1024 | openssl rsa -outform DER | xxd -p`
const pkcs1PrivKeyHex = "3082025d02010002818100e98edfa1c3b35884a54d0b36a6a603b0290fa85e49e30fa23fc94fef9c6790bc4849928607aa48d809da326fb42a969d06ad756b98b9c1a90f5d4a2b6d0ac05953c97f4da3120164a21a679793ce181c906dc01d235cc085ddcdf6ea06c389b6ab8885dfd685959e693138856a68a7e5db263337ff82a088d583a897cf2d59e9020301000102818100b6d5c9eb70b02d5369b3ee5b520a14490b5bde8a317d36f7e4c74b7460141311d1e5067735f8f01d6f5908b2b96fbd881f7a1ab9a84d82753e39e19e2d36856be960d05ac9ef8e8782ea1b6d65aee28fdfe1d61451e8cff0adfe84322f12cf455028b581cf60eb9e0e140ba5d21aeba6c2634d7c65318b9a665fc01c3191ca21024100fa5e818da3705b0fa33278bb28d4b6f6050388af2d4b75ec9375dd91ccf2e7d7068086a8b82a8f6282e4fbbdb8a7f2622eb97295249d87acea7f5f816f54d347024100eecf9406d7dc49cdfb95ab1eff4064de84c7a30f64b2798936a0d2018ba9eb52e4b636f82e96c49cc63b80b675e91e40d1b2e4017d4b9adaf33ab3d9cf1c214f024100c173704ace742c082323066226a4655226819a85304c542b9dacbeacbf5d1881ee863485fcf6f59f3a604f9b42289282067447f2b13dfeed3eab7851fc81e0550240741fc41f3fc002b382eed8730e33c5d8de40256e4accee846667f536832f711ab1d4590e7db91a8a116ac5bff3be13d3f9243ff2e976662aa9b395d907f8e9c9024046a5696c9ef882363e06c9fa4e2f5b580906452befba03f4a99d0f873697ef1f851d2226ca7934b30b7c3e80cb634a67172bbbf4781735fe3e09263e2dd723e7"
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto/dsa"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
_ "crypto/sha512"
"encoding/binary"
"fmt"
"hash"
"io"
"math/big"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdh"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/ed25519"
"github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/elgamal"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/ecc"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
"github.com/ProtonMail/go-crypto/openpgp/x25519"
"github.com/ProtonMail/go-crypto/openpgp/x448"
)
// PublicKey represents an OpenPGP public key. See RFC 4880, section 5.5.2.
type PublicKey struct {
Version int
CreationTime time.Time
PubKeyAlgo PublicKeyAlgorithm
PublicKey interface{} // *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey or *eddsa.PublicKey, *x25519.PublicKey, *x448.PublicKey, *ed25519.PublicKey, *ed448.PublicKey
Fingerprint []byte
KeyId uint64
IsSubkey bool
// RFC 4880 fields
n, e, p, q, g, y encoding.Field
// RFC 6637 fields
// oid contains the OID byte sequence identifying the elliptic curve used
oid encoding.Field
// kdf stores key derivation function parameters
// used for ECDH encryption. See RFC 6637, Section 9.
kdf encoding.Field
}
// UpgradeToV5 updates the version of the key to v5, and updates all necessary
// fields.
func (pk *PublicKey) UpgradeToV5() {
pk.Version = 5
pk.setFingerprintAndKeyId()
}
// UpgradeToV6 updates the version of the key to v6, and updates all necessary
// fields.
func (pk *PublicKey) UpgradeToV6() error {
pk.Version = 6
pk.setFingerprintAndKeyId()
return pk.checkV6Compatibility()
}
// signingKey provides a convenient abstraction over signature verification
// for v3 and v4 public keys.
type signingKey interface {
SerializeForHash(io.Writer) error
SerializeSignaturePrefix(io.Writer) error
serializeWithoutHeaders(io.Writer) error
}
// NewRSAPublicKey returns a PublicKey that wraps the given rsa.PublicKey.
func NewRSAPublicKey(creationTime time.Time, pub *rsa.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoRSA,
PublicKey: pub,
n: new(encoding.MPI).SetBig(pub.N),
e: new(encoding.MPI).SetBig(big.NewInt(int64(pub.E))),
}
pk.setFingerprintAndKeyId()
return pk
}
// NewDSAPublicKey returns a PublicKey that wraps the given dsa.PublicKey.
func NewDSAPublicKey(creationTime time.Time, pub *dsa.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoDSA,
PublicKey: pub,
p: new(encoding.MPI).SetBig(pub.P),
q: new(encoding.MPI).SetBig(pub.Q),
g: new(encoding.MPI).SetBig(pub.G),
y: new(encoding.MPI).SetBig(pub.Y),
}
pk.setFingerprintAndKeyId()
return pk
}
// NewElGamalPublicKey returns a PublicKey that wraps the given elgamal.PublicKey.
func NewElGamalPublicKey(creationTime time.Time, pub *elgamal.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoElGamal,
PublicKey: pub,
p: new(encoding.MPI).SetBig(pub.P),
g: new(encoding.MPI).SetBig(pub.G),
y: new(encoding.MPI).SetBig(pub.Y),
}
pk.setFingerprintAndKeyId()
return pk
}
func NewECDSAPublicKey(creationTime time.Time, pub *ecdsa.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoECDSA,
PublicKey: pub,
p: encoding.NewMPI(pub.MarshalPoint()),
}
curveInfo := ecc.FindByCurve(pub.GetCurve())
if curveInfo == nil {
panic("unknown elliptic curve")
}
pk.oid = curveInfo.Oid
pk.setFingerprintAndKeyId()
return pk
}
func NewECDHPublicKey(creationTime time.Time, pub *ecdh.PublicKey) *PublicKey {
var pk *PublicKey
var kdf = encoding.NewOID([]byte{0x1, pub.Hash.Id(), pub.Cipher.Id()})
pk = &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoECDH,
PublicKey: pub,
p: encoding.NewMPI(pub.MarshalPoint()),
kdf: kdf,
}
curveInfo := ecc.FindByCurve(pub.GetCurve())
if curveInfo == nil {
panic("unknown elliptic curve")
}
pk.oid = curveInfo.Oid
pk.setFingerprintAndKeyId()
return pk
}
func NewEdDSAPublicKey(creationTime time.Time, pub *eddsa.PublicKey) *PublicKey {
curveInfo := ecc.FindByCurve(pub.GetCurve())
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoEdDSA,
PublicKey: pub,
oid: curveInfo.Oid,
// Native point format, see draft-koch-eddsa-for-openpgp-04, Appendix B
p: encoding.NewMPI(pub.MarshalPoint()),
}
pk.setFingerprintAndKeyId()
return pk
}
func NewX25519PublicKey(creationTime time.Time, pub *x25519.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoX25519,
PublicKey: pub,
}
pk.setFingerprintAndKeyId()
return pk
}
func NewX448PublicKey(creationTime time.Time, pub *x448.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoX448,
PublicKey: pub,
}
pk.setFingerprintAndKeyId()
return pk
}
func NewEd25519PublicKey(creationTime time.Time, pub *ed25519.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoEd25519,
PublicKey: pub,
}
pk.setFingerprintAndKeyId()
return pk
}
func NewEd448PublicKey(creationTime time.Time, pub *ed448.PublicKey) *PublicKey {
pk := &PublicKey{
Version: 4,
CreationTime: creationTime,
PubKeyAlgo: PubKeyAlgoEd448,
PublicKey: pub,
}
pk.setFingerprintAndKeyId()
return pk
}
func (pk *PublicKey) parse(r io.Reader) (err error) {
// RFC 4880, section 5.5.2
var buf [6]byte
_, err = readFull(r, buf[:])
if err != nil {
return
}
pk.Version = int(buf[0])
if pk.Version != 4 && pk.Version != 5 && pk.Version != 6 {
return errors.UnsupportedError("public key version " + strconv.Itoa(int(buf[0])))
}
if V5Disabled && pk.Version == 5 {
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
}
if pk.Version >= 5 {
// Read the four-octet scalar octet count
// The count is not used in this implementation
var n [4]byte
_, err = readFull(r, n[:])
if err != nil {
return
}
}
pk.CreationTime = time.Unix(int64(uint32(buf[1])<<24|uint32(buf[2])<<16|uint32(buf[3])<<8|uint32(buf[4])), 0)
pk.PubKeyAlgo = PublicKeyAlgorithm(buf[5])
// Ignore four-ocet length
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
err = pk.parseRSA(r)
case PubKeyAlgoDSA:
err = pk.parseDSA(r)
case PubKeyAlgoElGamal:
err = pk.parseElGamal(r)
case PubKeyAlgoECDSA:
err = pk.parseECDSA(r)
case PubKeyAlgoECDH:
err = pk.parseECDH(r)
case PubKeyAlgoEdDSA:
err = pk.parseEdDSA(r)
case PubKeyAlgoX25519:
err = pk.parseX25519(r)
case PubKeyAlgoX448:
err = pk.parseX448(r)
case PubKeyAlgoEd25519:
err = pk.parseEd25519(r)
case PubKeyAlgoEd448:
err = pk.parseEd448(r)
default:
err = errors.UnsupportedError("public key type: " + strconv.Itoa(int(pk.PubKeyAlgo)))
}
if err != nil {
return
}
pk.setFingerprintAndKeyId()
return
}
func (pk *PublicKey) setFingerprintAndKeyId() {
// RFC 4880, section 12.2
if pk.Version >= 5 {
fingerprint := sha256.New()
if err := pk.SerializeForHash(fingerprint); err != nil {
// Should not happen for a hash.
panic(err)
}
pk.Fingerprint = make([]byte, 32)
copy(pk.Fingerprint, fingerprint.Sum(nil))
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[:8])
} else {
fingerprint := sha1.New()
if err := pk.SerializeForHash(fingerprint); err != nil {
// Should not happen for a hash.
panic(err)
}
pk.Fingerprint = make([]byte, 20)
copy(pk.Fingerprint, fingerprint.Sum(nil))
pk.KeyId = binary.BigEndian.Uint64(pk.Fingerprint[12:20])
}
}
func (pk *PublicKey) checkV6Compatibility() error {
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
switch pk.PubKeyAlgo {
case PubKeyAlgoECDH:
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
if curveInfo.GenName == ecc.Curve25519GenName {
return errors.StructuralError("cannot generate v6 key with deprecated OID: Curve25519Legacy")
}
case PubKeyAlgoEdDSA:
return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
}
return nil
}
// parseRSA parses RSA public key material from the given Reader. See RFC 4880,
// section 5.5.2.
func (pk *PublicKey) parseRSA(r io.Reader) (err error) {
pk.n = new(encoding.MPI)
if _, err = pk.n.ReadFrom(r); err != nil {
return
}
pk.e = new(encoding.MPI)
if _, err = pk.e.ReadFrom(r); err != nil {
return
}
if len(pk.e.Bytes()) > 3 {
err = errors.UnsupportedError("large public exponent")
return
}
rsa := &rsa.PublicKey{
N: new(big.Int).SetBytes(pk.n.Bytes()),
E: 0,
}
for i := 0; i < len(pk.e.Bytes()); i++ {
rsa.E <<= 8
rsa.E |= int(pk.e.Bytes()[i])
}
pk.PublicKey = rsa
return
}
// parseDSA parses DSA public key material from the given Reader. See RFC 4880,
// section 5.5.2.
func (pk *PublicKey) parseDSA(r io.Reader) (err error) {
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
}
pk.q = new(encoding.MPI)
if _, err = pk.q.ReadFrom(r); err != nil {
return
}
pk.g = new(encoding.MPI)
if _, err = pk.g.ReadFrom(r); err != nil {
return
}
pk.y = new(encoding.MPI)
if _, err = pk.y.ReadFrom(r); err != nil {
return
}
dsa := new(dsa.PublicKey)
dsa.P = new(big.Int).SetBytes(pk.p.Bytes())
dsa.Q = new(big.Int).SetBytes(pk.q.Bytes())
dsa.G = new(big.Int).SetBytes(pk.g.Bytes())
dsa.Y = new(big.Int).SetBytes(pk.y.Bytes())
pk.PublicKey = dsa
return
}
// parseElGamal parses ElGamal public key material from the given Reader. See
// RFC 4880, section 5.5.2.
func (pk *PublicKey) parseElGamal(r io.Reader) (err error) {
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
}
pk.g = new(encoding.MPI)
if _, err = pk.g.ReadFrom(r); err != nil {
return
}
pk.y = new(encoding.MPI)
if _, err = pk.y.ReadFrom(r); err != nil {
return
}
elgamal := new(elgamal.PublicKey)
elgamal.P = new(big.Int).SetBytes(pk.p.Bytes())
elgamal.G = new(big.Int).SetBytes(pk.g.Bytes())
elgamal.Y = new(big.Int).SetBytes(pk.y.Bytes())
pk.PublicKey = elgamal
return
}
// parseECDSA parses ECDSA public key material from the given Reader. See
// RFC 6637, Section 9.
func (pk *PublicKey) parseECDSA(r io.Reader) (err error) {
pk.oid = new(encoding.OID)
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
}
c, ok := curveInfo.Curve.(ecc.ECDSACurve)
if !ok {
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
}
ecdsaKey := ecdsa.NewPublicKey(c)
err = ecdsaKey.UnmarshalPoint(pk.p.Bytes())
pk.PublicKey = ecdsaKey
return
}
// parseECDH parses ECDH public key material from the given Reader. See
// RFC 6637, Section 9.
func (pk *PublicKey) parseECDH(r io.Reader) (err error) {
pk.oid = new(encoding.OID)
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
if pk.Version == 6 && curveInfo.GenName == ecc.Curve25519GenName {
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
return errors.StructuralError("cannot read v6 key with deprecated OID: Curve25519Legacy")
}
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
}
pk.kdf = new(encoding.OID)
if _, err = pk.kdf.ReadFrom(r); err != nil {
return
}
c, ok := curveInfo.Curve.(ecc.ECDHCurve)
if !ok {
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
}
if kdfLen := len(pk.kdf.Bytes()); kdfLen < 3 {
return errors.UnsupportedError("unsupported ECDH KDF length: " + strconv.Itoa(kdfLen))
}
if reserved := pk.kdf.Bytes()[0]; reserved != 0x01 {
return errors.UnsupportedError("unsupported KDF reserved field: " + strconv.Itoa(int(reserved)))
}
kdfHash, ok := algorithm.HashById[pk.kdf.Bytes()[1]]
if !ok {
return errors.UnsupportedError("unsupported ECDH KDF hash: " + strconv.Itoa(int(pk.kdf.Bytes()[1])))
}
kdfCipher, ok := algorithm.CipherById[pk.kdf.Bytes()[2]]
if !ok {
return errors.UnsupportedError("unsupported ECDH KDF cipher: " + strconv.Itoa(int(pk.kdf.Bytes()[2])))
}
ecdhKey := ecdh.NewPublicKey(c, kdfHash, kdfCipher)
err = ecdhKey.UnmarshalPoint(pk.p.Bytes())
pk.PublicKey = ecdhKey
return
}
func (pk *PublicKey) parseEdDSA(r io.Reader) (err error) {
if pk.Version == 6 {
// Implementations MUST NOT accept or generate version 6 key material using the deprecated OIDs.
return errors.StructuralError("cannot generate v6 key with deprecated algorithm: EdDSALegacy")
}
pk.oid = new(encoding.OID)
if _, err = pk.oid.ReadFrom(r); err != nil {
return
}
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
c, ok := curveInfo.Curve.(ecc.EdDSACurve)
if !ok {
return errors.UnsupportedError(fmt.Sprintf("unsupported oid: %x", pk.oid))
}
pk.p = new(encoding.MPI)
if _, err = pk.p.ReadFrom(r); err != nil {
return
}
if len(pk.p.Bytes()) == 0 {
return errors.StructuralError("empty EdDSA public key")
}
pub := eddsa.NewPublicKey(c)
switch flag := pk.p.Bytes()[0]; flag {
case 0x04:
// TODO: see _grcy_ecc_eddsa_ensure_compact in grcypt
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
case 0x40:
err = pub.UnmarshalPoint(pk.p.Bytes())
default:
return errors.UnsupportedError("unsupported EdDSA compression: " + strconv.Itoa(int(flag)))
}
pk.PublicKey = pub
return
}
func (pk *PublicKey) parseX25519(r io.Reader) (err error) {
point := make([]byte, x25519.KeySize)
_, err = io.ReadFull(r, point)
if err != nil {
return
}
pub := &x25519.PublicKey{
Point: point,
}
pk.PublicKey = pub
return
}
func (pk *PublicKey) parseX448(r io.Reader) (err error) {
point := make([]byte, x448.KeySize)
_, err = io.ReadFull(r, point)
if err != nil {
return
}
pub := &x448.PublicKey{
Point: point,
}
pk.PublicKey = pub
return
}
func (pk *PublicKey) parseEd25519(r io.Reader) (err error) {
point := make([]byte, ed25519.PublicKeySize)
_, err = io.ReadFull(r, point)
if err != nil {
return
}
pub := &ed25519.PublicKey{
Point: point,
}
pk.PublicKey = pub
return
}
func (pk *PublicKey) parseEd448(r io.Reader) (err error) {
point := make([]byte, ed448.PublicKeySize)
_, err = io.ReadFull(r, point)
if err != nil {
return
}
pub := &ed448.PublicKey{
Point: point,
}
pk.PublicKey = pub
return
}
// SerializeForHash serializes the PublicKey to w with the special packet
// header format needed for hashing.
func (pk *PublicKey) SerializeForHash(w io.Writer) error {
if err := pk.SerializeSignaturePrefix(w); err != nil {
return err
}
return pk.serializeWithoutHeaders(w)
}
// SerializeSignaturePrefix writes the prefix for this public key to the given Writer.
// The prefix is used when calculating a signature over this public key. See
// RFC 4880, section 5.2.4.
func (pk *PublicKey) SerializeSignaturePrefix(w io.Writer) error {
var pLength = pk.algorithmSpecificByteCount()
// version, timestamp, algorithm
pLength += versionSize + timestampSize + algorithmSize
if pk.Version >= 5 {
// key octet count (4).
pLength += 4
_, err := w.Write([]byte{
// When a v4 signature is made over a key, the hash data starts with the octet 0x99, followed by a two-octet length
// of the key, and then the body of the key packet. When a v6 signature is made over a key, the hash data starts
// with the salt, then octet 0x9B, followed by a four-octet length of the key, and then the body of the key packet.
0x95 + byte(pk.Version),
byte(pLength >> 24),
byte(pLength >> 16),
byte(pLength >> 8),
byte(pLength),
})
return err
}
if _, err := w.Write([]byte{0x99, byte(pLength >> 8), byte(pLength)}); err != nil {
return err
}
return nil
}
func (pk *PublicKey) Serialize(w io.Writer) (err error) {
length := uint32(versionSize + timestampSize + algorithmSize) // 6 byte header
length += pk.algorithmSpecificByteCount()
if pk.Version >= 5 {
length += 4 // octet key count
}
packetType := packetTypePublicKey
if pk.IsSubkey {
packetType = packetTypePublicSubkey
}
err = serializeHeader(w, packetType, int(length))
if err != nil {
return
}
return pk.serializeWithoutHeaders(w)
}
func (pk *PublicKey) algorithmSpecificByteCount() uint32 {
length := uint32(0)
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
length += uint32(pk.n.EncodedLength())
length += uint32(pk.e.EncodedLength())
case PubKeyAlgoDSA:
length += uint32(pk.p.EncodedLength())
length += uint32(pk.q.EncodedLength())
length += uint32(pk.g.EncodedLength())
length += uint32(pk.y.EncodedLength())
case PubKeyAlgoElGamal:
length += uint32(pk.p.EncodedLength())
length += uint32(pk.g.EncodedLength())
length += uint32(pk.y.EncodedLength())
case PubKeyAlgoECDSA:
length += uint32(pk.oid.EncodedLength())
length += uint32(pk.p.EncodedLength())
case PubKeyAlgoECDH:
length += uint32(pk.oid.EncodedLength())
length += uint32(pk.p.EncodedLength())
length += uint32(pk.kdf.EncodedLength())
case PubKeyAlgoEdDSA:
length += uint32(pk.oid.EncodedLength())
length += uint32(pk.p.EncodedLength())
case PubKeyAlgoX25519:
length += x25519.KeySize
case PubKeyAlgoX448:
length += x448.KeySize
case PubKeyAlgoEd25519:
length += ed25519.PublicKeySize
case PubKeyAlgoEd448:
length += ed448.PublicKeySize
default:
panic("unknown public key algorithm")
}
return length
}
// serializeWithoutHeaders marshals the PublicKey to w in the form of an
// OpenPGP public key packet, not including the packet header.
func (pk *PublicKey) serializeWithoutHeaders(w io.Writer) (err error) {
t := uint32(pk.CreationTime.Unix())
if _, err = w.Write([]byte{
byte(pk.Version),
byte(t >> 24), byte(t >> 16), byte(t >> 8), byte(t),
byte(pk.PubKeyAlgo),
}); err != nil {
return
}
if pk.Version >= 5 {
n := pk.algorithmSpecificByteCount()
if _, err = w.Write([]byte{
byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n),
}); err != nil {
return
}
}
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
if _, err = w.Write(pk.n.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.e.EncodedBytes())
return
case PubKeyAlgoDSA:
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
return
}
if _, err = w.Write(pk.q.EncodedBytes()); err != nil {
return
}
if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.y.EncodedBytes())
return
case PubKeyAlgoElGamal:
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
return
}
if _, err = w.Write(pk.g.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.y.EncodedBytes())
return
case PubKeyAlgoECDSA:
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.p.EncodedBytes())
return
case PubKeyAlgoECDH:
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
return
}
if _, err = w.Write(pk.p.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.kdf.EncodedBytes())
return
case PubKeyAlgoEdDSA:
if _, err = w.Write(pk.oid.EncodedBytes()); err != nil {
return
}
_, err = w.Write(pk.p.EncodedBytes())
return
case PubKeyAlgoX25519:
publicKey := pk.PublicKey.(*x25519.PublicKey)
_, err = w.Write(publicKey.Point)
return
case PubKeyAlgoX448:
publicKey := pk.PublicKey.(*x448.PublicKey)
_, err = w.Write(publicKey.Point)
return
case PubKeyAlgoEd25519:
publicKey := pk.PublicKey.(*ed25519.PublicKey)
_, err = w.Write(publicKey.Point)
return
case PubKeyAlgoEd448:
publicKey := pk.PublicKey.(*ed448.PublicKey)
_, err = w.Write(publicKey.Point)
return
}
return errors.InvalidArgumentError("bad public-key algorithm")
}
// CanSign returns true iff this public key can generate signatures
func (pk *PublicKey) CanSign() bool {
return pk.PubKeyAlgo != PubKeyAlgoRSAEncryptOnly && pk.PubKeyAlgo != PubKeyAlgoElGamal && pk.PubKeyAlgo != PubKeyAlgoECDH
}
// VerifyHashTag returns nil iff sig appears to be a plausible signature of the data
// hashed into signed, based solely on its HashTag. signed is mutated by this call.
func VerifyHashTag(signed hash.Hash, sig *Signature) (err error) {
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
sig.AddMetadataToHashSuffix()
}
signed.Write(sig.HashSuffix)
hashBytes := signed.Sum(nil)
if hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1] {
return errors.SignatureError("hash tag doesn't match")
}
return nil
}
// VerifySignature returns nil iff sig is a valid signature, made by this
// public key, of the data hashed into signed. signed is mutated by this call.
func (pk *PublicKey) VerifySignature(signed hash.Hash, sig *Signature) (err error) {
if !pk.CanSign() {
return errors.InvalidArgumentError("public key cannot generate signatures")
}
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
sig.AddMetadataToHashSuffix()
}
signed.Write(sig.HashSuffix)
hashBytes := signed.Sum(nil)
// see discussion https://github.com/ProtonMail/go-crypto/issues/107
if sig.Version >= 5 && (hashBytes[0] != sig.HashTag[0] || hashBytes[1] != sig.HashTag[1]) {
return errors.SignatureError("hash tag doesn't match")
}
if pk.PubKeyAlgo != sig.PubKeyAlgo {
return errors.InvalidArgumentError("public key and signature use different algorithms")
}
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
rsaPublicKey, _ := pk.PublicKey.(*rsa.PublicKey)
err = rsa.VerifyPKCS1v15(rsaPublicKey, sig.Hash, hashBytes, padToKeySize(rsaPublicKey, sig.RSASignature.Bytes()))
if err != nil {
return errors.SignatureError("RSA verification failure")
}
return nil
case PubKeyAlgoDSA:
dsaPublicKey, _ := pk.PublicKey.(*dsa.PublicKey)
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
subgroupSize := (dsaPublicKey.Q.BitLen() + 7) / 8
if len(hashBytes) > subgroupSize {
hashBytes = hashBytes[:subgroupSize]
}
if !dsa.Verify(dsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.DSASigR.Bytes()), new(big.Int).SetBytes(sig.DSASigS.Bytes())) {
return errors.SignatureError("DSA verification failure")
}
return nil
case PubKeyAlgoECDSA:
ecdsaPublicKey := pk.PublicKey.(*ecdsa.PublicKey)
if !ecdsa.Verify(ecdsaPublicKey, hashBytes, new(big.Int).SetBytes(sig.ECDSASigR.Bytes()), new(big.Int).SetBytes(sig.ECDSASigS.Bytes())) {
return errors.SignatureError("ECDSA verification failure")
}
return nil
case PubKeyAlgoEdDSA:
eddsaPublicKey := pk.PublicKey.(*eddsa.PublicKey)
if !eddsa.Verify(eddsaPublicKey, hashBytes, sig.EdDSASigR.Bytes(), sig.EdDSASigS.Bytes()) {
return errors.SignatureError("EdDSA verification failure")
}
return nil
case PubKeyAlgoEd25519:
ed25519PublicKey := pk.PublicKey.(*ed25519.PublicKey)
if !ed25519.Verify(ed25519PublicKey, hashBytes, sig.EdSig) {
return errors.SignatureError("Ed25519 verification failure")
}
return nil
case PubKeyAlgoEd448:
ed448PublicKey := pk.PublicKey.(*ed448.PublicKey)
if !ed448.Verify(ed448PublicKey, hashBytes, sig.EdSig) {
return errors.SignatureError("ed448 verification failure")
}
return nil
default:
return errors.SignatureError("Unsupported public key algorithm used in signature")
}
}
// keySignatureHash returns a Hash of the message that needs to be signed for
// pk to assert a subkey relationship to signed.
func keySignatureHash(pk, signed signingKey, hashFunc hash.Hash) (h hash.Hash, err error) {
h = hashFunc
// RFC 4880, section 5.2.4
err = pk.SerializeForHash(h)
if err != nil {
return nil, err
}
err = signed.SerializeForHash(h)
return
}
// VerifyKeyHashTag returns nil iff sig appears to be a plausible signature over this
// primary key and subkey, based solely on its HashTag.
func (pk *PublicKey) VerifyKeyHashTag(signed *PublicKey, sig *Signature) error {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
h, err := keySignatureHash(pk, signed, preparedHash)
if err != nil {
return err
}
return VerifyHashTag(h, sig)
}
// VerifyKeySignature returns nil iff sig is a valid signature, made by this
// public key, of signed.
func (pk *PublicKey) VerifyKeySignature(signed *PublicKey, sig *Signature) error {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
h, err := keySignatureHash(pk, signed, preparedHash)
if err != nil {
return err
}
if err = pk.VerifySignature(h, sig); err != nil {
return err
}
if sig.FlagSign {
// Signing subkeys must be cross-signed. See
// https://www.gnupg.org/faq/subkey-cross-certify.html.
if sig.EmbeddedSignature == nil {
return errors.StructuralError("signing subkey is missing cross-signature")
}
preparedHashEmbedded, err := sig.EmbeddedSignature.PrepareVerify()
if err != nil {
return err
}
// Verify the cross-signature. This is calculated over the same
// data as the main signature, so we cannot just recursively
// call signed.VerifyKeySignature(...)
if h, err = keySignatureHash(pk, signed, preparedHashEmbedded); err != nil {
return errors.StructuralError("error while hashing for cross-signature: " + err.Error())
}
if err := signed.VerifySignature(h, sig.EmbeddedSignature); err != nil {
return errors.StructuralError("error while verifying cross-signature: " + err.Error())
}
}
return nil
}
func keyRevocationHash(pk signingKey, hashFunc hash.Hash) (err error) {
return pk.SerializeForHash(hashFunc)
}
// VerifyRevocationHashTag returns nil iff sig appears to be a plausible signature
// over this public key, based solely on its HashTag.
func (pk *PublicKey) VerifyRevocationHashTag(sig *Signature) (err error) {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
if err = keyRevocationHash(pk, preparedHash); err != nil {
return err
}
return VerifyHashTag(preparedHash, sig)
}
// VerifyRevocationSignature returns nil iff sig is a valid signature, made by this
// public key.
func (pk *PublicKey) VerifyRevocationSignature(sig *Signature) (err error) {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
if err = keyRevocationHash(pk, preparedHash); err != nil {
return err
}
return pk.VerifySignature(preparedHash, sig)
}
// VerifySubkeyRevocationSignature returns nil iff sig is a valid subkey revocation signature,
// made by this public key, of signed.
func (pk *PublicKey) VerifySubkeyRevocationSignature(sig *Signature, signed *PublicKey) (err error) {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
h, err := keySignatureHash(pk, signed, preparedHash)
if err != nil {
return err
}
return pk.VerifySignature(h, sig)
}
// userIdSignatureHash returns a Hash of the message that needs to be signed
// to assert that pk is a valid key for id.
func userIdSignatureHash(id string, pk *PublicKey, h hash.Hash) (err error) {
// RFC 4880, section 5.2.4
if err := pk.SerializeSignaturePrefix(h); err != nil {
return err
}
if err := pk.serializeWithoutHeaders(h); err != nil {
return err
}
var buf [5]byte
buf[0] = 0xb4
buf[1] = byte(len(id) >> 24)
buf[2] = byte(len(id) >> 16)
buf[3] = byte(len(id) >> 8)
buf[4] = byte(len(id))
h.Write(buf[:])
h.Write([]byte(id))
return nil
}
// directKeySignatureHash returns a Hash of the message that needs to be signed.
func directKeySignatureHash(pk *PublicKey, h hash.Hash) (err error) {
return pk.SerializeForHash(h)
}
// VerifyUserIdHashTag returns nil iff sig appears to be a plausible signature over this
// public key and UserId, based solely on its HashTag
func (pk *PublicKey) VerifyUserIdHashTag(id string, sig *Signature) (err error) {
preparedHash, err := sig.PrepareVerify()
if err != nil {
return err
}
err = userIdSignatureHash(id, pk, preparedHash)
if err != nil {
return err
}
return VerifyHashTag(preparedHash, sig)
}
// VerifyUserIdSignature returns nil iff sig is a valid signature, made by this
// public key, that id is the identity of pub.
func (pk *PublicKey) VerifyUserIdSignature(id string, pub *PublicKey, sig *Signature) (err error) {
h, err := sig.PrepareVerify()
if err != nil {
return err
}
if err := userIdSignatureHash(id, pub, h); err != nil {
return err
}
return pk.VerifySignature(h, sig)
}
// VerifyDirectKeySignature returns nil iff sig is a valid signature, made by this
// public key.
func (pk *PublicKey) VerifyDirectKeySignature(sig *Signature) (err error) {
h, err := sig.PrepareVerify()
if err != nil {
return err
}
if err := directKeySignatureHash(pk, h); err != nil {
return err
}
return pk.VerifySignature(h, sig)
}
// KeyIdString returns the public key's fingerprint in capital hex
// (e.g. "6C7EE1B8621CC013").
func (pk *PublicKey) KeyIdString() string {
return fmt.Sprintf("%X", pk.Fingerprint[12:20])
}
// KeyIdShortString returns the short form of public key's fingerprint
// in capital hex, as shown by gpg --list-keys (e.g. "621CC013").
func (pk *PublicKey) KeyIdShortString() string {
return fmt.Sprintf("%X", pk.Fingerprint[16:20])
}
// BitLength returns the bit length for the given public key.
func (pk *PublicKey) BitLength() (bitLength uint16, err error) {
switch pk.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSAEncryptOnly, PubKeyAlgoRSASignOnly:
bitLength = pk.n.BitLength()
case PubKeyAlgoDSA:
bitLength = pk.p.BitLength()
case PubKeyAlgoElGamal:
bitLength = pk.p.BitLength()
case PubKeyAlgoECDSA:
bitLength = pk.p.BitLength()
case PubKeyAlgoECDH:
bitLength = pk.p.BitLength()
case PubKeyAlgoEdDSA:
bitLength = pk.p.BitLength()
case PubKeyAlgoX25519:
bitLength = x25519.KeySize * 8
case PubKeyAlgoX448:
bitLength = x448.KeySize * 8
case PubKeyAlgoEd25519:
bitLength = ed25519.PublicKeySize * 8
case PubKeyAlgoEd448:
bitLength = ed448.PublicKeySize * 8
default:
err = errors.InvalidArgumentError("bad public-key algorithm")
}
return
}
// Curve returns the used elliptic curve of this public key.
// Returns an error if no elliptic curve is used.
func (pk *PublicKey) Curve() (curve Curve, err error) {
switch pk.PubKeyAlgo {
case PubKeyAlgoECDSA, PubKeyAlgoECDH, PubKeyAlgoEdDSA:
curveInfo := ecc.FindByOid(pk.oid)
if curveInfo == nil {
return "", errors.UnsupportedError(fmt.Sprintf("unknown oid: %x", pk.oid))
}
curve = Curve(curveInfo.GenName)
case PubKeyAlgoEd25519, PubKeyAlgoX25519:
curve = Curve25519
case PubKeyAlgoEd448, PubKeyAlgoX448:
curve = Curve448
default:
err = errors.InvalidArgumentError("public key does not operate with an elliptic curve")
}
return
}
// KeyExpired returns whether sig is a self-signature of a key that has
// expired or is created in the future.
func (pk *PublicKey) KeyExpired(sig *Signature, currentTime time.Time) bool {
if pk.CreationTime.Unix() > currentTime.Unix() {
return true
}
if sig.KeyLifetimeSecs == nil || *sig.KeyLifetimeSecs == 0 {
return false
}
expiry := pk.CreationTime.Add(time.Duration(*sig.KeyLifetimeSecs) * time.Second)
return currentTime.Unix() > expiry.Unix()
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/public_key_test_data.go
================================================
package packet
const rsaFingerprintHex = "5fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb"
const rsaPkDataHex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001"
const dsaFingerprintHex = "eece4c094db002103714c63c8e8fbe54062f19ed"
const dsaPkDataHex = "9901a2044d432f89110400cd581334f0d7a1e1bdc8b9d6d8c0baf68793632735d2bb0903224cbaa1dfbf35a60ee7a13b92643421e1eb41aa8d79bea19a115a677f6b8ba3c7818ce53a6c2a24a1608bd8b8d6e55c5090cbde09dd26e356267465ae25e69ec8bdd57c7bbb2623e4d73336f73a0a9098f7f16da2e25252130fd694c0e8070c55a812a423ae7f00a0ebf50e70c2f19c3520a551bd4b08d30f23530d3d03ff7d0bf4a53a64a09dc5e6e6e35854b7d70c882b0c60293401958b1bd9e40abec3ea05ba87cf64899299d4bd6aa7f459c201d3fbbd6c82004bdc5e8a9eb8082d12054cc90fa9d4ec251a843236a588bf49552441817436c4f43326966fe85447d4e6d0acf8fa1ef0f014730770603ad7634c3088dc52501c237328417c31c89ed70400b2f1a98b0bf42f11fefc430704bebbaa41d9f355600c3facee1e490f64208e0e094ea55e3a598a219a58500bf78ac677b670a14f4e47e9cf8eab4f368cc1ddcaa18cc59309d4cc62dd4f680e73e6cc3e1ce87a84d0925efbcb26c575c093fc42eecf45135fabf6403a25c2016e1774c0484e440a18319072c617cc97ac0a3bb0"
const ecdsaFingerprintHex = "9892270b38b8980b05c8d56d43fe956c542ca00b"
const ecdsaPkDataHex = "9893045071c29413052b8104002304230401f4867769cedfa52c325018896245443968e52e51d0c2df8d939949cb5b330f2921711fbee1c9b9dddb95d15cb0255e99badeddda7cc23d9ddcaacbc290969b9f24019375d61c2e4e3b36953a28d8b2bc95f78c3f1d592fb24499be348656a7b17e3963187b4361afe497bc5f9f81213f04069f8e1fb9e6a6290ae295ca1a92b894396cb4"
const ecdhFingerprintHex = "722354df2475a42164d1d49faa8b938f9a201946"
const ecdhPkDataHex = "b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec91803010909"
const eddsaFingerprintHex = "b2d5e5ec0e6deca6bc8eeeb00907e75e1dd99ad8"
const eddsaPkDataHex = "98330456e2132b16092b06010401da470f01010740bbda39266affa511a8c2d02edf690fb784b0499c4406185811a163539ef11dc1b41d74657374696e67203c74657374696e674074657374696e672e636f6d3e8879041316080021050256e2132b021b03050b09080702061508090a0b020416020301021e01021780000a09100907e75e1dd99ad86d0c00fe39d2008359352782bc9b61ac382584cd8eff3f57a18c2287e3afeeb05d1f04ba00fe2d0bc1ddf3ff8adb9afa3e7d9287244b4ec567f3db4d60b74a9b5465ed528203"
// Source: https://sites.google.com/site/brainhub/pgpecckeys#TOC-ECC-NIST-P-384-key
const ecc384PubHex = `99006f044d53059213052b81040022030304f6b8c5aced5b84ef9f4a209db2e4a9dfb70d28cb8c10ecd57674a9fa5a67389942b62d5e51367df4c7bfd3f8e500feecf07ed265a621a8ebbbe53e947ec78c677eba143bd1533c2b350e1c29f82313e1e1108eba063be1e64b10e6950e799c2db42465635f6473615f64685f333834203c6f70656e70677040627261696e6875622e6f72673e8900cb04101309005305024d530592301480000000002000077072656665727265642d656d61696c2d656e636f64696e67407067702e636f6d7067706d696d65040b090807021901051b03000000021602051e010000000415090a08000a0910098033880f54719fca2b0180aa37350968bd5f115afd8ce7bc7b103822152dbff06d0afcda835329510905b98cb469ba208faab87c7412b799e7b633017f58364ea480e8a1a3f253a0c5f22c446e8be9a9fce6210136ee30811abbd49139de28b5bdf8dc36d06ae748579e9ff503b90073044d53059212052b810400220303042faa84024a20b6735c4897efa5bfb41bf85b7eefeab5ca0cb9ffc8ea04a46acb25534a577694f9e25340a4ab5223a9dd1eda530c8aa2e6718db10d7e672558c7736fe09369ea5739a2a3554bf16d41faa50562f11c6d39bbd5dffb6b9a9ec9180301090989008404181309000c05024d530592051b0c000000000a0910098033880f54719f80970180eee7a6d8fcee41ee4f9289df17f9bcf9d955dca25c583b94336f3a2b2d4986dc5cf417b8d2dc86f741a9e1a6d236c0e3017d1c76575458a0cfb93ae8a2b274fcc65ceecd7a91eec83656ba13219969f06945b48c56bd04152c3a0553c5f2f4bd1267`
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/reader.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
type PacketReader interface {
Next() (p Packet, err error)
Push(reader io.Reader) (err error)
Unread(p Packet)
}
// Reader reads packets from an io.Reader and allows packets to be 'unread' so
// that they result from the next call to Next.
type Reader struct {
q []Packet
readers []io.Reader
}
// New io.Readers are pushed when a compressed or encrypted packet is processed
// and recursively treated as a new source of packets. However, a carefully
// crafted packet can trigger an infinite recursive sequence of packets. See
// http://mumble.net/~campbell/misc/pgp-quine
// https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-4402
// This constant limits the number of recursive packets that may be pushed.
const maxReaders = 32
// Next returns the most recently unread Packet, or reads another packet from
// the top-most io.Reader. Unknown/unsupported/Marker packet types are skipped.
func (r *Reader) Next() (p Packet, err error) {
for {
p, err := r.read()
if err == io.EOF {
break
} else if err != nil {
if _, ok := err.(errors.UnknownPacketTypeError); ok {
continue
}
if _, ok := err.(errors.UnsupportedError); ok {
switch p.(type) {
case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
return nil, err
}
continue
}
return nil, err
} else {
//A marker packet MUST be ignored when received
switch p.(type) {
case *Marker:
continue
}
return p, nil
}
}
return nil, io.EOF
}
// Next returns the most recently unread Packet, or reads another packet from
// the top-most io.Reader. Unknown/Marker packet types are skipped while unsupported
// packets are returned as UnsupportedPacket type.
func (r *Reader) NextWithUnsupported() (p Packet, err error) {
for {
p, err = r.read()
if err == io.EOF {
break
} else if err != nil {
if _, ok := err.(errors.UnknownPacketTypeError); ok {
continue
}
if casteErr, ok := err.(errors.UnsupportedError); ok {
return &UnsupportedPacket{
IncompletePacket: p,
Error: casteErr,
}, nil
}
return
} else {
//A marker packet MUST be ignored when received
switch p.(type) {
case *Marker:
continue
}
return
}
}
return nil, io.EOF
}
func (r *Reader) read() (p Packet, err error) {
if len(r.q) > 0 {
p = r.q[len(r.q)-1]
r.q = r.q[:len(r.q)-1]
return
}
for len(r.readers) > 0 {
p, err = Read(r.readers[len(r.readers)-1])
if err == io.EOF {
r.readers = r.readers[:len(r.readers)-1]
continue
}
return p, err
}
return nil, io.EOF
}
// Push causes the Reader to start reading from a new io.Reader. When an EOF
// error is seen from the new io.Reader, it is popped and the Reader continues
// to read from the next most recent io.Reader. Push returns a StructuralError
// if pushing the reader would exceed the maximum recursion level, otherwise it
// returns nil.
func (r *Reader) Push(reader io.Reader) (err error) {
if len(r.readers) >= maxReaders {
return errors.StructuralError("too many layers of packets")
}
r.readers = append(r.readers, reader)
return nil
}
// Unread causes the given Packet to be returned from the next call to Next.
func (r *Reader) Unread(p Packet) {
r.q = append(r.q, p)
}
func NewReader(r io.Reader) *Reader {
return &Reader{
q: nil,
readers: []io.Reader{r},
}
}
// CheckReader is similar to Reader but additionally
// uses the pushdown automata to verify the read packet sequence.
type CheckReader struct {
Reader
verifier *SequenceVerifier
fullyRead bool
}
// Next returns the most recently unread Packet, or reads another packet from
// the top-most io.Reader. Unknown packet types are skipped.
// If the read packet sequence does not conform to the packet composition
// rules in rfc4880, it returns an error.
func (r *CheckReader) Next() (p Packet, err error) {
if r.fullyRead {
return nil, io.EOF
}
if len(r.q) > 0 {
p = r.q[len(r.q)-1]
r.q = r.q[:len(r.q)-1]
return
}
var errMsg error
for len(r.readers) > 0 {
p, errMsg, err = ReadWithCheck(r.readers[len(r.readers)-1], r.verifier)
if errMsg != nil {
err = errMsg
return
}
if err == nil {
return
}
if err == io.EOF {
r.readers = r.readers[:len(r.readers)-1]
continue
}
//A marker packet MUST be ignored when received
switch p.(type) {
case *Marker:
continue
}
if _, ok := err.(errors.UnknownPacketTypeError); ok {
continue
}
if _, ok := err.(errors.UnsupportedError); ok {
switch p.(type) {
case *SymmetricallyEncrypted, *AEADEncrypted, *Compressed, *LiteralData:
return nil, err
}
continue
}
return nil, err
}
if errMsg = r.verifier.Next(EOSSymbol); errMsg != nil {
return nil, errMsg
}
if errMsg = r.verifier.AssertValid(); errMsg != nil {
return nil, errMsg
}
r.fullyRead = true
return nil, io.EOF
}
func NewCheckReader(r io.Reader) *CheckReader {
return &CheckReader{
Reader: Reader{
q: nil,
readers: []io.Reader{r},
},
verifier: NewSequenceVerifier(),
fullyRead: false,
}
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/recipient.go
================================================
package packet
// Recipient type represents a Intended Recipient Fingerprint subpacket
// See https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#name-intended-recipient-fingerpr
type Recipient struct {
KeyVersion int
Fingerprint []byte
}
func (r *Recipient) Serialize() []byte {
packet := make([]byte, len(r.Fingerprint)+1)
packet[0] = byte(r.KeyVersion)
copy(packet[1:], r.Fingerprint)
return packet
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/signature.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"crypto"
"crypto/dsa"
"encoding/asn1"
"encoding/binary"
"hash"
"io"
"math/big"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/ecdsa"
"github.com/ProtonMail/go-crypto/openpgp/ed25519"
"github.com/ProtonMail/go-crypto/openpgp/ed448"
"github.com/ProtonMail/go-crypto/openpgp/eddsa"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/internal/encoding"
)
const (
// First octet of key flags.
// See RFC 9580, section 5.2.3.29 for details.
KeyFlagCertify = 1 << iota
KeyFlagSign
KeyFlagEncryptCommunications
KeyFlagEncryptStorage
KeyFlagSplitKey
KeyFlagAuthenticate
_
KeyFlagGroupKey
)
const (
// First octet of keyserver preference flags.
// See RFC 9580, section 5.2.3.25 for details.
_ = 1 << iota
_
_
_
_
_
_
KeyserverPrefNoModify
)
const SaltNotationName = "salt@notations.openpgpjs.org"
// Signature represents a signature. See RFC 9580, section 5.2.
type Signature struct {
Version int
SigType SignatureType
PubKeyAlgo PublicKeyAlgorithm
Hash crypto.Hash
// salt contains a random salt value for v6 signatures
// See RFC 9580 Section 5.2.4.
salt []byte
// HashSuffix is extra data that is hashed in after the signed data.
HashSuffix []byte
// HashTag contains the first two bytes of the hash for fast rejection
// of bad signed data.
HashTag [2]byte
// Metadata includes format, filename and time, and is protected by v5
// signatures of type 0x00 or 0x01. This metadata is included into the hash
// computation; if nil, six 0x00 bytes are used instead. See section 5.2.4.
Metadata *LiteralData
CreationTime time.Time
RSASignature encoding.Field
DSASigR, DSASigS encoding.Field
ECDSASigR, ECDSASigS encoding.Field
EdDSASigR, EdDSASigS encoding.Field
EdSig []byte
// rawSubpackets contains the unparsed subpackets, in order.
rawSubpackets []outputSubpacket
// The following are optional so are nil when not included in the
// signature.
SigLifetimeSecs, KeyLifetimeSecs *uint32
PreferredSymmetric, PreferredHash, PreferredCompression []uint8
PreferredCipherSuites [][2]uint8
IssuerKeyId *uint64
IssuerFingerprint []byte
SignerUserId *string
IsPrimaryId *bool
Notations []*Notation
IntendedRecipients []*Recipient
// TrustLevel and TrustAmount can be set by the signer to assert that
// the key is not only valid but also trustworthy at the specified
// level.
// See RFC 9580, section 5.2.3.21 for details.
TrustLevel TrustLevel
TrustAmount TrustAmount
// TrustRegularExpression can be used in conjunction with trust Signature
// packets to limit the scope of the trust that is extended.
// See RFC 9580, section 5.2.3.22 for details.
TrustRegularExpression *string
// KeyserverPrefsValid is set if any keyserver preferences were given. See RFC 9580, section
// 5.2.3.25 for details.
KeyserverPrefsValid bool
KeyserverPrefNoModify bool
// PreferredKeyserver can be set to a URI where the latest version of the
// key that this signature is made over can be found. See RFC 9580, section
// 5.2.3.26 for details.
PreferredKeyserver string
// PolicyURI can be set to the URI of a document that describes the
// policy under which the signature was issued. See RFC 9580, section
// 5.2.3.28 for details.
PolicyURI string
// FlagsValid is set if any flags were given. See RFC 9580, section
// 5.2.3.29 for details.
FlagsValid bool
FlagCertify, FlagSign, FlagEncryptCommunications, FlagEncryptStorage, FlagSplitKey, FlagAuthenticate, FlagGroupKey bool
// RevocationReason is set if this signature has been revoked.
// See RFC 9580, section 5.2.3.31 for details.
RevocationReason *ReasonForRevocation
RevocationReasonText string
// In a self-signature, these flags are set there is a features subpacket
// indicating that the issuer implementation supports these features
// see https://datatracker.ietf.org/doc/html/draft-ietf-openpgp-crypto-refresh#features-subpacket
SEIPDv1, SEIPDv2 bool
// EmbeddedSignature, if non-nil, is a signature of the parent key, by
// this key. This prevents an attacker from claiming another's signing
// subkey as their own.
EmbeddedSignature *Signature
outSubpackets []outputSubpacket
}
// VerifiableSignature internally keeps state if the
// the signature has been verified before.
type VerifiableSignature struct {
Valid *bool // nil if it has not been verified yet
Packet *Signature
}
// NewVerifiableSig returns a struct of type VerifiableSignature referencing the input signature.
func NewVerifiableSig(signature *Signature) *VerifiableSignature {
return &VerifiableSignature{
Packet: signature,
}
}
// Salt returns the signature salt for v6 signatures.
func (sig *Signature) Salt() []byte {
if sig == nil {
return nil
}
return sig.salt
}
func (sig *Signature) parse(r io.Reader) (err error) {
// RFC 9580, section 5.2.3
var buf [7]byte
_, err = readFull(r, buf[:1])
if err != nil {
return
}
sig.Version = int(buf[0])
if sig.Version != 4 && sig.Version != 5 && sig.Version != 6 {
err = errors.UnsupportedError("signature packet version " + strconv.Itoa(int(buf[0])))
return
}
if V5Disabled && sig.Version == 5 {
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
}
if sig.Version == 6 {
_, err = readFull(r, buf[:7])
} else {
_, err = readFull(r, buf[:5])
}
if err != nil {
return
}
sig.SigType = SignatureType(buf[0])
sig.PubKeyAlgo = PublicKeyAlgorithm(buf[1])
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly, PubKeyAlgoDSA, PubKeyAlgoECDSA, PubKeyAlgoEdDSA, PubKeyAlgoEd25519, PubKeyAlgoEd448:
default:
err = errors.UnsupportedError("public key algorithm " + strconv.Itoa(int(sig.PubKeyAlgo)))
return
}
var ok bool
if sig.Version < 5 {
sig.Hash, ok = algorithm.HashIdToHashWithSha1(buf[2])
} else {
sig.Hash, ok = algorithm.HashIdToHash(buf[2])
}
if !ok {
return errors.UnsupportedError("hash function " + strconv.Itoa(int(buf[2])))
}
var hashedSubpacketsLength int
if sig.Version == 6 {
// For a v6 signature, a four-octet length is used.
hashedSubpacketsLength =
int(buf[3])<<24 |
int(buf[4])<<16 |
int(buf[5])<<8 |
int(buf[6])
} else {
hashedSubpacketsLength = int(buf[3])<<8 | int(buf[4])
}
hashedSubpackets := make([]byte, hashedSubpacketsLength)
_, err = readFull(r, hashedSubpackets)
if err != nil {
return
}
err = sig.buildHashSuffix(hashedSubpackets)
if err != nil {
return
}
err = parseSignatureSubpackets(sig, hashedSubpackets, true)
if err != nil {
return
}
if sig.Version == 6 {
_, err = readFull(r, buf[:4])
} else {
_, err = readFull(r, buf[:2])
}
if err != nil {
return
}
var unhashedSubpacketsLength uint32
if sig.Version == 6 {
unhashedSubpacketsLength = uint32(buf[0])<<24 | uint32(buf[1])<<16 | uint32(buf[2])<<8 | uint32(buf[3])
} else {
unhashedSubpacketsLength = uint32(buf[0])<<8 | uint32(buf[1])
}
unhashedSubpackets := make([]byte, unhashedSubpacketsLength)
_, err = readFull(r, unhashedSubpackets)
if err != nil {
return
}
err = parseSignatureSubpackets(sig, unhashedSubpackets, false)
if err != nil {
return
}
_, err = readFull(r, sig.HashTag[:2])
if err != nil {
return
}
if sig.Version == 6 {
// Only for v6 signatures, a variable-length field containing the salt
_, err = readFull(r, buf[:1])
if err != nil {
return
}
saltLength := int(buf[0])
var expectedSaltLength int
expectedSaltLength, err = SaltLengthForHash(sig.Hash)
if err != nil {
return
}
if saltLength != expectedSaltLength {
err = errors.StructuralError("unexpected salt size for the given hash algorithm")
return
}
salt := make([]byte, expectedSaltLength)
_, err = readFull(r, salt)
if err != nil {
return
}
sig.salt = salt
}
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sig.RSASignature = new(encoding.MPI)
_, err = sig.RSASignature.ReadFrom(r)
case PubKeyAlgoDSA:
sig.DSASigR = new(encoding.MPI)
if _, err = sig.DSASigR.ReadFrom(r); err != nil {
return
}
sig.DSASigS = new(encoding.MPI)
_, err = sig.DSASigS.ReadFrom(r)
case PubKeyAlgoECDSA:
sig.ECDSASigR = new(encoding.MPI)
if _, err = sig.ECDSASigR.ReadFrom(r); err != nil {
return
}
sig.ECDSASigS = new(encoding.MPI)
_, err = sig.ECDSASigS.ReadFrom(r)
case PubKeyAlgoEdDSA:
sig.EdDSASigR = new(encoding.MPI)
if _, err = sig.EdDSASigR.ReadFrom(r); err != nil {
return
}
sig.EdDSASigS = new(encoding.MPI)
if _, err = sig.EdDSASigS.ReadFrom(r); err != nil {
return
}
case PubKeyAlgoEd25519:
sig.EdSig, err = ed25519.ReadSignature(r)
if err != nil {
return
}
case PubKeyAlgoEd448:
sig.EdSig, err = ed448.ReadSignature(r)
if err != nil {
return
}
default:
panic("unreachable")
}
return
}
// parseSignatureSubpackets parses subpackets of the main signature packet. See
// RFC 9580, section 5.2.3.1.
func parseSignatureSubpackets(sig *Signature, subpackets []byte, isHashed bool) (err error) {
for len(subpackets) > 0 {
subpackets, err = parseSignatureSubpacket(sig, subpackets, isHashed)
if err != nil {
return
}
}
if sig.CreationTime.IsZero() {
err = errors.StructuralError("no creation time in signature")
}
return
}
type signatureSubpacketType uint8
const (
creationTimeSubpacket signatureSubpacketType = 2
signatureExpirationSubpacket signatureSubpacketType = 3
exportableCertSubpacket signatureSubpacketType = 4
trustSubpacket signatureSubpacketType = 5
regularExpressionSubpacket signatureSubpacketType = 6
keyExpirationSubpacket signatureSubpacketType = 9
prefSymmetricAlgosSubpacket signatureSubpacketType = 11
issuerSubpacket signatureSubpacketType = 16
notationDataSubpacket signatureSubpacketType = 20
prefHashAlgosSubpacket signatureSubpacketType = 21
prefCompressionSubpacket signatureSubpacketType = 22
keyserverPrefsSubpacket signatureSubpacketType = 23
prefKeyserverSubpacket signatureSubpacketType = 24
primaryUserIdSubpacket signatureSubpacketType = 25
policyUriSubpacket signatureSubpacketType = 26
keyFlagsSubpacket signatureSubpacketType = 27
signerUserIdSubpacket signatureSubpacketType = 28
reasonForRevocationSubpacket signatureSubpacketType = 29
featuresSubpacket signatureSubpacketType = 30
embeddedSignatureSubpacket signatureSubpacketType = 32
issuerFingerprintSubpacket signatureSubpacketType = 33
intendedRecipientSubpacket signatureSubpacketType = 35
prefCipherSuitesSubpacket signatureSubpacketType = 39
)
// parseSignatureSubpacket parses a single subpacket. len(subpacket) is >= 1.
func parseSignatureSubpacket(sig *Signature, subpacket []byte, isHashed bool) (rest []byte, err error) {
// RFC 9580, section 5.2.3.7
var (
length uint32
packetType signatureSubpacketType
isCritical bool
)
if len(subpacket) == 0 {
err = errors.StructuralError("zero length signature subpacket")
return
}
switch {
case subpacket[0] < 192:
length = uint32(subpacket[0])
subpacket = subpacket[1:]
case subpacket[0] < 255:
if len(subpacket) < 2 {
goto Truncated
}
length = uint32(subpacket[0]-192)<<8 + uint32(subpacket[1]) + 192
subpacket = subpacket[2:]
default:
if len(subpacket) < 5 {
goto Truncated
}
length = uint32(subpacket[1])<<24 |
uint32(subpacket[2])<<16 |
uint32(subpacket[3])<<8 |
uint32(subpacket[4])
subpacket = subpacket[5:]
}
if length > uint32(len(subpacket)) {
goto Truncated
}
rest = subpacket[length:]
subpacket = subpacket[:length]
if len(subpacket) == 0 {
err = errors.StructuralError("zero length signature subpacket")
return
}
packetType = signatureSubpacketType(subpacket[0] & 0x7f)
isCritical = subpacket[0]&0x80 == 0x80
subpacket = subpacket[1:]
sig.rawSubpackets = append(sig.rawSubpackets, outputSubpacket{isHashed, packetType, isCritical, subpacket})
if !isHashed &&
packetType != issuerSubpacket &&
packetType != issuerFingerprintSubpacket &&
packetType != embeddedSignatureSubpacket {
return
}
switch packetType {
case creationTimeSubpacket:
if len(subpacket) != 4 {
err = errors.StructuralError("signature creation time not four bytes")
return
}
t := binary.BigEndian.Uint32(subpacket)
sig.CreationTime = time.Unix(int64(t), 0)
case signatureExpirationSubpacket:
// Signature expiration time, section 5.2.3.18
if len(subpacket) != 4 {
err = errors.StructuralError("expiration subpacket with bad length")
return
}
sig.SigLifetimeSecs = new(uint32)
*sig.SigLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case exportableCertSubpacket:
if subpacket[0] == 0 {
err = errors.UnsupportedError("signature with non-exportable certification")
return
}
case trustSubpacket:
if len(subpacket) != 2 {
err = errors.StructuralError("trust subpacket with bad length")
return
}
// Trust level and amount, section 5.2.3.21
sig.TrustLevel = TrustLevel(subpacket[0])
sig.TrustAmount = TrustAmount(subpacket[1])
case regularExpressionSubpacket:
if len(subpacket) == 0 {
err = errors.StructuralError("regexp subpacket with bad length")
return
}
// Trust regular expression, section 5.2.3.22
// RFC specifies the string should be null-terminated; remove a null byte from the end
if subpacket[len(subpacket)-1] != 0x00 {
err = errors.StructuralError("expected regular expression to be null-terminated")
return
}
trustRegularExpression := string(subpacket[:len(subpacket)-1])
sig.TrustRegularExpression = &trustRegularExpression
case keyExpirationSubpacket:
// Key expiration time, section 5.2.3.13
if len(subpacket) != 4 {
err = errors.StructuralError("key expiration subpacket with bad length")
return
}
sig.KeyLifetimeSecs = new(uint32)
*sig.KeyLifetimeSecs = binary.BigEndian.Uint32(subpacket)
case prefSymmetricAlgosSubpacket:
// Preferred symmetric algorithms, section 5.2.3.14
sig.PreferredSymmetric = make([]byte, len(subpacket))
copy(sig.PreferredSymmetric, subpacket)
case issuerSubpacket:
// Issuer, section 5.2.3.12
if sig.Version > 4 && isHashed {
err = errors.StructuralError("issuer subpacket found in v6 key")
return
}
if len(subpacket) != 8 {
err = errors.StructuralError("issuer subpacket with bad length")
return
}
if sig.Version <= 4 {
sig.IssuerKeyId = new(uint64)
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket)
}
case notationDataSubpacket:
// Notation data, section 5.2.3.24
if len(subpacket) < 8 {
err = errors.StructuralError("notation data subpacket with bad length")
return
}
nameLength := uint32(subpacket[4])<<8 | uint32(subpacket[5])
valueLength := uint32(subpacket[6])<<8 | uint32(subpacket[7])
if len(subpacket) != int(nameLength)+int(valueLength)+8 {
err = errors.StructuralError("notation data subpacket with bad length")
return
}
notation := Notation{
IsHumanReadable: (subpacket[0] & 0x80) == 0x80,
Name: string(subpacket[8:(nameLength + 8)]),
Value: subpacket[(nameLength + 8):(valueLength + nameLength + 8)],
IsCritical: isCritical,
}
sig.Notations = append(sig.Notations, ¬ation)
case prefHashAlgosSubpacket:
// Preferred hash algorithms, section 5.2.3.16
sig.PreferredHash = make([]byte, len(subpacket))
copy(sig.PreferredHash, subpacket)
case prefCompressionSubpacket:
// Preferred compression algorithms, section 5.2.3.17
sig.PreferredCompression = make([]byte, len(subpacket))
copy(sig.PreferredCompression, subpacket)
case keyserverPrefsSubpacket:
// Keyserver preferences, section 5.2.3.25
sig.KeyserverPrefsValid = true
if len(subpacket) == 0 {
return
}
if subpacket[0]&KeyserverPrefNoModify != 0 {
sig.KeyserverPrefNoModify = true
}
case prefKeyserverSubpacket:
// Preferred keyserver, section 5.2.3.26
sig.PreferredKeyserver = string(subpacket)
case primaryUserIdSubpacket:
// Primary User ID, section 5.2.3.27
if len(subpacket) != 1 {
err = errors.StructuralError("primary user id subpacket with bad length")
return
}
sig.IsPrimaryId = new(bool)
if subpacket[0] > 0 {
*sig.IsPrimaryId = true
}
case keyFlagsSubpacket:
// Key flags, section 5.2.3.29
sig.FlagsValid = true
if len(subpacket) == 0 {
return
}
if subpacket[0]&KeyFlagCertify != 0 {
sig.FlagCertify = true
}
if subpacket[0]&KeyFlagSign != 0 {
sig.FlagSign = true
}
if subpacket[0]&KeyFlagEncryptCommunications != 0 {
sig.FlagEncryptCommunications = true
}
if subpacket[0]&KeyFlagEncryptStorage != 0 {
sig.FlagEncryptStorage = true
}
if subpacket[0]&KeyFlagSplitKey != 0 {
sig.FlagSplitKey = true
}
if subpacket[0]&KeyFlagAuthenticate != 0 {
sig.FlagAuthenticate = true
}
if subpacket[0]&KeyFlagGroupKey != 0 {
sig.FlagGroupKey = true
}
case signerUserIdSubpacket:
userId := string(subpacket)
sig.SignerUserId = &userId
case reasonForRevocationSubpacket:
// Reason For Revocation, section 5.2.3.31
if len(subpacket) == 0 {
err = errors.StructuralError("empty revocation reason subpacket")
return
}
sig.RevocationReason = new(ReasonForRevocation)
*sig.RevocationReason = NewReasonForRevocation(subpacket[0])
sig.RevocationReasonText = string(subpacket[1:])
case featuresSubpacket:
// Features subpacket, section 5.2.3.32 specifies a very general
// mechanism for OpenPGP implementations to signal support for new
// features.
if len(subpacket) > 0 {
if subpacket[0]&0x01 != 0 {
sig.SEIPDv1 = true
}
// 0x02 and 0x04 are reserved
if subpacket[0]&0x08 != 0 {
sig.SEIPDv2 = true
}
}
case embeddedSignatureSubpacket:
// Only usage is in signatures that cross-certify
// signing subkeys. section 5.2.3.34 describes the
// format, with its usage described in section 11.1
if sig.EmbeddedSignature != nil {
err = errors.StructuralError("Cannot have multiple embedded signatures")
return
}
sig.EmbeddedSignature = new(Signature)
if err := sig.EmbeddedSignature.parse(bytes.NewBuffer(subpacket)); err != nil {
return nil, err
}
if sigType := sig.EmbeddedSignature.SigType; sigType != SigTypePrimaryKeyBinding {
return nil, errors.StructuralError("cross-signature has unexpected type " + strconv.Itoa(int(sigType)))
}
case policyUriSubpacket:
// Policy URI, section 5.2.3.28
sig.PolicyURI = string(subpacket)
case issuerFingerprintSubpacket:
if len(subpacket) == 0 {
err = errors.StructuralError("empty issuer fingerprint subpacket")
return
}
v, l := subpacket[0], len(subpacket[1:])
if v >= 5 && l != 32 || v < 5 && l != 20 {
return nil, errors.StructuralError("bad fingerprint length")
}
sig.IssuerFingerprint = make([]byte, l)
copy(sig.IssuerFingerprint, subpacket[1:])
sig.IssuerKeyId = new(uint64)
if v >= 5 {
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[1:9])
} else {
*sig.IssuerKeyId = binary.BigEndian.Uint64(subpacket[13:21])
}
case intendedRecipientSubpacket:
// Intended Recipient Fingerprint, section 5.2.3.36
if len(subpacket) < 1 {
return nil, errors.StructuralError("invalid intended recipient fingerpring length")
}
version, length := subpacket[0], len(subpacket[1:])
if version >= 5 && length != 32 || version < 5 && length != 20 {
return nil, errors.StructuralError("invalid fingerprint length")
}
fingerprint := make([]byte, length)
copy(fingerprint, subpacket[1:])
sig.IntendedRecipients = append(sig.IntendedRecipients, &Recipient{int(version), fingerprint})
case prefCipherSuitesSubpacket:
// Preferred AEAD cipher suites, section 5.2.3.15
if len(subpacket)%2 != 0 {
err = errors.StructuralError("invalid aead cipher suite length")
return
}
sig.PreferredCipherSuites = make([][2]byte, len(subpacket)/2)
for i := 0; i < len(subpacket)/2; i++ {
sig.PreferredCipherSuites[i] = [2]uint8{subpacket[2*i], subpacket[2*i+1]}
}
default:
if isCritical {
err = errors.UnsupportedError("unknown critical signature subpacket type " + strconv.Itoa(int(packetType)))
return
}
}
return
Truncated:
err = errors.StructuralError("signature subpacket truncated")
return
}
// subpacketLengthLength returns the length, in bytes, of an encoded length value.
func subpacketLengthLength(length int) int {
if length < 192 {
return 1
}
if length < 16320 {
return 2
}
return 5
}
func (sig *Signature) CheckKeyIdOrFingerprint(pk *PublicKey) bool {
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 {
return bytes.Equal(sig.IssuerFingerprint, pk.Fingerprint)
}
return sig.IssuerKeyId != nil && *sig.IssuerKeyId == pk.KeyId
}
func (sig *Signature) CheckKeyIdOrFingerprintExplicit(fingerprint []byte, keyId uint64) bool {
if sig.IssuerFingerprint != nil && len(sig.IssuerFingerprint) >= 20 && fingerprint != nil {
return bytes.Equal(sig.IssuerFingerprint, fingerprint)
}
return sig.IssuerKeyId != nil && *sig.IssuerKeyId == keyId
}
// serializeSubpacketLength marshals the given length into to.
func serializeSubpacketLength(to []byte, length int) int {
// RFC 9580, Section 4.2.1.
if length < 192 {
to[0] = byte(length)
return 1
}
if length < 16320 {
length -= 192
to[0] = byte((length >> 8) + 192)
to[1] = byte(length)
return 2
}
to[0] = 255
to[1] = byte(length >> 24)
to[2] = byte(length >> 16)
to[3] = byte(length >> 8)
to[4] = byte(length)
return 5
}
// subpacketsLength returns the serialized length, in bytes, of the given
// subpackets.
func subpacketsLength(subpackets []outputSubpacket, hashed bool) (length int) {
for _, subpacket := range subpackets {
if subpacket.hashed == hashed {
length += subpacketLengthLength(len(subpacket.contents) + 1)
length += 1 // type byte
length += len(subpacket.contents)
}
}
return
}
// serializeSubpackets marshals the given subpackets into to.
func serializeSubpackets(to []byte, subpackets []outputSubpacket, hashed bool) {
for _, subpacket := range subpackets {
if subpacket.hashed == hashed {
n := serializeSubpacketLength(to, len(subpacket.contents)+1)
to[n] = byte(subpacket.subpacketType)
if subpacket.isCritical {
to[n] |= 0x80
}
to = to[1+n:]
n = copy(to, subpacket.contents)
to = to[n:]
}
}
}
// SigExpired returns whether sig is a signature that has expired or is created
// in the future.
func (sig *Signature) SigExpired(currentTime time.Time) bool {
if sig.CreationTime.Unix() > currentTime.Unix() {
return true
}
if sig.SigLifetimeSecs == nil || *sig.SigLifetimeSecs == 0 {
return false
}
expiry := sig.CreationTime.Add(time.Duration(*sig.SigLifetimeSecs) * time.Second)
return currentTime.Unix() > expiry.Unix()
}
// buildHashSuffix constructs the HashSuffix member of sig in preparation for signing.
func (sig *Signature) buildHashSuffix(hashedSubpackets []byte) (err error) {
var hashId byte
var ok bool
if sig.Version < 5 {
hashId, ok = algorithm.HashToHashIdWithSha1(sig.Hash)
} else {
hashId, ok = algorithm.HashToHashId(sig.Hash)
}
if !ok {
sig.HashSuffix = nil
return errors.InvalidArgumentError("hash cannot be represented in OpenPGP: " + strconv.Itoa(int(sig.Hash)))
}
hashedFields := bytes.NewBuffer([]byte{
uint8(sig.Version),
uint8(sig.SigType),
uint8(sig.PubKeyAlgo),
uint8(hashId),
})
hashedSubpacketsLength := len(hashedSubpackets)
if sig.Version == 6 {
// v6 signatures store the length in 4 octets
hashedFields.Write([]byte{
uint8(hashedSubpacketsLength >> 24),
uint8(hashedSubpacketsLength >> 16),
uint8(hashedSubpacketsLength >> 8),
uint8(hashedSubpacketsLength),
})
} else {
hashedFields.Write([]byte{
uint8(hashedSubpacketsLength >> 8),
uint8(hashedSubpacketsLength),
})
}
lenPrefix := hashedFields.Len()
hashedFields.Write(hashedSubpackets)
var l uint64 = uint64(lenPrefix + len(hashedSubpackets))
if sig.Version == 5 {
// v5 case
hashedFields.Write([]byte{0x05, 0xff})
hashedFields.Write([]byte{
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
})
} else {
// v4 and v6 case
hashedFields.Write([]byte{byte(sig.Version), 0xff})
hashedFields.Write([]byte{
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
})
}
sig.HashSuffix = make([]byte, hashedFields.Len())
copy(sig.HashSuffix, hashedFields.Bytes())
return
}
func (sig *Signature) signPrepareHash(h hash.Hash) (digest []byte, err error) {
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
hashedSubpackets := make([]byte, hashedSubpacketsLen)
serializeSubpackets(hashedSubpackets, sig.outSubpackets, true)
err = sig.buildHashSuffix(hashedSubpackets)
if err != nil {
return
}
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
sig.AddMetadataToHashSuffix()
}
h.Write(sig.HashSuffix)
digest = h.Sum(nil)
copy(sig.HashTag[:], digest)
return
}
// PrepareSign must be called to create a hash object before Sign for v6 signatures.
// The created hash object initially hashes a randomly generated salt
// as required by v6 signatures. The generated salt is stored in sig. If the signature is not v6,
// the method returns an empty hash object.
// See RFC 9580 Section 5.2.4.
func (sig *Signature) PrepareSign(config *Config) (hash.Hash, error) {
if !sig.Hash.Available() {
return nil, errors.UnsupportedError("hash function")
}
hasher := sig.Hash.New()
if sig.Version == 6 {
if sig.salt == nil {
var err error
sig.salt, err = SignatureSaltForHash(sig.Hash, config.Random())
if err != nil {
return nil, err
}
}
hasher.Write(sig.salt)
}
return hasher, nil
}
// SetSalt sets the signature salt for v6 signatures.
// Assumes salt is generated correctly and checks if length matches.
// If the signature is not v6, the method ignores the salt.
// Use PrepareSign whenever possible instead of generating and
// hashing the salt externally.
// See RFC 9580 Section 5.2.4.
func (sig *Signature) SetSalt(salt []byte) error {
if sig.Version == 6 {
expectedSaltLength, err := SaltLengthForHash(sig.Hash)
if err != nil {
return err
}
if salt == nil || len(salt) != expectedSaltLength {
return errors.InvalidArgumentError("unexpected salt size for the given hash algorithm")
}
sig.salt = salt
}
return nil
}
// PrepareVerify must be called to create a hash object before verifying v6 signatures.
// The created hash object initially hashes the internally stored salt.
// If the signature is not v6, the method returns an empty hash object.
// See RFC 9580 Section 5.2.4.
func (sig *Signature) PrepareVerify() (hash.Hash, error) {
if !sig.Hash.Available() {
return nil, errors.UnsupportedError("hash function")
}
hasher := sig.Hash.New()
if sig.Version == 6 {
if sig.salt == nil {
return nil, errors.StructuralError("v6 requires a salt for the hash to be signed")
}
hasher.Write(sig.salt)
}
return hasher, nil
}
// Sign signs a message with a private key. The hash, h, must contain
// the hash of the message to be signed and will be mutated by this function.
// On success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) Sign(h hash.Hash, priv *PrivateKey, config *Config) (err error) {
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
sig.Version = priv.PublicKey.Version
sig.IssuerFingerprint = priv.PublicKey.Fingerprint
if sig.Version < 6 && config.RandomizeSignaturesViaNotation() {
sig.removeNotationsWithName(SaltNotationName)
salt, err := SignatureSaltForHash(sig.Hash, config.Random())
if err != nil {
return err
}
notation := Notation{
Name: SaltNotationName,
Value: salt,
IsCritical: false,
IsHumanReadable: false,
}
sig.Notations = append(sig.Notations, ¬ation)
}
sig.outSubpackets, err = sig.buildSubpackets(priv.PublicKey)
if err != nil {
return err
}
digest, err := sig.signPrepareHash(h)
if err != nil {
return
}
switch priv.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
// supports both *rsa.PrivateKey and crypto.Signer
sigdata, err := priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
if err == nil {
sig.RSASignature = encoding.NewMPI(sigdata)
}
case PubKeyAlgoDSA:
dsaPriv := priv.PrivateKey.(*dsa.PrivateKey)
// Need to truncate hashBytes to match FIPS 186-3 section 4.6.
subgroupSize := (dsaPriv.Q.BitLen() + 7) / 8
if len(digest) > subgroupSize {
digest = digest[:subgroupSize]
}
r, s, err := dsa.Sign(config.Random(), dsaPriv, digest)
if err == nil {
sig.DSASigR = new(encoding.MPI).SetBig(r)
sig.DSASigS = new(encoding.MPI).SetBig(s)
}
case PubKeyAlgoECDSA:
var r, s *big.Int
if sk, ok := priv.PrivateKey.(*ecdsa.PrivateKey); ok {
r, s, err = ecdsa.Sign(config.Random(), sk, digest)
} else {
var b []byte
b, err = priv.PrivateKey.(crypto.Signer).Sign(config.Random(), digest, sig.Hash)
if err == nil {
r, s, err = unwrapECDSASig(b)
}
}
if err == nil {
sig.ECDSASigR = new(encoding.MPI).SetBig(r)
sig.ECDSASigS = new(encoding.MPI).SetBig(s)
}
case PubKeyAlgoEdDSA:
sk := priv.PrivateKey.(*eddsa.PrivateKey)
r, s, err := eddsa.Sign(sk, digest)
if err == nil {
sig.EdDSASigR = encoding.NewMPI(r)
sig.EdDSASigS = encoding.NewMPI(s)
}
case PubKeyAlgoEd25519:
sk := priv.PrivateKey.(*ed25519.PrivateKey)
signature, err := ed25519.Sign(sk, digest)
if err == nil {
sig.EdSig = signature
}
case PubKeyAlgoEd448:
sk := priv.PrivateKey.(*ed448.PrivateKey)
signature, err := ed448.Sign(sk, digest)
if err == nil {
sig.EdSig = signature
}
default:
err = errors.UnsupportedError("public key algorithm: " + strconv.Itoa(int(sig.PubKeyAlgo)))
}
return
}
// unwrapECDSASig parses the two integer components of an ASN.1-encoded ECDSA signature.
func unwrapECDSASig(b []byte) (r, s *big.Int, err error) {
var ecsdaSig struct {
R, S *big.Int
}
_, err = asn1.Unmarshal(b, &ecsdaSig)
if err != nil {
return
}
return ecsdaSig.R, ecsdaSig.S, nil
}
// SignUserId computes a signature from priv, asserting that pub is a valid
// key for the identity id. On success, the signature is stored in sig. Call
// Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) SignUserId(id string, pub *PublicKey, priv *PrivateKey, config *Config) error {
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
if err := userIdSignatureHash(id, pub, prepareHash); err != nil {
return err
}
return sig.Sign(prepareHash, priv, config)
}
// SignDirectKeyBinding computes a signature from priv
// On success, the signature is stored in sig.
// Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) SignDirectKeyBinding(pub *PublicKey, priv *PrivateKey, config *Config) error {
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
if err := directKeySignatureHash(pub, prepareHash); err != nil {
return err
}
return sig.Sign(prepareHash, priv, config)
}
// CrossSignKey computes a signature from signingKey on pub hashed using hashKey. On success,
// the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) CrossSignKey(pub *PublicKey, hashKey *PublicKey, signingKey *PrivateKey,
config *Config) error {
prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
h, err := keySignatureHash(hashKey, pub, prepareHash)
if err != nil {
return err
}
return sig.Sign(h, signingKey, config)
}
// SignKey computes a signature from priv, asserting that pub is a subkey. On
// success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) SignKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
if priv.Dummy() {
return errors.ErrDummyPrivateKey("dummy key found")
}
prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
h, err := keySignatureHash(&priv.PublicKey, pub, prepareHash)
if err != nil {
return err
}
return sig.Sign(h, priv, config)
}
// RevokeKey computes a revocation signature of pub using priv. On success, the signature is
// stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) RevokeKey(pub *PublicKey, priv *PrivateKey, config *Config) error {
prepareHash, err := sig.PrepareSign(config)
if err != nil {
return err
}
if err := keyRevocationHash(pub, prepareHash); err != nil {
return err
}
return sig.Sign(prepareHash, priv, config)
}
// RevokeSubkey computes a subkey revocation signature of pub using priv.
// On success, the signature is stored in sig. Call Serialize to write it out.
// If config is nil, sensible defaults will be used.
func (sig *Signature) RevokeSubkey(pub *PublicKey, priv *PrivateKey, config *Config) error {
// Identical to a subkey binding signature
return sig.SignKey(pub, priv, config)
}
// Serialize marshals sig to w. Sign, SignUserId or SignKey must have been
// called first.
func (sig *Signature) Serialize(w io.Writer) (err error) {
if len(sig.outSubpackets) == 0 {
sig.outSubpackets = sig.rawSubpackets
}
if sig.RSASignature == nil && sig.DSASigR == nil && sig.ECDSASigR == nil && sig.EdDSASigR == nil && sig.EdSig == nil {
return errors.InvalidArgumentError("Signature: need to call Sign, SignUserId or SignKey before Serialize")
}
sigLength := 0
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
sigLength = int(sig.RSASignature.EncodedLength())
case PubKeyAlgoDSA:
sigLength = int(sig.DSASigR.EncodedLength())
sigLength += int(sig.DSASigS.EncodedLength())
case PubKeyAlgoECDSA:
sigLength = int(sig.ECDSASigR.EncodedLength())
sigLength += int(sig.ECDSASigS.EncodedLength())
case PubKeyAlgoEdDSA:
sigLength = int(sig.EdDSASigR.EncodedLength())
sigLength += int(sig.EdDSASigS.EncodedLength())
case PubKeyAlgoEd25519:
sigLength = ed25519.SignatureSize
case PubKeyAlgoEd448:
sigLength = ed448.SignatureSize
default:
panic("impossible")
}
hashedSubpacketsLen := subpacketsLength(sig.outSubpackets, true)
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
length := 4 + /* length of version|signature type|public-key algorithm|hash algorithm */
2 /* length of hashed subpackets */ + hashedSubpacketsLen +
2 /* length of unhashed subpackets */ + unhashedSubpacketsLen +
2 /* hash tag */ + sigLength
if sig.Version == 6 {
length += 4 + /* the two length fields are four-octet instead of two */
1 + /* salt length */
len(sig.salt) /* length salt */
}
err = serializeHeader(w, packetTypeSignature, length)
if err != nil {
return
}
err = sig.serializeBody(w)
if err != nil {
return err
}
return
}
func (sig *Signature) serializeBody(w io.Writer) (err error) {
var fields []byte
if sig.Version == 6 {
// v6 signatures use 4 octets for length
hashedSubpacketsLen :=
uint32(uint32(sig.HashSuffix[4])<<24) |
uint32(uint32(sig.HashSuffix[5])<<16) |
uint32(uint32(sig.HashSuffix[6])<<8) |
uint32(sig.HashSuffix[7])
fields = sig.HashSuffix[:8+hashedSubpacketsLen]
} else {
hashedSubpacketsLen := uint16(uint16(sig.HashSuffix[4])<<8) |
uint16(sig.HashSuffix[5])
fields = sig.HashSuffix[:6+hashedSubpacketsLen]
}
_, err = w.Write(fields)
if err != nil {
return
}
unhashedSubpacketsLen := subpacketsLength(sig.outSubpackets, false)
var unhashedSubpackets []byte
if sig.Version == 6 {
unhashedSubpackets = make([]byte, 4+unhashedSubpacketsLen)
unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 24)
unhashedSubpackets[1] = byte(unhashedSubpacketsLen >> 16)
unhashedSubpackets[2] = byte(unhashedSubpacketsLen >> 8)
unhashedSubpackets[3] = byte(unhashedSubpacketsLen)
serializeSubpackets(unhashedSubpackets[4:], sig.outSubpackets, false)
} else {
unhashedSubpackets = make([]byte, 2+unhashedSubpacketsLen)
unhashedSubpackets[0] = byte(unhashedSubpacketsLen >> 8)
unhashedSubpackets[1] = byte(unhashedSubpacketsLen)
serializeSubpackets(unhashedSubpackets[2:], sig.outSubpackets, false)
}
_, err = w.Write(unhashedSubpackets)
if err != nil {
return
}
_, err = w.Write(sig.HashTag[:])
if err != nil {
return
}
if sig.Version == 6 {
// write salt for v6 signatures
_, err = w.Write([]byte{uint8(len(sig.salt))})
if err != nil {
return
}
_, err = w.Write(sig.salt)
if err != nil {
return
}
}
switch sig.PubKeyAlgo {
case PubKeyAlgoRSA, PubKeyAlgoRSASignOnly:
_, err = w.Write(sig.RSASignature.EncodedBytes())
case PubKeyAlgoDSA:
if _, err = w.Write(sig.DSASigR.EncodedBytes()); err != nil {
return
}
_, err = w.Write(sig.DSASigS.EncodedBytes())
case PubKeyAlgoECDSA:
if _, err = w.Write(sig.ECDSASigR.EncodedBytes()); err != nil {
return
}
_, err = w.Write(sig.ECDSASigS.EncodedBytes())
case PubKeyAlgoEdDSA:
if _, err = w.Write(sig.EdDSASigR.EncodedBytes()); err != nil {
return
}
_, err = w.Write(sig.EdDSASigS.EncodedBytes())
case PubKeyAlgoEd25519:
err = ed25519.WriteSignature(w, sig.EdSig)
case PubKeyAlgoEd448:
err = ed448.WriteSignature(w, sig.EdSig)
default:
panic("impossible")
}
return
}
// outputSubpacket represents a subpacket to be marshaled.
type outputSubpacket struct {
hashed bool // true if this subpacket is in the hashed area.
subpacketType signatureSubpacketType
isCritical bool
contents []byte
}
func (sig *Signature) buildSubpackets(issuer PublicKey) (subpackets []outputSubpacket, err error) {
creationTime := make([]byte, 4)
binary.BigEndian.PutUint32(creationTime, uint32(sig.CreationTime.Unix()))
// Signature Creation Time
subpackets = append(subpackets, outputSubpacket{true, creationTimeSubpacket, true, creationTime})
// Signature Expiration Time
if sig.SigLifetimeSecs != nil && *sig.SigLifetimeSecs != 0 {
sigLifetime := make([]byte, 4)
binary.BigEndian.PutUint32(sigLifetime, *sig.SigLifetimeSecs)
subpackets = append(subpackets, outputSubpacket{true, signatureExpirationSubpacket, true, sigLifetime})
}
// Trust Signature
if sig.TrustLevel != 0 {
subpackets = append(subpackets, outputSubpacket{true, trustSubpacket, true, []byte{byte(sig.TrustLevel), byte(sig.TrustAmount)}})
}
// Regular Expression
if sig.TrustRegularExpression != nil {
// RFC specifies the string should be null-terminated; add a null byte to the end
subpackets = append(subpackets, outputSubpacket{true, regularExpressionSubpacket, true, []byte(*sig.TrustRegularExpression + "\000")})
}
// Key Expiration Time
if sig.KeyLifetimeSecs != nil && *sig.KeyLifetimeSecs != 0 {
keyLifetime := make([]byte, 4)
binary.BigEndian.PutUint32(keyLifetime, *sig.KeyLifetimeSecs)
subpackets = append(subpackets, outputSubpacket{true, keyExpirationSubpacket, true, keyLifetime})
}
// Preferred Symmetric Ciphers for v1 SEIPD
if len(sig.PreferredSymmetric) > 0 {
subpackets = append(subpackets, outputSubpacket{true, prefSymmetricAlgosSubpacket, false, sig.PreferredSymmetric})
}
// Issuer Key ID
if sig.IssuerKeyId != nil && sig.Version == 4 {
keyId := make([]byte, 8)
binary.BigEndian.PutUint64(keyId, *sig.IssuerKeyId)
subpackets = append(subpackets, outputSubpacket{true, issuerSubpacket, true, keyId})
}
// Notation Data
for _, notation := range sig.Notations {
subpackets = append(
subpackets,
outputSubpacket{
true,
notationDataSubpacket,
notation.IsCritical,
notation.getData(),
})
}
// Preferred Hash Algorithms
if len(sig.PreferredHash) > 0 {
subpackets = append(subpackets, outputSubpacket{true, prefHashAlgosSubpacket, false, sig.PreferredHash})
}
// Preferred Compression Algorithms
if len(sig.PreferredCompression) > 0 {
subpackets = append(subpackets, outputSubpacket{true, prefCompressionSubpacket, false, sig.PreferredCompression})
}
// Keyserver Preferences
// Keyserver preferences may only appear in self-signatures or certification signatures.
if sig.KeyserverPrefsValid {
var prefs byte
if sig.KeyserverPrefNoModify {
prefs |= KeyserverPrefNoModify
}
subpackets = append(subpackets, outputSubpacket{true, keyserverPrefsSubpacket, false, []byte{prefs}})
}
// Preferred Keyserver
if len(sig.PreferredKeyserver) > 0 {
subpackets = append(subpackets, outputSubpacket{true, prefKeyserverSubpacket, false, []uint8(sig.PreferredKeyserver)})
}
// Primary User ID
if sig.IsPrimaryId != nil && *sig.IsPrimaryId {
subpackets = append(subpackets, outputSubpacket{true, primaryUserIdSubpacket, false, []byte{1}})
}
// Policy URI
if len(sig.PolicyURI) > 0 {
subpackets = append(subpackets, outputSubpacket{true, policyUriSubpacket, false, []uint8(sig.PolicyURI)})
}
// Key Flags
// Key flags may only appear in self-signatures or certification signatures.
if sig.FlagsValid {
var flags byte
if sig.FlagCertify {
flags |= KeyFlagCertify
}
if sig.FlagSign {
flags |= KeyFlagSign
}
if sig.FlagEncryptCommunications {
flags |= KeyFlagEncryptCommunications
}
if sig.FlagEncryptStorage {
flags |= KeyFlagEncryptStorage
}
if sig.FlagSplitKey {
flags |= KeyFlagSplitKey
}
if sig.FlagAuthenticate {
flags |= KeyFlagAuthenticate
}
if sig.FlagGroupKey {
flags |= KeyFlagGroupKey
}
subpackets = append(subpackets, outputSubpacket{true, keyFlagsSubpacket, true, []byte{flags}})
}
// Signer's User ID
if sig.SignerUserId != nil {
subpackets = append(subpackets, outputSubpacket{true, signerUserIdSubpacket, false, []byte(*sig.SignerUserId)})
}
// Reason for Revocation
// Revocation reason appears only in revocation signatures and is serialized as per section 5.2.3.31.
if sig.RevocationReason != nil {
subpackets = append(subpackets, outputSubpacket{true, reasonForRevocationSubpacket, true,
append([]uint8{uint8(*sig.RevocationReason)}, []uint8(sig.RevocationReasonText)...)})
}
// Features
var features = byte(0x00)
if sig.SEIPDv1 {
features |= 0x01
}
if sig.SEIPDv2 {
features |= 0x08
}
if features != 0x00 {
subpackets = append(subpackets, outputSubpacket{true, featuresSubpacket, false, []byte{features}})
}
// Embedded Signature
// EmbeddedSignature appears only in subkeys capable of signing and is serialized as per section 5.2.3.34.
if sig.EmbeddedSignature != nil {
var buf bytes.Buffer
err = sig.EmbeddedSignature.serializeBody(&buf)
if err != nil {
return
}
subpackets = append(subpackets, outputSubpacket{true, embeddedSignatureSubpacket, true, buf.Bytes()})
}
// Issuer Fingerprint
if sig.IssuerFingerprint != nil {
contents := append([]uint8{uint8(issuer.Version)}, sig.IssuerFingerprint...)
subpackets = append(subpackets, outputSubpacket{true, issuerFingerprintSubpacket, sig.Version >= 5, contents})
}
// Intended Recipient Fingerprint
for _, recipient := range sig.IntendedRecipients {
subpackets = append(
subpackets,
outputSubpacket{
true,
intendedRecipientSubpacket,
false,
recipient.Serialize(),
})
}
// Preferred AEAD Ciphersuites
if len(sig.PreferredCipherSuites) > 0 {
serialized := make([]byte, len(sig.PreferredCipherSuites)*2)
for i, cipherSuite := range sig.PreferredCipherSuites {
serialized[2*i] = cipherSuite[0]
serialized[2*i+1] = cipherSuite[1]
}
subpackets = append(subpackets, outputSubpacket{true, prefCipherSuitesSubpacket, false, serialized})
}
return
}
// AddMetadataToHashSuffix modifies the current hash suffix to include metadata
// (format, filename, and time). Version 5 keys protect this data including it
// in the hash computation. See section 5.2.4.
func (sig *Signature) AddMetadataToHashSuffix() {
if sig == nil || sig.Version != 5 {
return
}
if sig.SigType != 0x00 && sig.SigType != 0x01 {
return
}
lit := sig.Metadata
if lit == nil {
// This will translate into six 0x00 bytes.
lit = &LiteralData{}
}
// Extract the current byte count
n := sig.HashSuffix[len(sig.HashSuffix)-8:]
l := uint64(
uint64(n[0])<<56 | uint64(n[1])<<48 | uint64(n[2])<<40 | uint64(n[3])<<32 |
uint64(n[4])<<24 | uint64(n[5])<<16 | uint64(n[6])<<8 | uint64(n[7]))
suffix := bytes.NewBuffer(nil)
suffix.Write(sig.HashSuffix[:l])
// Add the metadata
var buf [4]byte
buf[0] = lit.Format
fileName := lit.FileName
if len(lit.FileName) > 255 {
fileName = fileName[:255]
}
buf[1] = byte(len(fileName))
suffix.Write(buf[:2])
suffix.Write([]byte(lit.FileName))
binary.BigEndian.PutUint32(buf[:], lit.Time)
suffix.Write(buf[:])
suffix.Write([]byte{0x05, 0xff})
suffix.Write([]byte{
uint8(l >> 56), uint8(l >> 48), uint8(l >> 40), uint8(l >> 32),
uint8(l >> 24), uint8(l >> 16), uint8(l >> 8), uint8(l),
})
sig.HashSuffix = suffix.Bytes()
}
// SaltLengthForHash selects the required salt length for the given hash algorithm,
// as per Table 23 (Hash algorithm registry) of the crypto refresh.
// See RFC 9580 Section 9.5.
func SaltLengthForHash(hash crypto.Hash) (int, error) {
switch hash {
case crypto.SHA256, crypto.SHA224, crypto.SHA3_256:
return 16, nil
case crypto.SHA384:
return 24, nil
case crypto.SHA512, crypto.SHA3_512:
return 32, nil
default:
return 0, errors.UnsupportedError("hash function not supported for V6 signatures")
}
}
// SignatureSaltForHash generates a random signature salt
// with the length for the given hash algorithm.
// See RFC 9580 Section 9.5.
func SignatureSaltForHash(hash crypto.Hash, randReader io.Reader) ([]byte, error) {
saltLength, err := SaltLengthForHash(hash)
if err != nil {
return nil, err
}
salt := make([]byte, saltLength)
_, err = io.ReadFull(randReader, salt)
if err != nil {
return nil, err
}
return salt, nil
}
// removeNotationsWithName removes all notations in this signature with the given name.
func (sig *Signature) removeNotationsWithName(name string) {
if sig == nil || sig.Notations == nil {
return
}
updatedNotations := make([]*Notation, 0, len(sig.Notations))
for _, notation := range sig.Notations {
if notation.Name != name {
updatedNotations = append(updatedNotations, notation)
}
}
sig.Notations = updatedNotations
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetric_key_encrypted.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"crypto/cipher"
"crypto/sha256"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/s2k"
"golang.org/x/crypto/hkdf"
)
// This is the largest session key that we'll support. Since at most 256-bit cipher
// is supported in OpenPGP, this is large enough to contain also the auth tag.
const maxSessionKeySizeInBytes = 64
// SymmetricKeyEncrypted represents a passphrase protected session key. See RFC
// 4880, section 5.3.
type SymmetricKeyEncrypted struct {
Version int
CipherFunc CipherFunction
Mode AEADMode
s2k func(out, in []byte)
iv []byte
encryptedKey []byte // Contains also the authentication tag for AEAD
}
// parse parses an SymmetricKeyEncrypted packet as specified in
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#name-symmetric-key-encrypted-ses
func (ske *SymmetricKeyEncrypted) parse(r io.Reader) error {
var buf [1]byte
// Version
if _, err := readFull(r, buf[:]); err != nil {
return err
}
ske.Version = int(buf[0])
if ske.Version != 4 && ske.Version != 5 && ske.Version != 6 {
return errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
}
if V5Disabled && ske.Version == 5 {
return errors.UnsupportedError("support for parsing v5 entities is disabled; build with `-tags v5` if needed")
}
if ske.Version > 5 {
// Scalar octet count
if _, err := readFull(r, buf[:]); err != nil {
return err
}
}
// Cipher function
if _, err := readFull(r, buf[:]); err != nil {
return err
}
ske.CipherFunc = CipherFunction(buf[0])
if !ske.CipherFunc.IsSupported() {
return errors.UnsupportedError("unknown cipher: " + strconv.Itoa(int(buf[0])))
}
if ske.Version >= 5 {
// AEAD mode
if _, err := readFull(r, buf[:]); err != nil {
return errors.StructuralError("cannot read AEAD octet from packet")
}
ske.Mode = AEADMode(buf[0])
}
if ske.Version > 5 {
// Scalar octet count
if _, err := readFull(r, buf[:]); err != nil {
return err
}
}
var err error
if ske.s2k, err = s2k.Parse(r); err != nil {
if _, ok := err.(errors.ErrDummyPrivateKey); ok {
return errors.UnsupportedError("missing key GNU extension in session key")
}
return err
}
if ske.Version >= 5 {
// AEAD IV
iv := make([]byte, ske.Mode.IvLength())
_, err := readFull(r, iv)
if err != nil {
return errors.StructuralError("cannot read AEAD IV")
}
ske.iv = iv
}
encryptedKey := make([]byte, maxSessionKeySizeInBytes)
// The session key may follow. We just have to try and read to find
// out. If it exists then we limit it to maxSessionKeySizeInBytes.
n, err := readFull(r, encryptedKey)
if err != nil && err != io.ErrUnexpectedEOF {
return err
}
if n != 0 {
if n == maxSessionKeySizeInBytes {
return errors.UnsupportedError("oversized encrypted session key")
}
ske.encryptedKey = encryptedKey[:n]
}
return nil
}
// Decrypt attempts to decrypt an encrypted session key and returns the key and
// the cipher to use when decrypting a subsequent Symmetrically Encrypted Data
// packet.
func (ske *SymmetricKeyEncrypted) Decrypt(passphrase []byte) ([]byte, CipherFunction, error) {
key := make([]byte, ske.CipherFunc.KeySize())
ske.s2k(key, passphrase)
if len(ske.encryptedKey) == 0 {
return key, ske.CipherFunc, nil
}
switch ske.Version {
case 4:
plaintextKey, cipherFunc, err := ske.decryptV4(key)
return plaintextKey, cipherFunc, err
case 5, 6:
plaintextKey, err := ske.aeadDecrypt(ske.Version, key)
return plaintextKey, CipherFunction(0), err
}
err := errors.UnsupportedError("unknown SymmetricKeyEncrypted version")
return nil, CipherFunction(0), err
}
func (ske *SymmetricKeyEncrypted) decryptV4(key []byte) ([]byte, CipherFunction, error) {
// the IV is all zeros
iv := make([]byte, ske.CipherFunc.blockSize())
c := cipher.NewCFBDecrypter(ske.CipherFunc.new(key), iv)
plaintextKey := make([]byte, len(ske.encryptedKey))
c.XORKeyStream(plaintextKey, ske.encryptedKey)
cipherFunc := CipherFunction(plaintextKey[0])
if cipherFunc.blockSize() == 0 {
return nil, ske.CipherFunc, errors.UnsupportedError(
"unknown cipher: " + strconv.Itoa(int(cipherFunc)))
}
plaintextKey = plaintextKey[1:]
if len(plaintextKey) != cipherFunc.KeySize() {
return nil, cipherFunc, errors.StructuralError(
"length of decrypted key not equal to cipher keysize")
}
return plaintextKey, cipherFunc, nil
}
func (ske *SymmetricKeyEncrypted) aeadDecrypt(version int, key []byte) ([]byte, error) {
adata := []byte{0xc3, byte(version), byte(ske.CipherFunc), byte(ske.Mode)}
aead := getEncryptedKeyAeadInstance(ske.CipherFunc, ske.Mode, key, adata, version)
plaintextKey, err := aead.Open(nil, ske.iv, ske.encryptedKey, adata)
if err != nil {
return nil, err
}
return plaintextKey, nil
}
// SerializeSymmetricKeyEncrypted serializes a symmetric key packet to w.
// The packet contains a random session key, encrypted by a key derived from
// the given passphrase. The session key is returned and must be passed to
// SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
func SerializeSymmetricKeyEncrypted(w io.Writer, passphrase []byte, config *Config) (key []byte, err error) {
cipherFunc := config.Cipher()
sessionKey := make([]byte, cipherFunc.KeySize())
_, err = io.ReadFull(config.Random(), sessionKey)
if err != nil {
return
}
err = SerializeSymmetricKeyEncryptedReuseKey(w, sessionKey, passphrase, config)
if err != nil {
return
}
key = sessionKey
return
}
// SerializeSymmetricKeyEncryptedReuseKey serializes a symmetric key packet to w.
// The packet contains the given session key, encrypted by a key derived from
// the given passphrase. The returned session key must be passed to
// SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
// Deprecated: Use SerializeSymmetricKeyEncryptedAEADReuseKey instead.
func SerializeSymmetricKeyEncryptedReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, config *Config) (err error) {
return SerializeSymmetricKeyEncryptedAEADReuseKey(w, sessionKey, passphrase, config.AEAD() != nil, config)
}
// SerializeSymmetricKeyEncryptedAEADReuseKey serializes a symmetric key packet to w.
// The packet contains the given session key, encrypted by a key derived from
// the given passphrase. The returned session key must be passed to
// SerializeSymmetricallyEncrypted.
// If aeadSupported is set, SKESK v6 is used, otherwise v4.
// Note: aeadSupported MUST match the value passed to SerializeSymmetricallyEncrypted.
// If config is nil, sensible defaults will be used.
func SerializeSymmetricKeyEncryptedAEADReuseKey(w io.Writer, sessionKey []byte, passphrase []byte, aeadSupported bool, config *Config) (err error) {
var version int
if aeadSupported {
version = 6
} else {
version = 4
}
cipherFunc := config.Cipher()
// cipherFunc must be AES
if !cipherFunc.IsSupported() || cipherFunc < CipherAES128 || cipherFunc > CipherAES256 {
return errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(cipherFunc)))
}
keySize := cipherFunc.KeySize()
s2kBuf := new(bytes.Buffer)
keyEncryptingKey := make([]byte, keySize)
// s2k.Serialize salts and stretches the passphrase, and writes the
// resulting key to keyEncryptingKey and the s2k descriptor to s2kBuf.
err = s2k.Serialize(s2kBuf, keyEncryptingKey, config.Random(), passphrase, config.S2K())
if err != nil {
return
}
s2kBytes := s2kBuf.Bytes()
var packetLength int
switch version {
case 4:
packetLength = 2 /* header */ + len(s2kBytes) + 1 /* cipher type */ + keySize
case 5, 6:
ivLen := config.AEAD().Mode().IvLength()
tagLen := config.AEAD().Mode().TagLength()
packetLength = 3 + len(s2kBytes) + ivLen + keySize + tagLen
}
if version > 5 {
packetLength += 2 // additional octet count fields
}
err = serializeHeader(w, packetTypeSymmetricKeyEncrypted, packetLength)
if err != nil {
return
}
// Symmetric Key Encrypted Version
buf := []byte{byte(version)}
if version > 5 {
// Scalar octet count
buf = append(buf, byte(3+len(s2kBytes)+config.AEAD().Mode().IvLength()))
}
// Cipher function
buf = append(buf, byte(cipherFunc))
if version >= 5 {
// AEAD mode
buf = append(buf, byte(config.AEAD().Mode()))
}
if version > 5 {
// Scalar octet count
buf = append(buf, byte(len(s2kBytes)))
}
_, err = w.Write(buf)
if err != nil {
return
}
_, err = w.Write(s2kBytes)
if err != nil {
return
}
switch version {
case 4:
iv := make([]byte, cipherFunc.blockSize())
c := cipher.NewCFBEncrypter(cipherFunc.new(keyEncryptingKey), iv)
encryptedCipherAndKey := make([]byte, keySize+1)
c.XORKeyStream(encryptedCipherAndKey, buf[1:])
c.XORKeyStream(encryptedCipherAndKey[1:], sessionKey)
_, err = w.Write(encryptedCipherAndKey)
if err != nil {
return
}
case 5, 6:
mode := config.AEAD().Mode()
adata := []byte{0xc3, byte(version), byte(cipherFunc), byte(mode)}
aead := getEncryptedKeyAeadInstance(cipherFunc, mode, keyEncryptingKey, adata, version)
// Sample iv using random reader
iv := make([]byte, config.AEAD().Mode().IvLength())
_, err = io.ReadFull(config.Random(), iv)
if err != nil {
return
}
// Seal and write (encryptedData includes auth. tag)
encryptedData := aead.Seal(nil, iv, sessionKey, adata)
_, err = w.Write(iv)
if err != nil {
return
}
_, err = w.Write(encryptedData)
if err != nil {
return
}
}
return
}
func getEncryptedKeyAeadInstance(c CipherFunction, mode AEADMode, inputKey, associatedData []byte, version int) (aead cipher.AEAD) {
var blockCipher cipher.Block
if version > 5 {
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, associatedData)
encryptionKey := make([]byte, c.KeySize())
_, _ = readFull(hkdfReader, encryptionKey)
blockCipher = c.new(encryptionKey)
} else {
blockCipher = c.new(inputKey)
}
return mode.new(blockCipher)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"io"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
const aeadSaltSize = 32
// SymmetricallyEncrypted represents a symmetrically encrypted byte string. The
// encrypted Contents will consist of more OpenPGP packets. See RFC 4880,
// sections 5.7 and 5.13.
type SymmetricallyEncrypted struct {
Version int
Contents io.Reader // contains tag for version 2
IntegrityProtected bool // If true it is type 18 (with MDC or AEAD). False is packet type 9
// Specific to version 1
prefix []byte
// Specific to version 2
Cipher CipherFunction
Mode AEADMode
ChunkSizeByte byte
Salt [aeadSaltSize]byte
}
const (
symmetricallyEncryptedVersionMdc = 1
symmetricallyEncryptedVersionAead = 2
)
func (se *SymmetricallyEncrypted) parse(r io.Reader) error {
if se.IntegrityProtected {
// See RFC 4880, section 5.13.
var buf [1]byte
_, err := readFull(r, buf[:])
if err != nil {
return err
}
switch buf[0] {
case symmetricallyEncryptedVersionMdc:
se.Version = symmetricallyEncryptedVersionMdc
case symmetricallyEncryptedVersionAead:
se.Version = symmetricallyEncryptedVersionAead
if err := se.parseAead(r); err != nil {
return err
}
default:
return errors.UnsupportedError("unknown SymmetricallyEncrypted version")
}
}
se.Contents = r
return nil
}
// Decrypt returns a ReadCloser, from which the decrypted Contents of the
// packet can be read. An incorrect key will only be detected after trying
// to decrypt the entire data.
func (se *SymmetricallyEncrypted) Decrypt(c CipherFunction, key []byte) (io.ReadCloser, error) {
if se.Version == symmetricallyEncryptedVersionAead {
return se.decryptAead(key)
}
return se.decryptMdc(c, key)
}
// SerializeSymmetricallyEncrypted serializes a symmetrically encrypted packet
// to w and returns a WriteCloser to which the to-be-encrypted packets can be
// written.
// If aeadSupported is set to true, SEIPDv2 is used with the indicated CipherSuite.
// Otherwise, SEIPDv1 is used with the indicated CipherFunction.
// Note: aeadSupported MUST match the value passed to SerializeEncryptedKeyAEAD
// and/or SerializeSymmetricKeyEncryptedAEADReuseKey.
// If config is nil, sensible defaults will be used.
func SerializeSymmetricallyEncrypted(w io.Writer, c CipherFunction, aeadSupported bool, cipherSuite CipherSuite, key []byte, config *Config) (Contents io.WriteCloser, err error) {
writeCloser := noOpCloser{w}
ciphertext, err := serializeStreamHeader(writeCloser, packetTypeSymmetricallyEncryptedIntegrityProtected)
if err != nil {
return
}
if aeadSupported {
return serializeSymmetricallyEncryptedAead(ciphertext, cipherSuite, config.AEADConfig.ChunkSizeByte(), config.Random(), key)
}
return serializeSymmetricallyEncryptedMdc(ciphertext, c, key, config)
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_aead.go
================================================
// Copyright 2023 Proton AG. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto/cipher"
"crypto/sha256"
"fmt"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"golang.org/x/crypto/hkdf"
)
// parseAead parses a V2 SEIPD packet (AEAD) as specified in
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func (se *SymmetricallyEncrypted) parseAead(r io.Reader) error {
headerData := make([]byte, 3)
if n, err := io.ReadFull(r, headerData); n < 3 {
return errors.StructuralError("could not read aead header: " + err.Error())
}
// Cipher
se.Cipher = CipherFunction(headerData[0])
// cipherFunc must have block size 16 to use AEAD
if se.Cipher.blockSize() != 16 {
return errors.UnsupportedError("invalid aead cipher: " + strconv.Itoa(int(se.Cipher)))
}
// Mode
se.Mode = AEADMode(headerData[1])
if se.Mode.TagLength() == 0 {
return errors.UnsupportedError("unknown aead mode: " + strconv.Itoa(int(se.Mode)))
}
// Chunk size
se.ChunkSizeByte = headerData[2]
if se.ChunkSizeByte > 16 {
return errors.UnsupportedError("invalid aead chunk size byte: " + strconv.Itoa(int(se.ChunkSizeByte)))
}
// Salt
if n, err := io.ReadFull(r, se.Salt[:]); n < aeadSaltSize {
return errors.StructuralError("could not read aead salt: " + err.Error())
}
return nil
}
// associatedData for chunks: tag, version, cipher, mode, chunk size byte
func (se *SymmetricallyEncrypted) associatedData() []byte {
return []byte{
0xD2,
symmetricallyEncryptedVersionAead,
byte(se.Cipher),
byte(se.Mode),
se.ChunkSizeByte,
}
}
// decryptAead decrypts a V2 SEIPD packet (AEAD) as specified in
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func (se *SymmetricallyEncrypted) decryptAead(inputKey []byte) (io.ReadCloser, error) {
if se.Cipher.KeySize() != len(inputKey) {
return nil, errors.StructuralError(fmt.Sprintf("invalid session key length for cipher: got %d bytes, but expected %d bytes", len(inputKey), se.Cipher.KeySize()))
}
aead, nonce := getSymmetricallyEncryptedAeadInstance(se.Cipher, se.Mode, inputKey, se.Salt[:], se.associatedData())
// Carry the first tagLen bytes
chunkSize := decodeAEADChunkSize(se.ChunkSizeByte)
tagLen := se.Mode.TagLength()
chunkBytes := make([]byte, chunkSize+tagLen*2)
peekedBytes := chunkBytes[chunkSize+tagLen:]
n, err := io.ReadFull(se.Contents, peekedBytes)
if n < tagLen || (err != nil && err != io.EOF) {
return nil, errors.StructuralError("not enough data to decrypt:" + err.Error())
}
return &aeadDecrypter{
aeadCrypter: aeadCrypter{
aead: aead,
chunkSize: decodeAEADChunkSize(se.ChunkSizeByte),
nonce: nonce,
associatedData: se.associatedData(),
chunkIndex: nonce[len(nonce)-8:],
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
},
reader: se.Contents,
chunkBytes: chunkBytes,
peekedBytes: peekedBytes,
}, nil
}
// serializeSymmetricallyEncryptedAead encrypts to a writer a V2 SEIPD packet (AEAD) as specified in
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-5.13.2
func serializeSymmetricallyEncryptedAead(ciphertext io.WriteCloser, cipherSuite CipherSuite, chunkSizeByte byte, rand io.Reader, inputKey []byte) (Contents io.WriteCloser, err error) {
// cipherFunc must have block size 16 to use AEAD
if cipherSuite.Cipher.blockSize() != 16 {
return nil, errors.InvalidArgumentError("invalid aead cipher function")
}
if cipherSuite.Cipher.KeySize() != len(inputKey) {
return nil, errors.InvalidArgumentError("error in aead serialization: bad key length")
}
// Data for en/decryption: tag, version, cipher, aead mode, chunk size
prefix := []byte{
0xD2,
symmetricallyEncryptedVersionAead,
byte(cipherSuite.Cipher),
byte(cipherSuite.Mode),
chunkSizeByte,
}
// Write header (that correspond to prefix except first byte)
n, err := ciphertext.Write(prefix[1:])
if err != nil || n < 4 {
return nil, err
}
// Random salt
salt := make([]byte, aeadSaltSize)
if _, err := io.ReadFull(rand, salt); err != nil {
return nil, err
}
if _, err := ciphertext.Write(salt); err != nil {
return nil, err
}
aead, nonce := getSymmetricallyEncryptedAeadInstance(cipherSuite.Cipher, cipherSuite.Mode, inputKey, salt, prefix)
chunkSize := decodeAEADChunkSize(chunkSizeByte)
tagLen := aead.Overhead()
chunkBytes := make([]byte, chunkSize+tagLen)
return &aeadEncrypter{
aeadCrypter: aeadCrypter{
aead: aead,
chunkSize: chunkSize,
associatedData: prefix,
nonce: nonce,
chunkIndex: nonce[len(nonce)-8:],
packetTag: packetTypeSymmetricallyEncryptedIntegrityProtected,
},
writer: ciphertext,
chunkBytes: chunkBytes,
}, nil
}
func getSymmetricallyEncryptedAeadInstance(c CipherFunction, mode AEADMode, inputKey, salt, associatedData []byte) (aead cipher.AEAD, nonce []byte) {
hkdfReader := hkdf.New(sha256.New, inputKey, salt, associatedData)
encryptionKey := make([]byte, c.KeySize())
_, _ = readFull(hkdfReader, encryptionKey)
nonce = make([]byte, mode.IvLength())
// Last 64 bits of nonce are the counter
_, _ = readFull(hkdfReader, nonce[:len(nonce)-8])
blockCipher := c.new(encryptionKey)
aead = mode.new(blockCipher)
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/symmetrically_encrypted_mdc.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"crypto/cipher"
"crypto/sha1"
"crypto/subtle"
"hash"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
)
// seMdcReader wraps an io.Reader with a no-op Close method.
type seMdcReader struct {
in io.Reader
}
func (ser seMdcReader) Read(buf []byte) (int, error) {
return ser.in.Read(buf)
}
func (ser seMdcReader) Close() error {
return nil
}
func (se *SymmetricallyEncrypted) decryptMdc(c CipherFunction, key []byte) (io.ReadCloser, error) {
if !c.IsSupported() {
return nil, errors.UnsupportedError("unsupported cipher: " + strconv.Itoa(int(c)))
}
if len(key) != c.KeySize() {
return nil, errors.InvalidArgumentError("SymmetricallyEncrypted: incorrect key length")
}
if se.prefix == nil {
se.prefix = make([]byte, c.blockSize()+2)
_, err := readFull(se.Contents, se.prefix)
if err != nil {
return nil, err
}
} else if len(se.prefix) != c.blockSize()+2 {
return nil, errors.InvalidArgumentError("can't try ciphers with different block lengths")
}
ocfbResync := OCFBResync
if se.IntegrityProtected {
// MDC packets use a different form of OCFB mode.
ocfbResync = OCFBNoResync
}
s := NewOCFBDecrypter(c.new(key), se.prefix, ocfbResync)
plaintext := cipher.StreamReader{S: s, R: se.Contents}
if se.IntegrityProtected {
// IntegrityProtected packets have an embedded hash that we need to check.
h := sha1.New()
h.Write(se.prefix)
return &seMDCReader{in: plaintext, h: h}, nil
}
// Otherwise, we just need to wrap plaintext so that it's a valid ReadCloser.
return seMdcReader{plaintext}, nil
}
const mdcTrailerSize = 1 /* tag byte */ + 1 /* length byte */ + sha1.Size
// An seMDCReader wraps an io.Reader, maintains a running hash and keeps hold
// of the most recent 22 bytes (mdcTrailerSize). Upon EOF, those bytes form an
// MDC packet containing a hash of the previous Contents which is checked
// against the running hash. See RFC 4880, section 5.13.
type seMDCReader struct {
in io.Reader
h hash.Hash
trailer [mdcTrailerSize]byte
scratch [mdcTrailerSize]byte
trailerUsed int
error bool
eof bool
}
func (ser *seMDCReader) Read(buf []byte) (n int, err error) {
if ser.error {
err = io.ErrUnexpectedEOF
return
}
if ser.eof {
err = io.EOF
return
}
// If we haven't yet filled the trailer buffer then we must do that
// first.
for ser.trailerUsed < mdcTrailerSize {
n, err = ser.in.Read(ser.trailer[ser.trailerUsed:])
ser.trailerUsed += n
if err == io.EOF {
if ser.trailerUsed != mdcTrailerSize {
n = 0
err = io.ErrUnexpectedEOF
ser.error = true
return
}
ser.eof = true
n = 0
return
}
if err != nil {
n = 0
return
}
}
// If it's a short read then we read into a temporary buffer and shift
// the data into the caller's buffer.
if len(buf) <= mdcTrailerSize {
n, err = readFull(ser.in, ser.scratch[:len(buf)])
copy(buf, ser.trailer[:n])
ser.h.Write(buf[:n])
copy(ser.trailer[:], ser.trailer[n:])
copy(ser.trailer[mdcTrailerSize-n:], ser.scratch[:])
if n < len(buf) {
ser.eof = true
err = io.EOF
}
return
}
n, err = ser.in.Read(buf[mdcTrailerSize:])
copy(buf, ser.trailer[:])
ser.h.Write(buf[:n])
copy(ser.trailer[:], buf[n:])
if err == io.EOF {
ser.eof = true
}
return
}
// This is a new-format packet tag byte for a type 19 (Integrity Protected) packet.
const mdcPacketTagByte = byte(0x80) | 0x40 | 19
func (ser *seMDCReader) Close() error {
if ser.error {
return errors.ErrMDCHashMismatch
}
for !ser.eof {
// We haven't seen EOF so we need to read to the end
var buf [1024]byte
_, err := ser.Read(buf[:])
if err == io.EOF {
break
}
if err != nil {
return errors.ErrMDCHashMismatch
}
}
ser.h.Write(ser.trailer[:2])
final := ser.h.Sum(nil)
if subtle.ConstantTimeCompare(final, ser.trailer[2:]) != 1 {
return errors.ErrMDCHashMismatch
}
// The hash already includes the MDC header, but we still check its value
// to confirm encryption correctness
if ser.trailer[0] != mdcPacketTagByte || ser.trailer[1] != sha1.Size {
return errors.ErrMDCHashMismatch
}
return nil
}
// An seMDCWriter writes through to an io.WriteCloser while maintains a running
// hash of the data written. On close, it emits an MDC packet containing the
// running hash.
type seMDCWriter struct {
w io.WriteCloser
h hash.Hash
}
func (w *seMDCWriter) Write(buf []byte) (n int, err error) {
w.h.Write(buf)
return w.w.Write(buf)
}
func (w *seMDCWriter) Close() (err error) {
var buf [mdcTrailerSize]byte
buf[0] = mdcPacketTagByte
buf[1] = sha1.Size
w.h.Write(buf[:2])
digest := w.h.Sum(nil)
copy(buf[2:], digest)
_, err = w.w.Write(buf[:])
if err != nil {
return
}
return w.w.Close()
}
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
type noOpCloser struct {
w io.Writer
}
func (c noOpCloser) Write(data []byte) (n int, err error) {
return c.w.Write(data)
}
func (c noOpCloser) Close() error {
return nil
}
func serializeSymmetricallyEncryptedMdc(ciphertext io.WriteCloser, c CipherFunction, key []byte, config *Config) (Contents io.WriteCloser, err error) {
// Disallow old cipher suites
if !c.IsSupported() || c < CipherAES128 {
return nil, errors.InvalidArgumentError("invalid mdc cipher function")
}
if c.KeySize() != len(key) {
return nil, errors.InvalidArgumentError("error in mdc serialization: bad key length")
}
_, err = ciphertext.Write([]byte{symmetricallyEncryptedVersionMdc})
if err != nil {
return
}
block := c.new(key)
blockSize := block.BlockSize()
iv := make([]byte, blockSize)
_, err = io.ReadFull(config.Random(), iv)
if err != nil {
return nil, err
}
s, prefix := NewOCFBEncrypter(block, iv, OCFBNoResync)
_, err = ciphertext.Write(prefix)
if err != nil {
return
}
plaintext := cipher.StreamWriter{S: s, W: ciphertext}
h := sha1.New()
h.Write(iv)
h.Write(iv[blockSize-2:])
Contents = &seMDCWriter{w: plaintext, h: h}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userattribute.go
================================================
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"bytes"
"image"
"image/jpeg"
"io"
)
const UserAttrImageSubpacket = 1
// UserAttribute is capable of storing other types of data about a user
// beyond name, email and a text comment. In practice, user attributes are typically used
// to store a signed thumbnail photo JPEG image of the user.
// See RFC 4880, section 5.12.
type UserAttribute struct {
Contents []*OpaqueSubpacket
}
// NewUserAttributePhoto creates a user attribute packet
// containing the given images.
func NewUserAttributePhoto(photos ...image.Image) (uat *UserAttribute, err error) {
uat = new(UserAttribute)
for _, photo := range photos {
var buf bytes.Buffer
// RFC 4880, Section 5.12.1.
data := []byte{
0x10, 0x00, // Little-endian image header length (16 bytes)
0x01, // Image header version 1
0x01, // JPEG
0, 0, 0, 0, // 12 reserved octets, must be all zero.
0, 0, 0, 0,
0, 0, 0, 0}
if _, err = buf.Write(data); err != nil {
return
}
if err = jpeg.Encode(&buf, photo, nil); err != nil {
return
}
lengthBuf := make([]byte, 5)
n := serializeSubpacketLength(lengthBuf, len(buf.Bytes())+1)
lengthBuf = lengthBuf[:n]
uat.Contents = append(uat.Contents, &OpaqueSubpacket{
SubType: UserAttrImageSubpacket,
EncodedLength: lengthBuf,
Contents: buf.Bytes(),
})
}
return
}
// NewUserAttribute creates a new user attribute packet containing the given subpackets.
func NewUserAttribute(contents ...*OpaqueSubpacket) *UserAttribute {
return &UserAttribute{Contents: contents}
}
func (uat *UserAttribute) parse(r io.Reader) (err error) {
// RFC 4880, section 5.13
b, err := io.ReadAll(r)
if err != nil {
return
}
uat.Contents, err = OpaqueSubpackets(b)
return
}
// Serialize marshals the user attribute to w in the form of an OpenPGP packet, including
// header.
func (uat *UserAttribute) Serialize(w io.Writer) (err error) {
var buf bytes.Buffer
for _, sp := range uat.Contents {
err = sp.Serialize(&buf)
if err != nil {
return err
}
}
if err = serializeHeader(w, packetTypeUserAttribute, buf.Len()); err != nil {
return err
}
_, err = w.Write(buf.Bytes())
return
}
// ImageData returns zero or more byte slices, each containing
// JPEG File Interchange Format (JFIF), for each photo in the
// user attribute packet.
func (uat *UserAttribute) ImageData() (imageData [][]byte) {
for _, sp := range uat.Contents {
if sp.SubType == UserAttrImageSubpacket && len(sp.Contents) > 16 {
imageData = append(imageData, sp.Contents[16:])
}
}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/packet/userid.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package packet
import (
"io"
"strings"
)
// UserId contains text that is intended to represent the name and email
// address of the key holder. See RFC 4880, section 5.11. By convention, this
// takes the form "Full Name (Comment) "
type UserId struct {
Id string // By convention, this takes the form "Full Name (Comment) " which is split out in the fields below.
Name, Comment, Email string
}
func hasInvalidCharacters(s string) bool {
for _, c := range s {
switch c {
case '(', ')', '<', '>', 0:
return true
}
}
return false
}
// NewUserId returns a UserId or nil if any of the arguments contain invalid
// characters. The invalid characters are '\x00', '(', ')', '<' and '>'
func NewUserId(name, comment, email string) *UserId {
// RFC 4880 doesn't deal with the structure of userid strings; the
// name, comment and email form is just a convention. However, there's
// no convention about escaping the metacharacters and GPG just refuses
// to create user ids where, say, the name contains a '('. We mirror
// this behaviour.
if hasInvalidCharacters(name) || hasInvalidCharacters(comment) || hasInvalidCharacters(email) {
return nil
}
uid := new(UserId)
uid.Name, uid.Comment, uid.Email = name, comment, email
uid.Id = name
if len(comment) > 0 {
if len(uid.Id) > 0 {
uid.Id += " "
}
uid.Id += "("
uid.Id += comment
uid.Id += ")"
}
if len(email) > 0 {
if len(uid.Id) > 0 {
uid.Id += " "
}
uid.Id += "<"
uid.Id += email
uid.Id += ">"
}
return uid
}
func (uid *UserId) parse(r io.Reader) (err error) {
// RFC 4880, section 5.11
b, err := io.ReadAll(r)
if err != nil {
return
}
uid.Id = string(b)
uid.Name, uid.Comment, uid.Email = parseUserId(uid.Id)
return
}
// Serialize marshals uid to w in the form of an OpenPGP packet, including
// header.
func (uid *UserId) Serialize(w io.Writer) error {
err := serializeHeader(w, packetTypeUserId, len(uid.Id))
if err != nil {
return err
}
_, err = w.Write([]byte(uid.Id))
return err
}
// parseUserId extracts the name, comment and email from a user id string that
// is formatted as "Full Name (Comment) ".
func parseUserId(id string) (name, comment, email string) {
var n, c, e struct {
start, end int
}
var state int
for offset, rune := range id {
switch state {
case 0:
// Entering name
n.start = offset
state = 1
fallthrough
case 1:
// In name
if rune == '(' {
state = 2
n.end = offset
} else if rune == '<' {
state = 5
n.end = offset
}
case 2:
// Entering comment
c.start = offset
state = 3
fallthrough
case 3:
// In comment
if rune == ')' {
state = 4
c.end = offset
}
case 4:
// Between comment and email
if rune == '<' {
state = 5
}
case 5:
// Entering email
e.start = offset
state = 6
fallthrough
case 6:
// In email
if rune == '>' {
state = 7
e.end = offset
}
default:
// After email
}
}
switch state {
case 1:
// ended in the name
n.end = len(id)
case 3:
// ended in comment
c.end = len(id)
case 6:
// ended in email
e.end = len(id)
}
name = strings.TrimSpace(id[n.start:n.end])
comment = strings.TrimSpace(id[c.start:c.end])
email = strings.TrimSpace(id[e.start:e.end])
// RFC 2822 3.4: alternate simple form of a mailbox
if email == "" && strings.ContainsRune(name, '@') {
email = name
name = ""
}
return
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/read.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package openpgp implements high level operations on OpenPGP messages.
package openpgp // import "github.com/ProtonMail/go-crypto/openpgp"
import (
"crypto"
_ "crypto/sha256"
_ "crypto/sha512"
"hash"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/packet"
_ "golang.org/x/crypto/sha3"
)
// SignatureType is the armor type for a PGP signature.
var SignatureType = "PGP SIGNATURE"
// readArmored reads an armored block with the given type.
func readArmored(r io.Reader, expectedType string) (body io.Reader, err error) {
block, err := armor.Decode(r)
if err != nil {
return
}
if block.Type != expectedType {
return nil, errors.InvalidArgumentError("expected '" + expectedType + "', got: " + block.Type)
}
return block.Body, nil
}
// MessageDetails contains the result of parsing an OpenPGP encrypted and/or
// signed message.
type MessageDetails struct {
IsEncrypted bool // true if the message was encrypted.
EncryptedToKeyIds []uint64 // the list of recipient key ids.
IsSymmetricallyEncrypted bool // true if a passphrase could have decrypted the message.
DecryptedWith Key // the private key used to decrypt the message, if any.
IsSigned bool // true if the message is signed.
SignedByKeyId uint64 // the key id of the signer, if any.
SignedByFingerprint []byte // the key fingerprint of the signer, if any.
SignedBy *Key // the key of the signer, if available.
LiteralData *packet.LiteralData // the metadata of the contents
UnverifiedBody io.Reader // the contents of the message.
// If IsSigned is true and SignedBy is non-zero then the signature will
// be verified as UnverifiedBody is read. The signature cannot be
// checked until the whole of UnverifiedBody is read so UnverifiedBody
// must be consumed until EOF before the data can be trusted. Even if a
// message isn't signed (or the signer is unknown) the data may contain
// an authentication code that is only checked once UnverifiedBody has
// been consumed. Once EOF has been seen, the following fields are
// valid. (An authentication code failure is reported as a
// SignatureError error when reading from UnverifiedBody.)
Signature *packet.Signature // the signature packet itself.
SignatureError error // nil if the signature is good.
UnverifiedSignatures []*packet.Signature // all other unverified signature packets.
decrypted io.ReadCloser
}
// A PromptFunction is used as a callback by functions that may need to decrypt
// a private key, or prompt for a passphrase. It is called with a list of
// acceptable, encrypted private keys and a boolean that indicates whether a
// passphrase is usable. It should either decrypt a private key or return a
// passphrase to try. If the decrypted private key or given passphrase isn't
// correct, the function will be called again, forever. Any error returned will
// be passed up.
type PromptFunction func(keys []Key, symmetric bool) ([]byte, error)
// A keyEnvelopePair is used to store a private key with the envelope that
// contains a symmetric key, encrypted with that key.
type keyEnvelopePair struct {
key Key
encryptedKey *packet.EncryptedKey
}
// ReadMessage parses an OpenPGP message that may be signed and/or encrypted.
// The given KeyRing should contain both public keys (for signature
// verification) and, possibly encrypted, private keys for decrypting.
// If config is nil, sensible defaults will be used.
func ReadMessage(r io.Reader, keyring KeyRing, prompt PromptFunction, config *packet.Config) (md *MessageDetails, err error) {
var p packet.Packet
var symKeys []*packet.SymmetricKeyEncrypted
var pubKeys []keyEnvelopePair
// Integrity protected encrypted packet: SymmetricallyEncrypted or AEADEncrypted
var edp packet.EncryptedDataPacket
packets := packet.NewReader(r)
md = new(MessageDetails)
md.IsEncrypted = true
// The message, if encrypted, starts with a number of packets
// containing an encrypted decryption key. The decryption key is either
// encrypted to a public key, or with a passphrase. This loop
// collects these packets.
ParsePackets:
for {
p, err = packets.Next()
if err != nil {
return nil, err
}
switch p := p.(type) {
case *packet.SymmetricKeyEncrypted:
// This packet contains the decryption key encrypted with a passphrase.
md.IsSymmetricallyEncrypted = true
symKeys = append(symKeys, p)
case *packet.EncryptedKey:
// This packet contains the decryption key encrypted to a public key.
md.EncryptedToKeyIds = append(md.EncryptedToKeyIds, p.KeyId)
switch p.Algo {
case packet.PubKeyAlgoRSA, packet.PubKeyAlgoRSAEncryptOnly, packet.PubKeyAlgoElGamal, packet.PubKeyAlgoECDH, packet.PubKeyAlgoX25519, packet.PubKeyAlgoX448:
break
default:
continue
}
if keyring != nil {
var keys []Key
if p.KeyId == 0 {
keys = keyring.DecryptionKeys()
} else {
keys = keyring.KeysById(p.KeyId)
}
for _, k := range keys {
pubKeys = append(pubKeys, keyEnvelopePair{k, p})
}
}
case *packet.SymmetricallyEncrypted:
if !p.IntegrityProtected && !config.AllowUnauthenticatedMessages() {
return nil, errors.UnsupportedError("message is not integrity protected")
}
edp = p
break ParsePackets
case *packet.AEADEncrypted:
edp = p
break ParsePackets
case *packet.Compressed, *packet.LiteralData, *packet.OnePassSignature:
// This message isn't encrypted.
if len(symKeys) != 0 || len(pubKeys) != 0 {
return nil, errors.StructuralError("key material not followed by encrypted message")
}
packets.Unread(p)
return readSignedMessage(packets, nil, keyring, config)
}
}
var candidates []Key
var decrypted io.ReadCloser
// Now that we have the list of encrypted keys we need to decrypt at
// least one of them or, if we cannot, we need to call the prompt
// function so that it can decrypt a key or give us a passphrase.
FindKey:
for {
// See if any of the keys already have a private key available
candidates = candidates[:0]
candidateFingerprints := make(map[string]bool)
for _, pk := range pubKeys {
if pk.key.PrivateKey == nil {
continue
}
if !pk.key.PrivateKey.Encrypted {
if len(pk.encryptedKey.Key) == 0 {
errDec := pk.encryptedKey.Decrypt(pk.key.PrivateKey, config)
if errDec != nil {
continue
}
}
// Try to decrypt symmetrically encrypted
decrypted, err = edp.Decrypt(pk.encryptedKey.CipherFunc, pk.encryptedKey.Key)
if err != nil && err != errors.ErrKeyIncorrect {
return nil, err
}
if decrypted != nil {
md.DecryptedWith = pk.key
break FindKey
}
} else {
fpr := string(pk.key.PublicKey.Fingerprint[:])
if v := candidateFingerprints[fpr]; v {
continue
}
candidates = append(candidates, pk.key)
candidateFingerprints[fpr] = true
}
}
if len(candidates) == 0 && len(symKeys) == 0 {
return nil, errors.ErrKeyIncorrect
}
if prompt == nil {
return nil, errors.ErrKeyIncorrect
}
passphrase, err := prompt(candidates, len(symKeys) != 0)
if err != nil {
return nil, err
}
// Try the symmetric passphrase first
if len(symKeys) != 0 && passphrase != nil {
for _, s := range symKeys {
key, cipherFunc, err := s.Decrypt(passphrase)
// In v4, on wrong passphrase, session key decryption is very likely to result in an invalid cipherFunc:
// only for < 5% of cases we will proceed to decrypt the data
if err == nil {
decrypted, err = edp.Decrypt(cipherFunc, key)
if err != nil {
return nil, err
}
if decrypted != nil {
break FindKey
}
}
}
}
}
md.decrypted = decrypted
if err := packets.Push(decrypted); err != nil {
return nil, err
}
mdFinal, sensitiveParsingErr := readSignedMessage(packets, md, keyring, config)
if sensitiveParsingErr != nil {
return nil, errors.HandleSensitiveParsingError(sensitiveParsingErr, md.decrypted != nil)
}
return mdFinal, nil
}
// readSignedMessage reads a possibly signed message if mdin is non-zero then
// that structure is updated and returned. Otherwise a fresh MessageDetails is
// used.
func readSignedMessage(packets *packet.Reader, mdin *MessageDetails, keyring KeyRing, config *packet.Config) (md *MessageDetails, err error) {
if mdin == nil {
mdin = new(MessageDetails)
}
md = mdin
var p packet.Packet
var h hash.Hash
var wrappedHash hash.Hash
var prevLast bool
FindLiteralData:
for {
p, err = packets.Next()
if err != nil {
return nil, err
}
switch p := p.(type) {
case *packet.Compressed:
if err := packets.Push(p.Body); err != nil {
return nil, err
}
case *packet.OnePassSignature:
if prevLast {
return nil, errors.UnsupportedError("nested signature packets")
}
if p.IsLast {
prevLast = true
}
h, wrappedHash, err = hashForSignature(p.Hash, p.SigType, p.Salt)
if err != nil {
md.SignatureError = err
}
md.IsSigned = true
if p.Version == 6 {
md.SignedByFingerprint = p.KeyFingerprint
}
md.SignedByKeyId = p.KeyId
if keyring != nil {
keys := keyring.KeysByIdUsage(p.KeyId, packet.KeyFlagSign)
if len(keys) > 0 {
md.SignedBy = &keys[0]
}
}
case *packet.LiteralData:
md.LiteralData = p
break FindLiteralData
}
}
if md.IsSigned && md.SignatureError == nil {
md.UnverifiedBody = &signatureCheckReader{packets, h, wrappedHash, md, config}
} else if md.decrypted != nil {
md.UnverifiedBody = &checkReader{md, false}
} else {
md.UnverifiedBody = md.LiteralData.Body
}
return md, nil
}
func wrapHashForSignature(hashFunc hash.Hash, sigType packet.SignatureType) (hash.Hash, error) {
switch sigType {
case packet.SigTypeBinary:
return hashFunc, nil
case packet.SigTypeText:
return NewCanonicalTextHash(hashFunc), nil
}
return nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
}
// hashForSignature returns a pair of hashes that can be used to verify a
// signature. The signature may specify that the contents of the signed message
// should be preprocessed (i.e. to normalize line endings). Thus this function
// returns two hashes. The second should be used to hash the message itself and
// performs any needed preprocessing.
func hashForSignature(hashFunc crypto.Hash, sigType packet.SignatureType, sigSalt []byte) (hash.Hash, hash.Hash, error) {
if _, ok := algorithm.HashToHashIdWithSha1(hashFunc); !ok {
return nil, nil, errors.UnsupportedError("unsupported hash function")
}
if !hashFunc.Available() {
return nil, nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashFunc)))
}
h := hashFunc.New()
if sigSalt != nil {
h.Write(sigSalt)
}
wrappedHash, err := wrapHashForSignature(h, sigType)
if err != nil {
return nil, nil, err
}
switch sigType {
case packet.SigTypeBinary:
return h, wrappedHash, nil
case packet.SigTypeText:
return h, wrappedHash, nil
}
return nil, nil, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(sigType)))
}
// checkReader wraps an io.Reader from a LiteralData packet. When it sees EOF
// it closes the ReadCloser from any SymmetricallyEncrypted packet to trigger
// MDC checks.
type checkReader struct {
md *MessageDetails
checked bool
}
func (cr *checkReader) Read(buf []byte) (int, error) {
n, sensitiveParsingError := cr.md.LiteralData.Body.Read(buf)
if sensitiveParsingError == io.EOF {
if cr.checked {
// Only check once
return n, io.EOF
}
mdcErr := cr.md.decrypted.Close()
if mdcErr != nil {
return n, mdcErr
}
cr.checked = true
return n, io.EOF
}
if sensitiveParsingError != nil {
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
}
return n, nil
}
// signatureCheckReader wraps an io.Reader from a LiteralData packet and hashes
// the data as it is read. When it sees an EOF from the underlying io.Reader
// it parses and checks a trailing Signature packet and triggers any MDC checks.
type signatureCheckReader struct {
packets *packet.Reader
h, wrappedHash hash.Hash
md *MessageDetails
config *packet.Config
}
func (scr *signatureCheckReader) Read(buf []byte) (int, error) {
n, sensitiveParsingError := scr.md.LiteralData.Body.Read(buf)
// Hash only if required
if scr.md.SignedBy != nil {
scr.wrappedHash.Write(buf[:n])
}
readsDecryptedData := scr.md.decrypted != nil
if sensitiveParsingError == io.EOF {
var p packet.Packet
var readError error
var sig *packet.Signature
p, readError = scr.packets.Next()
for readError == nil {
var ok bool
if sig, ok = p.(*packet.Signature); ok {
if sig.Version == 5 && (sig.SigType == 0x00 || sig.SigType == 0x01) {
sig.Metadata = scr.md.LiteralData
}
// If signature KeyID matches
if scr.md.SignedBy != nil && *sig.IssuerKeyId == scr.md.SignedByKeyId {
key := scr.md.SignedBy
signatureError := key.PublicKey.VerifySignature(scr.h, sig)
if signatureError == nil {
signatureError = checkMessageSignatureDetails(key, sig, scr.config)
}
scr.md.Signature = sig
scr.md.SignatureError = signatureError
} else {
scr.md.UnverifiedSignatures = append(scr.md.UnverifiedSignatures, sig)
}
}
p, readError = scr.packets.Next()
}
if scr.md.SignedBy != nil && scr.md.Signature == nil {
if scr.md.UnverifiedSignatures == nil {
scr.md.SignatureError = errors.StructuralError("LiteralData not followed by signature")
} else {
scr.md.SignatureError = errors.StructuralError("No matching signature found")
}
}
// The SymmetricallyEncrypted packet, if any, might have an
// unsigned hash of its own. In order to check this we need to
// close that Reader.
if scr.md.decrypted != nil {
if sensitiveParsingError := scr.md.decrypted.Close(); sensitiveParsingError != nil {
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, true)
}
}
return n, io.EOF
}
if sensitiveParsingError != nil {
return n, errors.HandleSensitiveParsingError(sensitiveParsingError, readsDecryptedData)
}
return n, nil
}
// VerifyDetachedSignature takes a signed file and a detached signature and
// returns the signature packet and the entity the signature was signed by,
// if any, and a possible signature verification error.
// If the signer isn't known, ErrUnknownIssuer is returned.
func VerifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
return verifyDetachedSignature(keyring, signed, signature, nil, false, config)
}
// VerifyDetachedSignatureAndHash performs the same actions as
// VerifyDetachedSignature and checks that the expected hash functions were used.
func VerifyDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
return verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
}
// CheckDetachedSignature takes a signed file and a detached signature and
// returns the entity the signature was signed by, if any, and a possible
// signature verification error. If the signer isn't known,
// ErrUnknownIssuer is returned.
func CheckDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
_, signer, err = verifyDetachedSignature(keyring, signed, signature, nil, false, config)
return
}
// CheckDetachedSignatureAndHash performs the same actions as
// CheckDetachedSignature and checks that the expected hash functions were used.
func CheckDetachedSignatureAndHash(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, config *packet.Config) (signer *Entity, err error) {
_, signer, err = verifyDetachedSignature(keyring, signed, signature, expectedHashes, true, config)
return
}
func verifyDetachedSignature(keyring KeyRing, signed, signature io.Reader, expectedHashes []crypto.Hash, checkHashes bool, config *packet.Config) (sig *packet.Signature, signer *Entity, err error) {
var issuerKeyId uint64
var hashFunc crypto.Hash
var sigType packet.SignatureType
var keys []Key
var p packet.Packet
packets := packet.NewReader(signature)
for {
p, err = packets.Next()
if err == io.EOF {
return nil, nil, errors.ErrUnknownIssuer
}
if err != nil {
return nil, nil, err
}
var ok bool
sig, ok = p.(*packet.Signature)
if !ok {
return nil, nil, errors.StructuralError("non signature packet found")
}
if sig.IssuerKeyId == nil {
return nil, nil, errors.StructuralError("signature doesn't have an issuer")
}
issuerKeyId = *sig.IssuerKeyId
hashFunc = sig.Hash
sigType = sig.SigType
if checkHashes {
matchFound := false
// check for hashes
for _, expectedHash := range expectedHashes {
if hashFunc == expectedHash {
matchFound = true
break
}
}
if !matchFound {
return nil, nil, errors.StructuralError("hash algorithm or salt mismatch with cleartext message headers")
}
}
keys = keyring.KeysByIdUsage(issuerKeyId, packet.KeyFlagSign)
if len(keys) > 0 {
break
}
}
if len(keys) == 0 {
panic("unreachable")
}
h, err := sig.PrepareVerify()
if err != nil {
return nil, nil, err
}
wrappedHash, err := wrapHashForSignature(h, sigType)
if err != nil {
return nil, nil, err
}
if _, err := io.Copy(wrappedHash, signed); err != nil && err != io.EOF {
return nil, nil, err
}
for _, key := range keys {
err = key.PublicKey.VerifySignature(h, sig)
if err == nil {
return sig, key.Entity, checkMessageSignatureDetails(&key, sig, config)
}
}
return nil, nil, err
}
// CheckArmoredDetachedSignature performs the same actions as
// CheckDetachedSignature but expects the signature to be armored.
func CheckArmoredDetachedSignature(keyring KeyRing, signed, signature io.Reader, config *packet.Config) (signer *Entity, err error) {
body, err := readArmored(signature, SignatureType)
if err != nil {
return
}
return CheckDetachedSignature(keyring, signed, body, config)
}
// checkMessageSignatureDetails returns an error if:
// - The signature (or one of the binding signatures mentioned below)
// has a unknown critical notation data subpacket
// - The primary key of the signing entity is revoked
// - The primary identity is revoked
// - The signature is expired
// - The primary key of the signing entity is expired according to the
// primary identity binding signature
//
// ... or, if the signature was signed by a subkey and:
// - The signing subkey is revoked
// - The signing subkey is expired according to the subkey binding signature
// - The signing subkey binding signature is expired
// - The signing subkey cross-signature is expired
//
// NOTE: The order of these checks is important, as the caller may choose to
// ignore ErrSignatureExpired or ErrKeyExpired errors, but should never
// ignore any other errors.
func checkMessageSignatureDetails(key *Key, signature *packet.Signature, config *packet.Config) error {
now := config.Now()
primarySelfSignature, primaryIdentity := key.Entity.PrimarySelfSignature()
signedBySubKey := key.PublicKey != key.Entity.PrimaryKey
sigsToCheck := []*packet.Signature{signature, primarySelfSignature}
if signedBySubKey {
sigsToCheck = append(sigsToCheck, key.SelfSignature, key.SelfSignature.EmbeddedSignature)
}
for _, sig := range sigsToCheck {
for _, notation := range sig.Notations {
if notation.IsCritical && !config.KnownNotation(notation.Name) {
return errors.SignatureError("unknown critical notation: " + notation.Name)
}
}
}
if key.Entity.Revoked(now) || // primary key is revoked
(signedBySubKey && key.Revoked(now)) || // subkey is revoked
(primaryIdentity != nil && primaryIdentity.Revoked(now)) { // primary identity is revoked for v4
return errors.ErrKeyRevoked
}
if key.Entity.PrimaryKey.KeyExpired(primarySelfSignature, now) { // primary key is expired
return errors.ErrKeyExpired
}
if signedBySubKey {
if key.PublicKey.KeyExpired(key.SelfSignature, now) { // subkey is expired
return errors.ErrKeyExpired
}
}
for _, sig := range sigsToCheck {
if sig.SigExpired(now) { // any of the relevant signatures are expired
return errors.ErrSignatureExpired
}
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/read_write_test_data.go
================================================
package openpgp
const testKey1KeyId uint64 = 0xA34D7E18C20C31BB
const testKey3KeyId uint64 = 0x338934250CCC0360
const testKeyP256KeyId uint64 = 0xd44a2c495918513e
const signedInput = "Signed message\nline 2\nline 3\n"
const signedTextInput = "Signed message\r\nline 2\r\nline 3\r\n"
const recipientUnspecifiedHex = "848c0300000000000000000103ff62d4d578d03cf40c3da998dfe216c074fa6ddec5e31c197c9666ba292830d91d18716a80f699f9d897389a90e6d62d0238f5f07a5248073c0f24920e4bc4a30c2d17ee4e0cae7c3d4aaa4e8dced50e3010a80ee692175fa0385f62ecca4b56ee6e9980aa3ec51b61b077096ac9e800edaf161268593eedb6cc7027ff5cb32745d250010d407a6221ae22ef18469b444f2822478c4d190b24d36371a95cb40087cdd42d9399c3d06a53c0673349bfb607927f20d1e122bde1e2bf3aa6cae6edf489629bcaa0689539ae3b718914d88ededc3b"
const detachedSignatureHex = "889c04000102000605024d449cd1000a0910a34d7e18c20c31bb167603ff57718d09f28a519fdc7b5a68b6a3336da04df85e38c5cd5d5bd2092fa4629848a33d85b1729402a2aab39c3ac19f9d573f773cc62c264dc924c067a79dfd8a863ae06c7c8686120760749f5fd9b1e03a64d20a7df3446ddc8f0aeadeaeba7cbaee5c1e366d65b6a0c6cc749bcb912d2f15013f812795c2e29eb7f7b77f39ce77"
const detachedSignatureTextHex = "889c04010102000605024d449d21000a0910a34d7e18c20c31bbc8c60400a24fbef7342603a41cb1165767bd18985d015fb72fe05db42db36cfb2f1d455967f1e491194fbf6cf88146222b23bf6ffbd50d17598d976a0417d3192ff9cc0034fd00f287b02e90418bbefe609484b09231e4e7a5f3562e199bf39909ab5276c4d37382fe088f6b5c3426fc1052865da8b3ab158672d58b6264b10823dc4b39"
const detachedSignatureDSAHex = "884604001102000605024d6c4eac000a0910338934250ccc0360f18d00a087d743d6405ed7b87755476629600b8b694a39e900a0abff8126f46faf1547c1743c37b21b4ea15b8f83"
const detachedSignatureP256Hex = "885e0400130a0006050256e5bb00000a0910d44a2c495918513edef001009841a4f792beb0befccb35c8838a6a87d9b936beaa86db6745ddc7b045eee0cf00fd1ac1f78306b17e965935dd3f8bae4587a76587e4af231efe19cc4011a8434817"
// The plaintext is https://www.gutenberg.org/cache/epub/1080/pg1080.txt
const modestProposalSha512 = "lbbrB1+WP3T9AaC9OQqBdOcCjgeEQadlulXsNPgVx0tyqPzDHwUugZ2gE7V0ESKAw6kAVfgkcuvfgxAAGaeHtw=="
const testKeys1And2Hex = "988d044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd0011010001b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b0020003b88d044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f0011010001889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab0020003988d044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b0020003b88d044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020003"
const testKeys1And2PrivateHex = "9501d8044d3c5c10010400b1d13382944bd5aba23a4312968b5095d14f947f600eb478e14a6fcb16b0e0cac764884909c020bc495cfcc39a935387c661507bdb236a0612fb582cac3af9b29cc2c8c70090616c41b662f4da4c1201e195472eb7f4ae1ccbcbf9940fe21d985e379a5563dde5b9a23d35f1cfaa5790da3b79db26f23695107bfaca8e7b5bcd00110100010003ff4d91393b9a8e3430b14d6209df42f98dc927425b881f1209f319220841273a802a97c7bdb8b3a7740b3ab5866c4d1d308ad0d3a79bd1e883aacf1ac92dfe720285d10d08752a7efe3c609b1d00f17f2805b217be53999a7da7e493bfc3e9618fd17018991b8128aea70a05dbce30e4fbe626aa45775fa255dd9177aabf4df7cf0200c1ded12566e4bc2bb590455e5becfb2e2c9796482270a943343a7835de41080582c2be3caf5981aa838140e97afa40ad652a0b544f83eb1833b0957dce26e47b0200eacd6046741e9ce2ec5beb6fb5e6335457844fb09477f83b050a96be7da043e17f3a9523567ed40e7a521f818813a8b8a72209f1442844843ccc7eb9805442570200bdafe0438d97ac36e773c7162028d65844c4d463e2420aa2228c6e50dc2743c3d6c72d0d782a5173fe7be2169c8a9f4ef8a7cf3e37165e8c61b89c346cdc6c1799d2b41054657374204b6579203120285253412988b804130102002205024d3c5c10021b03060b090807030206150802090a0b0416020301021e01021780000a0910a34d7e18c20c31bbb5b304009cc45fe610b641a2c146331be94dade0a396e73ca725e1b25c21708d9cab46ecca5ccebc23055879df8f99eea39b377962a400f2ebdc36a7c99c333d74aeba346315137c3ff9d0a09b0273299090343048afb8107cf94cbd1400e3026f0ccac7ecebbc4d78588eb3e478fe2754d3ca664bcf3eac96ca4a6b0c8d7df5102f60f6b00200009d01d8044d3c5c10010400b201df61d67487301f11879d514f4248ade90c8f68c7af1284c161098de4c28c2850f1ec7b8e30f959793e571542ffc6532189409cb51c3d30dad78c4ad5165eda18b20d9826d8707d0f742e2ab492103a85bbd9ddf4f5720f6de7064feb0d39ee002219765bb07bcfb8b877f47abe270ddeda4f676108cecb6b9bb2ad484a4f00110100010003fd17a7490c22a79c59281fb7b20f5e6553ec0c1637ae382e8adaea295f50241037f8997cf42c1ce26417e015091451b15424b2c59eb8d4161b0975630408e394d3b00f88d4b4e18e2cc85e8251d4753a27c639c83f5ad4a571c4f19d7cd460b9b73c25ade730c99df09637bd173d8e3e981ac64432078263bb6dc30d3e974150dd0200d0ee05be3d4604d2146fb0457f31ba17c057560785aa804e8ca5530a7cd81d3440d0f4ba6851efcfd3954b7e68908fc0ba47f7ac37bf559c6c168b70d3a7c8cd0200da1c677c4bce06a068070f2b3733b0a714e88d62aa3f9a26c6f5216d48d5c2b5624144f3807c0df30be66b3268eeeca4df1fbded58faf49fc95dc3c35f134f8b01fd1396b6c0fc1b6c4f0eb8f5e44b8eace1e6073e20d0b8bc5385f86f1cf3f050f66af789f3ef1fc107b7f4421e19e0349c730c68f0a226981f4e889054fdb4dc149e8e889f04180102000905024d3c5c10021b0c000a0910a34d7e18c20c31bb1a03040085c8d62e16d05dc4e9dad64953c8a2eed8b6c12f92b1575eeaa6dcf7be9473dd5b24b37b6dffbb4e7c99ed1bd3cb11634be19b3e6e207bed7505c7ca111ccf47cb323bf1f8851eb6360e8034cbff8dd149993c959de89f8f77f38e7e98b8e3076323aa719328e2b408db5ec0d03936efd57422ba04f925cdc7b4c1af7590e40ab00200009501fe044d3c5c33010400b488c3e5f83f4d561f317817538d9d0397981e9aef1321ca68ebfae1cf8b7d388e19f4b5a24a82e2fbbf1c6c26557a6c5845307a03d815756f564ac7325b02bc83e87d5480a8fae848f07cb891f2d51ce7df83dcafdc12324517c86d472cc0ee10d47a68fd1d9ae49a6c19bbd36d82af597a0d88cc9c49de9df4e696fc1f0b5d0011010001fe030302e9030f3c783e14856063f16938530e148bc57a7aa3f3e4f90df9dceccdc779bc0835e1ad3d006e4a8d7b36d08b8e0de5a0d947254ecfbd22037e6572b426bcfdc517796b224b0036ff90bc574b5509bede85512f2eefb520fb4b02aa523ba739bff424a6fe81c5041f253f8d757e69a503d3563a104d0d49e9e890b9d0c26f96b55b743883b472caa7050c4acfd4a21f875bdf1258d88bd61224d303dc9df77f743137d51e6d5246b88c406780528fd9a3e15bab5452e5b93970d9dcc79f48b38651b9f15bfbcf6da452837e9cc70683d1bdca94507870f743e4ad902005812488dd342f836e72869afd00ce1850eea4cfa53ce10e3608e13d3c149394ee3cbd0e23d018fcbcb6e2ec5a1a22972d1d462ca05355d0d290dd2751e550d5efb38c6c89686344df64852bf4ff86638708f644e8ec6bd4af9b50d8541cb91891a431326ab2e332faa7ae86cfb6e0540aa63160c1e5cdd5a4add518b303fff0a20117c6bc77f7cfbaf36b04c865c6c2b42754657374204b6579203220285253412c20656e637279707465642070726976617465206b65792988b804130102002205024d3c5c33021b03060b090807030206150802090a0b0416020301021e01021780000a0910d4984f961e35246b98940400908a73b6a6169f700434f076c6c79015a49bee37130eaf23aaa3cfa9ce60bfe4acaa7bc95f1146ada5867e0079babb38804891f4f0b8ebca57a86b249dee786161a755b7a342e68ccf3f78ed6440a93a6626beb9a37aa66afcd4f888790cb4bb46d94a4ae3eb3d7d3e6b00f6bfec940303e89ec5b32a1eaaacce66497d539328b00200009d01fe044d3c5c33010400a4e913f9442abcc7f1804ccab27d2f787ffa592077ca935a8bb23165bd8d57576acac647cc596b2c3f814518cc8c82953c7a4478f32e0cf645630a5ba38d9618ef2bc3add69d459ae3dece5cab778938d988239f8c5ae437807075e06c828019959c644ff05ef6a5a1dab72227c98e3a040b0cf219026640698d7a13d8538a570011010001fe030302e9030f3c783e148560f936097339ae381d63116efcf802ff8b1c9360767db5219cc987375702a4123fd8657d3e22700f23f95020d1b261eda5257e9a72f9a918e8ef22dd5b3323ae03bbc1923dd224db988cadc16acc04b120a9f8b7e84da9716c53e0334d7b66586ddb9014df604b41be1e960dcfcbc96f4ed150a1a0dd070b9eb14276b9b6be413a769a75b519a53d3ecc0c220e85cd91ca354d57e7344517e64b43b6e29823cbd87eae26e2b2e78e6dedfbb76e3e9f77bcb844f9a8932eb3db2c3f9e44316e6f5d60e9e2a56e46b72abe6b06dc9a31cc63f10023d1f5e12d2a3ee93b675c96f504af0001220991c88db759e231b3320dcedf814dcf723fd9857e3d72d66a0f2af26950b915abdf56c1596f46a325bf17ad4810d3535fb02a259b247ac3dbd4cc3ecf9c51b6c07cebb009c1506fba0a89321ec8683e3fd009a6e551d50243e2d5092fefb3321083a4bad91320dc624bd6b5dddf93553e3d53924c05bfebec1fb4bd47e89a1a889f04180102000905024d3c5c33021b0c000a0910d4984f961e35246b26c703ff7ee29ef53bc1ae1ead533c408fa136db508434e233d6e62be621e031e5940bbd4c08142aed0f82217e7c3e1ec8de574bc06ccf3c36633be41ad78a9eacd209f861cae7b064100758545cc9dd83db71806dc1cfd5fb9ae5c7474bba0c19c44034ae61bae5eca379383339dece94ff56ff7aa44a582f3e5c38f45763af577c0934b0020000"
const dsaElGamalTestKeysHex = "9501e1044dfcb16a110400aa3e5c1a1f43dd28c2ffae8abf5cfce555ee874134d8ba0a0f7b868ce2214beddc74e5e1e21ded354a95d18acdaf69e5e342371a71fbb9093162e0c5f3427de413a7f2c157d83f5cd2f9d791256dc4f6f0e13f13c3302af27f2384075ab3021dff7a050e14854bbde0a1094174855fc02f0bae8e00a340d94a1f22b32e48485700a0cec672ac21258fb95f61de2ce1af74b2c4fa3e6703ff698edc9be22c02ae4d916e4fa223f819d46582c0516235848a77b577ea49018dcd5e9e15cff9dbb4663a1ae6dd7580fa40946d40c05f72814b0f88481207e6c0832c3bded4853ebba0a7e3bd8e8c66df33d5a537cd4acf946d1080e7a3dcea679cb2b11a72a33a2b6a9dc85f466ad2ddf4c3db6283fa645343286971e3dd700703fc0c4e290d45767f370831a90187e74e9972aae5bff488eeff7d620af0362bfb95c1a6c3413ab5d15a2e4139e5d07a54d72583914661ed6a87cce810be28a0aa8879a2dd39e52fb6fe800f4f181ac7e328f740cde3d09a05cecf9483e4cca4253e60d4429ffd679d9996a520012aad119878c941e3cf151459873bdfc2a9563472fe0303027a728f9feb3b864260a1babe83925ce794710cfd642ee4ae0e5b9d74cee49e9c67b6cd0ea5dfbb582132195a121356a1513e1bca73e5b80c58c7ccb4164453412f456c47616d616c2054657374204b65792031886204131102002205024dfcb16a021b03060b090807030206150802090a0b0416020301021e01021780000a091033af447ccd759b09fadd00a0b8fd6f5a790bad7e9f2dbb7632046dc4493588db009c087c6a9ba9f7f49fab221587a74788c00db4889ab00200009d0157044dfcb16a1004008dec3f9291205255ccff8c532318133a6840739dd68b03ba942676f9038612071447bf07d00d559c5c0875724ea16a4c774f80d8338b55fca691a0522e530e604215b467bbc9ccfd483a1da99d7bc2648b4318fdbd27766fc8bfad3fddb37c62b8ae7ccfe9577e9b8d1e77c1d417ed2c2ef02d52f4da11600d85d3229607943700030503ff506c94c87c8cab778e963b76cf63770f0a79bf48fb49d3b4e52234620fc9f7657f9f8d56c96a2b7c7826ae6b57ebb2221a3fe154b03b6637cea7e6d98e3e45d87cf8dc432f723d3d71f89c5192ac8d7290684d2c25ce55846a80c9a7823f6acd9bb29fa6cd71f20bc90eccfca20451d0c976e460e672b000df49466408d527affe0303027a728f9feb3b864260abd761730327bca2aaa4ea0525c175e92bf240682a0e83b226f97ecb2e935b62c9a133858ce31b271fa8eb41f6a1b3cd72a63025ce1a75ee4180dcc284884904181102000905024dfcb16a021b0c000a091033af447ccd759b09dd0b009e3c3e7296092c81bee5a19929462caaf2fff3ae26009e218c437a2340e7ea628149af1ec98ec091a43992b00200009501e1044dfcb1be1104009f61faa61aa43df75d128cbe53de528c4aec49ce9360c992e70c77072ad5623de0a3a6212771b66b39a30dad6781799e92608316900518ec01184a85d872365b7d2ba4bacfb5882ea3c2473d3750dc6178cc1cf82147fb58caa28b28e9f12f6d1efcb0534abed644156c91cca4ab78834268495160b2400bc422beb37d237c2300a0cac94911b6d493bda1e1fbc6feeca7cb7421d34b03fe22cec6ccb39675bb7b94a335c2b7be888fd3906a1125f33301d8aa6ec6ee6878f46f73961c8d57a3e9544d8ef2a2cbfd4d52da665b1266928cfe4cb347a58c412815f3b2d2369dec04b41ac9a71cc9547426d5ab941cccf3b18575637ccfb42df1a802df3cfe0a999f9e7109331170e3a221991bf868543960f8c816c28097e503fe319db10fb98049f3a57d7c80c420da66d56f3644371631fad3f0ff4040a19a4fedc2d07727a1b27576f75a4d28c47d8246f27071e12d7a8de62aad216ddbae6aa02efd6b8a3e2818cda48526549791ab277e447b3a36c57cefe9b592f5eab73959743fcc8e83cbefec03a329b55018b53eec196765ae40ef9e20521a603c551efe0303020950d53a146bf9c66034d00c23130cce95576a2ff78016ca471276e8227fb30b1ffbd92e61804fb0c3eff9e30b1a826ee8f3e4730b4d86273ca977b4164453412f456c47616d616c2054657374204b65792032886204131102002205024dfcb1be021b03060b090807030206150802090a0b0416020301021e01021780000a0910a86bf526325b21b22bd9009e34511620415c974750a20df5cb56b182f3b48e6600a0a9466cb1a1305a84953445f77d461593f1d42bc1b00200009d0157044dfcb1be1004009565a951da1ee87119d600c077198f1c1bceb0f7aa54552489298e41ff788fa8f0d43a69871f0f6f77ebdfb14a4260cf9fbeb65d5844b4272a1904dd95136d06c3da745dc46327dd44a0f16f60135914368c8039a34033862261806bb2c5ce1152e2840254697872c85441ccb7321431d75a747a4bfb1d2c66362b51ce76311700030503fc0ea76601c196768070b7365a200e6ddb09307f262d5f39eec467b5f5784e22abdf1aa49226f59ab37cb49969d8f5230ea65caf56015abda62604544ed526c5c522bf92bed178a078789f6c807b6d34885688024a5bed9e9f8c58d11d4b82487b44c5f470c5606806a0443b79cadb45e0f897a561a53f724e5349b9267c75ca17fe0303020950d53a146bf9c660bc5f4ce8f072465e2d2466434320c1e712272fafc20e342fe7608101580fa1a1a367e60486a7cd1246b7ef5586cf5e10b32762b710a30144f12dd17dd4884904181102000905024dfcb1be021b0c000a0910a86bf526325b21b2904c00a0b2b66b4b39ccffda1d10f3ea8d58f827e30a8b8e009f4255b2d8112a184e40cde43a34e8655ca7809370b0020000"
const ed25519wX25519Key = "c54b0663877fe31b00000020f94da7bb48d60a61e567706a6587d0331999bb9d891a08242ead84543df895a3001972817b12be707e8d5f586ce61361201d344eb266a2c82fde6835762b65b0b7c2b1061f1b0a00000042058263877fe3030b090705150a0e080c021600029b03021e09222106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc905270902070200000000ad2820103e2d7d227ec0e6d7ce4471db36bfc97083253690271498a7ef0576c07faae14585b3b903b0127ec4fda2f023045a2ec76bcb4f9571a9651e14aee1137a1d668442c88f951e33c4ffd33fb9a17d511eed758fc6d9cc50cb5fd793b2039d5804c74b0663877fe319000000208693248367f9e5015db922f8f48095dda784987f2d5985b12fbad16caf5e4435004d600a4f794d44775c57a26e0feefed558e9afffd6ad0d582d57fb2ba2dcedb8c29b06181b0a0000002c050263877fe322a106cb186c4f0609a697e4d52dfa6c722b0c1f1e27c18a56708f6525ec27bad9acc9021b0c00000000defa20a6e9186d9d5935fc8fe56314cdb527486a5a5120f9b762a235a729f039010a56b89c658568341fbef3b894e9834ad9bc72afae2f4c9c47a43855e65f1cb0a3f77bbc5f61085c1f8249fe4e7ca59af5f0bcee9398e0fa8d76e522e1d8ab42bb0d"
const signedMessageHex = "a3019bc0cbccc0c4b8d8b74ee2108fe16ec6d3ca490cbe362d3f8333d3f352531472538b8b13d353b97232f352158c20943157c71c16064626063656269052062e4e01987e9b6fccff4b7df3a34c534b23e679cbec3bc0f8f6e64dfb4b55fe3f8efa9ce110ddb5cd79faf1d753c51aecfa669f7e7aa043436596cccc3359cb7dd6bbe9ecaa69e5989d9e57209571edc0b2fa7f57b9b79a64ee6e99ce1371395fee92fec2796f7b15a77c386ff668ee27f6d38f0baa6c438b561657377bf6acff3c5947befd7bf4c196252f1d6e5c524d0300"
const signedTextMessageHex = "a3019bc0cbccc8c4b8d8b74ee2108fe16ec6d36a250cbece0c178233d3f352531472538b8b13d35379b97232f352158ca0b4312f57c71c1646462606365626906a062e4e019811591798ff99bf8afee860b0d8a8c2a85c3387e3bcf0bb3b17987f2bbcfab2aa526d930cbfd3d98757184df3995c9f3e7790e36e3e9779f06089d4c64e9e47dd6202cb6e9bc73c5d11bb59fbaf89d22d8dc7cf199ddf17af96e77c5f65f9bbed56f427bd8db7af37f6c9984bf9385efaf5f184f986fb3e6adb0ecfe35bbf92d16a7aa2a344fb0bc52fb7624f0200"
const signedEncryptedMessageHex = "c18c032a67d68660df41c70103ff5a84c9a72f80e74ef0384c2d6a9ebfe2b09e06a8f298394f6d2abf174e40934ab0ec01fb2d0ddf21211c6fe13eb238563663b017a6b44edca552eb4736c4b7dc6ed907dd9e12a21b51b64b46f902f76fb7aaf805c1db8070574d8d0431a23e324a750f77fb72340a17a42300ee4ca8207301e95a731da229a63ab9c6b44541fbd2c11d016d810b3b3b2b38f15b5b40f0a4910332829c2062f1f7cc61f5b03677d73c54cafa1004ced41f315d46444946faae571d6f426e6dbd45d9780eb466df042005298adabf7ce0ef766dfeb94cd449c7ed0046c880339599c4711af073ce649b1e237c40b50a5536283e03bdbb7afad78bd08707715c67fb43295f905b4c479178809d429a8e167a9a8c6dfd8ab20b4edebdc38d6dec879a3202e1b752690d9bb5b0c07c5a227c79cc200e713a99251a4219d62ad5556900cf69bd384b6c8e726c7be267471d0d23af956da165af4af757246c2ebcc302b39e8ef2fccb4971b234fcda22d759ddb20e27269ee7f7fe67898a9de721bfa02ab0becaa046d00ea16cb1afc4e2eab40d0ac17121c565686e5cbd0cbdfbd9d6db5c70278b9c9db5a83176d04f61fbfbc4471d721340ede2746e5c312ded4f26787985af92b64fae3f253dbdde97f6a5e1996fd4d865599e32ff76325d3e9abe93184c02988ee89a4504356a4ef3b9b7a57cbb9637ca90af34a7676b9ef559325c3cca4e29d69fec1887f5440bb101361d744ad292a8547f22b4f22b419a42aa836169b89190f46d9560824cb2ac6e8771de8223216a5e647e132ab9eebcba89569ab339cb1c3d70fe806b31f4f4c600b4103b8d7583ebff16e43dcda551e6530f975122eb8b29"
const verifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61"
const unverifiedSignatureEncryptedMessageHex = "c2b304000108000605026048f6d600210910a34d7e18c20c31bb1621045fb74b1d03b1e3cb31bc2f8aa34d7e18c20c31bb9a3b0400a32ddac1af259c1b0abab0041327ea04970944401978fb647dd1cf9aba4f164e43f0d8a9389501886474bdd4a6e77f6aea945c07dfbf87743835b44cc2c39a1f9aeecfa83135abc92e18e50396f2e6a06c44e0188b0081effbfb4160d28f118d4ff73dd199a102e47cffd8c7ff2bacd83ae72b5820c021a486766dd587b5da61"
const signedEncryptedMessage2Hex = "85010e03cf6a7abcd43e36731003fb057f5495b79db367e277cdbe4ab90d924ddee0c0381494112ff8c1238fb0184af35d1731573b01bc4c55ecacd2aafbe2003d36310487d1ecc9ac994f3fada7f9f7f5c3a64248ab7782906c82c6ff1303b69a84d9a9529c31ecafbcdb9ba87e05439897d87e8a2a3dec55e14df19bba7f7bd316291c002ae2efd24f83f9e3441203fc081c0c23dc3092a454ca8a082b27f631abf73aca341686982e8fbda7e0e7d863941d68f3de4a755c2964407f4b5e0477b3196b8c93d551dd23c8beef7d0f03fbb1b6066f78907faf4bf1677d8fcec72651124080e0b7feae6b476e72ab207d38d90b958759fdedfc3c6c35717c9dbfc979b3cfbbff0a76d24a5e57056bb88acbd2a901ef64bc6e4db02adc05b6250ff378de81dca18c1910ab257dff1b9771b85bb9bbe0a69f5989e6d1710a35e6dfcceb7d8fb5ccea8db3932b3d9ff3fe0d327597c68b3622aec8e3716c83a6c93f497543b459b58ba504ed6bcaa747d37d2ca746fe49ae0a6ce4a8b694234e941b5159ff8bd34b9023da2814076163b86f40eed7c9472f81b551452d5ab87004a373c0172ec87ea6ce42ccfa7dbdad66b745496c4873d8019e8c28d6b3"
const signatureEncryptedMessage2Hex = "c24604001102000605024dfd0166000a091033af447ccd759b09bae600a096ec5e63ecf0a403085e10f75cc3bab327663282009f51fad9df457ed8d2b70d8a73c76e0443eac0f377"
const symmetricallyEncryptedCompressedHex = "c32e040903085a357c1a7b5614ed00cc0d1d92f428162058b3f558a0fb0980d221ebac6c97d5eda4e0fe32f6e706e94dd263012d6ca1ef8c4bbd324098225e603a10c85ebf09cbf7b5aeeb5ce46381a52edc51038b76a8454483be74e6dcd1e50d5689a8ae7eceaeefed98a0023d49b22eb1f65c2aa1ef1783bb5e1995713b0457102ec3c3075fe871267ffa4b686ad5d52000d857"
const dsaTestKeyHex = "9901a2044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
const dsaTestKeyPrivateHex = "9501bb044d6c49de110400cb5ce438cf9250907ac2ba5bf6547931270b89f7c4b53d9d09f4d0213a5ef2ec1f26806d3d259960f872a4a102ef1581ea3f6d6882d15134f21ef6a84de933cc34c47cc9106efe3bd84c6aec12e78523661e29bc1a61f0aab17fa58a627fd5fd33f5149153fbe8cd70edf3d963bc287ef875270ff14b5bfdd1bca4483793923b00a0fe46d76cb6e4cbdc568435cd5480af3266d610d303fe33ae8273f30a96d4d34f42fa28ce1112d425b2e3bf7ea553d526e2db6b9255e9dc7419045ce817214d1a0056dbc8d5289956a4b1b69f20f1105124096e6a438f41f2e2495923b0f34b70642607d45559595c7fe94d7fa85fc41bf7d68c1fd509ebeaa5f315f6059a446b9369c277597e4f474a9591535354c7e7f4fd98a08aa60400b130c24ff20bdfbf683313f5daebf1c9b34b3bdadfc77f2ddd72ee1fb17e56c473664bc21d66467655dd74b9005e3a2bacce446f1920cd7017231ae447b67036c9b431b8179deacd5120262d894c26bc015bffe3d827ba7087ad9b700d2ca1f6d16cc1786581e5dd065f293c31209300f9b0afcc3f7c08dd26d0a22d87580b4d00009f592e0619d823953577d4503061706843317e4fee083db41054657374204b65792033202844534129886204131102002205024d6c49de021b03060b090807030206150802090a0b0416020301021e01021780000a0910338934250ccc03607e0400a0bdb9193e8a6b96fc2dfc108ae848914b504481f100a09c4dc148cb693293a67af24dd40d2b13a9e36794"
const p256TestKeyHex = "98520456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b7754b8560456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b6030108078861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
const p256TestKeyPrivateHex = "94a50456e5b83813082a8648ce3d030107020304a2072cd6d21321266c758cc5b83fab0510f751cb8d91897cddb7047d8d6f185546e2107111b0a95cb8ef063c33245502af7a65f004d5919d93ee74eb71a66253fe070302f0c2bfb0b6c30f87ee1599472b8636477eab23ced13b271886a4b50ed34c9d8436af5af5b8f88921f0efba6ef8c37c459bbb88bc1c6a13bbd25c4ce9b1e97679569ee77645d469bf4b43de637f5561b424502d3235362054657374204b6579203c696e76616c6964406578616d706c652e636f6d3e8879041313080021050256e5b838021b03050b09080702061508090a0b020416020301021e01021780000a0910d44a2c495918513e54e50100dfa64f97d9b47766fc1943c6314ba3f2b2a103d71ad286dc5b1efb96a345b0c80100dbc8150b54241f559da6ef4baacea6d31902b4f4b1bdc09b34bf0502334b77549ca90456e5b83812082a8648ce3d030107020304bfe3cea9cee13486f8d518aa487fecab451f25467d2bf08e58f63e5fa525d5482133e6a79299c274b068ef0be448152ad65cf11cf764348588ca4f6a0bcf22b603010807fe0703027510012471a603cfee2968dce19f732721ddf03e966fd133b4e3c7a685b788705cbc46fb026dc94724b830c9edbaecd2fb2c662f23169516cacd1fe423f0475c364ecc10abcabcfd4bbbda1a36a1bd8861041813080009050256e5b838021b0c000a0910d44a2c495918513e4a4800ff49d589fa64024ad30be363a032e3a0e0e6f5db56ba4c73db850518bf0121b8f20100fd78e065f4c70ea5be9df319ea67e493b936fc78da834a71828043d3154af56e"
const armoredPrivateKeyBlock = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Version: GnuPG v1.4.10 (GNU/Linux)
lQHYBE2rFNoBBADFwqWQIW/DSqcB4yCQqnAFTJ27qS5AnB46ccAdw3u4Greeu3Bp
idpoHdjULy7zSKlwR1EA873dO/k/e11Ml3dlAFUinWeejWaK2ugFP6JjiieSsrKn
vWNicdCS4HTWn0X4sjl0ZiAygw6GNhqEQ3cpLeL0g8E9hnYzJKQ0LWJa0QARAQAB
AAP/TB81EIo2VYNmTq0pK1ZXwUpxCrvAAIG3hwKjEzHcbQznsjNvPUihZ+NZQ6+X
0HCfPAdPkGDCLCb6NavcSW+iNnLTrdDnSI6+3BbIONqWWdRDYJhqZCkqmG6zqSfL
IdkJgCw94taUg5BWP/AAeQrhzjChvpMQTVKQL5mnuZbUCeMCAN5qrYMP2S9iKdnk
VANIFj7656ARKt/nf4CBzxcpHTyB8+d2CtPDKCmlJP6vL8t58Jmih+kHJMvC0dzn
gr5f5+sCAOOe5gt9e0am7AvQWhdbHVfJU0TQJx+m2OiCJAqGTB1nvtBLHdJnfdC9
TnXXQ6ZXibqLyBies/xeY2sCKL5qtTMCAKnX9+9d/5yQxRyrQUHt1NYhaXZnJbHx
q4ytu0eWz+5i68IYUSK69jJ1NWPM0T6SkqpB3KCAIv68VFm9PxqG1KmhSrQIVGVz
dCBLZXmIuAQTAQIAIgUCTasU2gIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA
CgkQO9o98PRieSoLhgQAkLEZex02Qt7vGhZzMwuN0R22w3VwyYyjBx+fM3JFETy1
ut4xcLJoJfIaF5ZS38UplgakHG0FQ+b49i8dMij0aZmDqGxrew1m4kBfjXw9B/v+
eIqpODryb6cOSwyQFH0lQkXC040pjq9YqDsO5w0WYNXYKDnzRV0p4H1pweo2VDid
AdgETasU2gEEAN46UPeWRqKHvA99arOxee38fBt2CI08iiWyI8T3J6ivtFGixSqV
bRcPxYO/qLpVe5l84Nb3X71GfVXlc9hyv7CD6tcowL59hg1E/DC5ydI8K8iEpUmK
/UnHdIY5h8/kqgGxkY/T/hgp5fRQgW1ZoZxLajVlMRZ8W4tFtT0DeA+JABEBAAEA
A/0bE1jaaZKj6ndqcw86jd+QtD1SF+Cf21CWRNeLKnUds4FRRvclzTyUMuWPkUeX
TaNNsUOFqBsf6QQ2oHUBBK4VCHffHCW4ZEX2cd6umz7mpHW6XzN4DECEzOVksXtc
lUC1j4UB91DC/RNQqwX1IV2QLSwssVotPMPqhOi0ZLNY7wIA3n7DWKInxYZZ4K+6
rQ+POsz6brEoRHwr8x6XlHenq1Oki855pSa1yXIARoTrSJkBtn5oI+f8AzrnN0BN
oyeQAwIA/7E++3HDi5aweWrViiul9cd3rcsS0dEnksPhvS0ozCJiHsq/6GFmy7J8
QSHZPteedBnZyNp5jR+H7cIfVN3KgwH/Skq4PsuPhDq5TKK6i8Pc1WW8MA6DXTdU
nLkX7RGmMwjC0DBf7KWAlPjFaONAX3a8ndnz//fy1q7u2l9AZwrj1qa1iJ8EGAEC
AAkFAk2rFNoCGwwACgkQO9o98PRieSo2/QP/WTzr4ioINVsvN1akKuekmEMI3LAp
BfHwatufxxP1U+3Si/6YIk7kuPB9Hs+pRqCXzbvPRrI8NHZBmc8qIGthishdCYad
AHcVnXjtxrULkQFGbGvhKURLvS9WnzD/m1K2zzwxzkPTzT9/Yf06O6Mal5AdugPL
VrM0m72/jnpKo04=
=zNCn
-----END PGP PRIVATE KEY BLOCK-----`
const e2ePublicKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Charset: UTF-8
xv8AAABSBAAAAAATCCqGSM49AwEHAgME1LRoXSpOxtHXDUdmuvzchyg6005qIBJ4
sfaSxX7QgH9RV2ONUhC+WiayCNADq+UMzuR/vunSr4aQffXvuGnR383/AAAAFDxk
Z2lsQHlhaG9vLWluYy5jb20+wv8AAACGBBATCAA4/wAAAAWCVGvAG/8AAAACiwn/
AAAACZC2VkQCOjdvYf8AAAAFlQgJCgv/AAAAA5YBAv8AAAACngEAAE1BAP0X8veD
24IjmI5/C6ZAfVNXxgZZFhTAACFX75jUA3oD6AEAzoSwKf1aqH6oq62qhCN/pekX
+WAsVMBhNwzLpqtCRjLO/wAAAFYEAAAAABIIKoZIzj0DAQcCAwT50ain7vXiIRv8
B1DO3x3cE/aattZ5sHNixJzRCXi2vQIA5QmOxZ6b5jjUekNbdHG3SZi1a2Ak5mfX
fRxC/5VGAwEIB8L/AAAAZQQYEwgAGP8AAAAFglRrwBz/AAAACZC2VkQCOjdvYQAA
FJAA9isX3xtGyMLYwp2F3nXm7QEdY5bq5VUcD/RJlj792VwA/1wH0pCzVLl4Q9F9
ex7En5r7rHR5xwX82Msc+Rq9dSyO
=7MrZ
-----END PGP PUBLIC KEY BLOCK-----`
const dsaKeyWithSHA512 = `9901a2044f04b07f110400db244efecc7316553ee08d179972aab87bb1214de7692593fcf5b6feb1c80fba268722dd464748539b85b81d574cd2d7ad0ca2444de4d849b8756bad7768c486c83a824f9bba4af773d11742bdfb4ac3b89ef8cc9452d4aad31a37e4b630d33927bff68e879284a1672659b8b298222fc68f370f3e24dccacc4a862442b9438b00a0ea444a24088dc23e26df7daf8f43cba3bffc4fe703fe3d6cd7fdca199d54ed8ae501c30e3ec7871ea9cdd4cf63cfe6fc82281d70a5b8bb493f922cd99fba5f088935596af087c8d818d5ec4d0b9afa7f070b3d7c1dd32a84fca08d8280b4890c8da1dde334de8e3cad8450eed2a4a4fcc2db7b8e5528b869a74a7f0189e11ef097ef1253582348de072bb07a9fa8ab838e993cef0ee203ff49298723e2d1f549b00559f886cd417a41692ce58d0ac1307dc71d85a8af21b0cf6eaa14baf2922d3a70389bedf17cc514ba0febbd107675a372fe84b90162a9e88b14d4b1c6be855b96b33fb198c46f058568817780435b6936167ebb3724b680f32bf27382ada2e37a879b3d9de2abe0c3f399350afd1ad438883f4791e2e3b4184453412068617368207472756e636174696f6e207465737488620413110a002205024f04b07f021b03060b090807030206150802090a0b0416020301021e01021780000a0910ef20e0cefca131581318009e2bf3bf047a44d75a9bacd00161ee04d435522397009a03a60d51bd8a568c6c021c8d7cf1be8d990d6417b0020003`
const unknownHashFunctionHex = `8a00000040040001990006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
const rsaSignatureBadMPIlength = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
const missingHashFunctionHex = `8a00000040040001030006050253863c24000a09103b4fe6acc0b21f32ffff0101010101010101010101010101010101010101010101010101010101010101010101010101`
const campbellQuine = `a0b001000300fcffa0b001000d00f2ff000300fcffa0b001000d00f2ff8270a01c00000500faff8270a01c00000500faff000500faff001400ebff8270a01c00000500faff000500faff001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400001400ebff428821c400000000ffff000000ffff000b00f4ff428821c400000000ffff000000ffff000b00f4ff0233214c40000100feff000233214c40000100feff0000`
const keyV4forVerifyingSignedMessageV3 = `-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: GPGTools - https://gpgtools.org
mI0EVfxoFQEEAMBIqmbDfYygcvP6Phr1wr1XI41IF7Qixqybs/foBF8qqblD9gIY
BKpXjnBOtbkcVOJ0nljd3/sQIfH4E0vQwK5/4YRQSI59eKOqd6Fx+fWQOLG+uu6z
tewpeCj9LLHvibx/Sc7VWRnrznia6ftrXxJ/wHMezSab3tnGC0YPVdGNABEBAAG0
JEdvY3J5cHRvIFRlc3QgS2V5IDx0aGVtYXhAZ21haWwuY29tPoi5BBMBCgAjBQJV
/GgVAhsDBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQeXnQmhdGW9PFVAP+
K7TU0qX5ArvIONIxh/WAweyOk884c5cE8f+3NOPOOCRGyVy0FId5A7MmD5GOQh4H
JseOZVEVCqlmngEvtHZb3U1VYtVGE5WZ+6rQhGsMcWP5qaT4soYwMBlSYxgYwQcx
YhN9qOr292f9j2Y//TTIJmZT4Oa+lMxhWdqTfX+qMgG4jQRV/GgVAQQArhFSiij1
b+hT3dnapbEU+23Z1yTu1DfF6zsxQ4XQWEV3eR8v+8mEDDNcz8oyyF56k6UQ3rXi
UMTIwRDg4V6SbZmaFbZYCOwp/EmXJ3rfhm7z7yzXj2OFN22luuqbyVhuL7LRdB0M
pxgmjXb4tTvfgKd26x34S+QqUJ7W6uprY4sAEQEAAYifBBgBCgAJBQJV/GgVAhsM
AAoJEHl50JoXRlvT7y8D/02ckx4OMkKBZo7viyrBw0MLG92i+DC2bs35PooHR6zz
786mitjOp5z2QWNLBvxC70S0qVfCIz8jKupO1J6rq6Z8CcbLF3qjm6h1omUBf8Nd
EfXKD2/2HV6zMKVknnKzIEzauh+eCKS2CeJUSSSryap/QLVAjRnckaES/OsEWhNB
=RZia
-----END PGP PUBLIC KEY BLOCK-----
`
const signedMessageV3 = `-----BEGIN PGP MESSAGE-----
Comment: GPGTools - https://gpgtools.org
owGbwMvMwMVYWXlhlrhb9GXG03JJDKF/MtxDMjKLFYAoUaEktbhEITe1uDgxPVWP
q5NhKjMrWAVcC9evD8z/bF/uWNjqtk/X3y5/38XGRQHm/57rrDRYuGnTw597Xqka
uM3137/hH3Os+Jf2dc0fXOITKwJvXJvecPVs0ta+Vg7ZO1MLn8w58Xx+6L58mbka
DGHyU9yTueZE8D+QF/Tz28Y78dqtF56R1VPn9Xw4uJqrWYdd7b3vIZ1V6R4Nh05d
iT57d/OhWwA=
=hG7R
-----END PGP MESSAGE-----
`
// https://mailarchive.ietf.org/arch/msg/openpgp/9SheW_LENE0Kxf7haNllovPyAdY/
const v5PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd
fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA
Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC
X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI
CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9
M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA
MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD
AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF
GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb
DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7
TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
=IiS2
-----END PGP PRIVATE KEY BLOCK-----`
// See OpenPGP crypto refresh Section A.3.
const v6PrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
xUsGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laMAGXKB
exK+cH6NX1hs5hNhIB00TrJmosgv3mg1ditlsLfCsQYfGwoAAABCBYJjh3/jAwsJ
BwUVCg4IDAIWAAKbAwIeCSIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
2azJBScJAgcCAAAAAK0oIBA+LX0ifsDm185Ecds2v8lwgyU2kCcUmKfvBXbAf6rh
RYWzuQOwEn7E/aLwIwRaLsdry0+VcallHhSu4RN6HWaEQsiPlR4zxP/TP7mhfVEe
7XWPxtnMUMtf15OyA51YBMdLBmOHf+MZAAAAIIaTJINn+eUBXbki+PSAld2nhJh/
LVmFsS+60WyvXkQ1AE1gCk95TUR3XFeibg/u/tVY6a//1q0NWC1X+yui3O24wpsG
GBsKAAAALAWCY4d/4wKbDCIhBssYbE8GCaaX5NUt+mxyKwwfHifBilZwj2Ul7Ce6
2azJAAAAAAQBIKbpGG2dWTX8j+VjFM21J0hqWlEg+bdiojWnKfA5AQpWUWtnNwDE
M0g12vYxoWM8Y81W+bHBw805I8kWVkXU6vFOi+HWvv/ira7ofJu16NnoUkhclkUr
k0mXubZvyl4GBg==
-----END PGP PRIVATE KEY BLOCK-----`
// See OpenPGP crypto refresh merge request:
// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/304
const v6PrivKeyMsg = `-----BEGIN PGP MESSAGE-----
wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
bhF30A+IitsxxA==
-----END PGP MESSAGE-----`
// See OpenPGP crypto refresh merge request:
// https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/305
const v6PrivKeyInlineSignMsg = `-----BEGIN PGP MESSAGE-----
wV0GIQYSyD8ecG9jCP4VGkF3Q6HwM3kOk+mXhIjR2zeNqZMIhRmHzxjV8bU/gXzO
WgBM85PMiVi93AZfJfhK9QmxfdNnZBjeo1VDeVZheQHgaVf7yopqR6W1FT6NOrfS
aQIHAgZhZBZTW+CwcW1g4FKlbExAf56zaw76/prQoN+bAzxpohup69LA7JW/Vp0l
yZnuSj3hcFj0DfqLTGgr4/u717J+sPWbtQBfgMfG9AOIwwrUBqsFE9zW+f1zdlYo
bhF30A+IitsxxA==
-----END PGP MESSAGE-----`
// See https://gitlab.com/openpgp-wg/rfc4880bis/-/merge_requests/274
// decryption password: "correct horse battery staple"
const v6ArgonSealedPrivKey = `-----BEGIN PGP PRIVATE KEY BLOCK-----
xYIGY4d/4xsAAAAg+U2nu0jWCmHlZ3BqZYfQMxmZu52JGggkLq2EVD34laP9JgkC
FARdb9ccngltHraRe25uHuyuAQQVtKipJ0+r5jL4dacGWSAheCWPpITYiyfyIOPS
3gIDyg8f7strd1OB4+LZsUhcIjOMpVHgmiY/IutJkulneoBYwrEGHxsKAAAAQgWC
Y4d/4wMLCQcFFQoOCAwCFgACmwMCHgkiIQbLGGxPBgmml+TVLfpscisMHx4nwYpW
cI9lJewnutmsyQUnCQIHAgAAAACtKCAQPi19In7A5tfORHHbNr/JcIMlNpAnFJin
7wV2wH+q4UWFs7kDsBJ+xP2i8CMEWi7Ha8tPlXGpZR4UruETeh1mhELIj5UeM8T/
0z+5oX1RHu11j8bZzFDLX9eTsgOdWATHggZjh3/jGQAAACCGkySDZ/nlAV25Ivj0
gJXdp4SYfy1ZhbEvutFsr15ENf0mCQIUBA5hhGgp2oaavg6mFUXcFMwBBBUuE8qf
9Ock+xwusd+GAglBr5LVyr/lup3xxQvHXFSjjA2haXfoN6xUGRdDEHI6+uevKjVR
v5oAxgu7eJpaXNjCmwYYGwoAAAAsBYJjh3/jApsMIiEGyxhsTwYJppfk1S36bHIr
DB8eJ8GKVnCPZSXsJ7rZrMkAAAAABAEgpukYbZ1ZNfyP5WMUzbUnSGpaUSD5t2Ki
Nacp8DkBClZRa2c3AMQzSDXa9jGhYzxjzVb5scHDzTkjyRZWRdTq8U6L4da+/+Kt
ruh8m7Xo2ehSSFyWRSuTSZe5tm/KXgYG
-----END PGP PRIVATE KEY BLOCK-----`
const v4Key25519 = `-----BEGIN PGP PRIVATE KEY BLOCK-----
xUkEZB3qzRto01j2k2pwN5ux9w70stPinAdXULLr20CRW7U7h2GSeACch0M+
qzQg8yjFQ8VBvu3uwgKH9senoHmj72lLSCLTmhFKzQR0ZXN0wogEEBsIAD4F
gmQd6s0ECwkHCAmQIf45+TuC+xMDFQgKBBYAAgECGQECmwMCHgEWIQSWEzMi
jJUHvyIbVKIh/jn5O4L7EwAAUhaHNlgudvxARdPPETUzVgjuWi+YIz8w1xIb
lHQMvIrbe2sGCQIethpWofd0x7DHuv/ciHg+EoxJ/Td6h4pWtIoKx0kEZB3q
zRm4CyA7quliq7yx08AoOqHTuuCgvpkSdEhpp3pEyejQOgBo0p6ywIiLPllY
0t+jpNspHpAGfXID6oqjpYuJw3AfVRBlwnQEGBsIACoFgmQd6s0JkCH+Ofk7
gvsTApsMFiEElhMzIoyVB78iG1SiIf45+TuC+xMAAGgQuN9G73446ykvJ/mL
sCZ7zGFId2gBd1EnG0FTC4npfOKpck0X8dngByrCxU8LDSfvjsEp/xDAiKsQ
aU71tdtNBQ==
=e7jT
-----END PGP PRIVATE KEY BLOCK-----`
const keyWithExpiredCrossSig = `-----BEGIN PGP PUBLIC KEY BLOCK-----
xsDNBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
vLIwa3T4CyshfT0AEQEAAc0hQm9iIEJhYmJhZ2UgPGJvYkBvcGVucGdwLmV4YW1w
bGU+wsEABBMBCgATBYJeO2eVAgsJAxUICgKbAQIeAQAhCRD7/MgqAV5zMBYhBNGm
bhojsYLJmA94jPv8yCoBXnMwKWUMAJ3FKZfJ2mXvh+GFqgymvK4NoKkDRPB0CbUN
aDdG7ZOizQrWXo7Da2MYIZ6eZUDqBKLdhZ5gZfVnisDfu/yeCgpENaKib1MPHpA8
nZQjnPejbBDomNqY8HRzr5jvXNlwywBpjWGtegCKUY9xbSynjbfzIlMrWL4S+Rfl
+bOOQKRyYJWXmECmVyqY8cz2VUYmETjNcwC8VCDUxQnhtcCJ7Aej22hfYwVEPb/J
BsJBPq8WECCiGfJ9Y2y6TF+62KzG9Kfs5hqUeHhQy8V4TSi479ewwL7DH86XmIIK
chSANBS+7iyMtctjNZfmF9zYdGJFvjI/mbBR/lK66E515Inuf75XnL8hqlXuwqvG
ni+i03Aet1DzULZEIio4uIU6ioc1lGO9h7K2Xn4S7QQH1QoISNMWqXibUR0RCGjw
FsEDTt2QwJl8XXxoJCooM7BCcCQo+rMNVUHDjIwrdoQjPld3YZsUQQRcqH6bLuln
cfn5ufl8zTGWKydoj/iTz8KcjZ7w187AzQRdpZzyAQwA1jC/XGxjK6ddgrRfW9j+
s/U00++EvIsgTs2kr3Rg0GP7FLWV0YNtR1mpl55/bEl7yAxCDTkOgPUMXcaKlnQh
6zrlt6H53mF6Bvs3inOHQvOsGtU0dqvb1vkTF0juLiJgPlM7pWv+pNQ6IA39vKoQ
sTMBv4v5vYNXP9GgKbg8inUNT17BxzZYHfw5+q63ectgDm2on1e8CIRCZ76oBVwz
dkVxoy3gjh1eENlk2D4P0uJNZzF1Q8GV67yLANGMCDICE/OkWn6daipYDzW4iJQt
YPUWP4hWhjdm+CK+hg6IQUEn2Vtvi16D2blRP8BpUNNa4fNuylWVuJV76rIHvsLZ
1pbM3LHpRgE8s6jivS3Rz3WRs0TmWCNnvHPqWizQ3VTy+r3UQVJ5AmhJDrZdZq9i
aUIuZ01PoE1+CHiJwuxPtWvVAxf2POcm1M/F1fK1J0e+lKlQuyonTXqXR22Y41wr
fP2aPk3nPSTW2DUAf3vRMZg57ZpRxLEhEMxcM4/LMR+PABEBAAHCwrIEGAEKAAkF
gl8sAVYCmwIB3QkQ+/zIKgFeczDA+qAEGQEKAAwFgl47Z5UFgwB4TOAAIQkQfC+q
Tfk8N7IWIQQd3OFfCSF87i87N2B8L6pN+Tw3st58C/0exp0X2U4LqicSHEOSqHZj
jiysdqIELHGyo5DSPv92UFPp36aqjF9OFgtNNwSa56fmAVCD4+hor/fKARRIeIjF
qdIC5Y/9a4B10NQFJa5lsvB38x/d39LI2kEoglZnqWgdJskROo3vNQF4KlIcm6FH
dn4WI8UkC5oUUcrpZVMSKoacIaxLwqnXT42nIVgYYuqrd/ZagZZjG5WlrTOd5+NI
zi/l0fWProcPHGLjmAh4Thu8i7omtVw1nQaMnq9I77ffg3cPDgXknYrLL+q8xXh/
0mEJyIhnmPwllWCSZuLv9DrD5pOexFfdlwXhf6cLzNpW6QhXD/Tf5KrqIPr9aOv8
9xaEEXWh0vEby2kIsI2++ft+vfdIyxYw/wKqx0awTSnuBV1rG3z1dswX4BfoY66x
Bz3KOVqlz9+mG/FTRQwrgPvR+qgLCHbuotxoGN7fzW+PI75hQG5JQAqhsC9sHjQH
UrI21/VUNwzfw3v5pYsWuFb5bdQ3ASJetICQiMy7IW8WIQTRpm4aI7GCyZgPeIz7
/MgqAV5zMG6/C/wLpPl/9e6Hf5wmXIUwpZNQbNZvpiCcyx9sXsHXaycOQVxn3McZ
nYOUP9/mobl1tIeDQyTNbkxWjU0zzJl8XQsDZerb5098pg+x7oGIL7M1vn5s5JMl
owROourqF88JEtOBxLMxlAM7X4hB48xKQ3Hu9hS1GdnqLKki4MqRGl4l5FUwyGOM
GjyS3TzkfiDJNwQxybQiC9n57ij20ieNyLfuWCMLcNNnZUgZtnF6wCctoq/0ZIWu
a7nvuA/XC2WW9YjEJJiWdy5109pqac+qWiY11HWy/nms4gpMdxVpT0RhrKGWq4o0
M5q3ZElOoeN70UO3OSbU5EVrG7gB1GuwF9mTHUVlV0veSTw0axkta3FGT//XfSpD
lRrCkyLzwq0M+UUHQAuYpAfobDlDdnxxOD2jm5GyTzak3GSVFfjW09QFVO6HlGp5
01/jtzkUiS6nwoHHkfnyn0beZuR8X6KlcrzLB0VFgQFLmkSM9cSOgYhD0PTu9aHb
hW1Hj9AO8lzggBQ=
=Nt+N
-----END PGP PUBLIC KEY BLOCK-----
`
const sigFromKeyWithExpiredCrossSig = `-----BEGIN PGP SIGNATURE-----
wsDzBAABCgAGBYJfLAFsACEJEHwvqk35PDeyFiEEHdzhXwkhfO4vOzdgfC+qTfk8
N7KiqwwAts4QGB7v9bABCC2qkTxJhmStC0wQMcHRcjL/qAiVnmasQWmvE9KVsdm3
AaXd8mIx4a37/RRvr9dYrY2eE4uw72cMqPxNja2tvVXkHQvk1oEUqfkvbXs4ypKI
NyeTWjXNOTZEbg0hbm3nMy+Wv7zgB1CEvAsEboLDJlhGqPcD+X8a6CJGrBGUBUrv
KVmZr3U6vEzClz3DBLpoddCQseJRhT4YM1nKmBlZ5quh2LFgTSpajv5OsZheqt9y
EZAPbqmLhDmWRQwGzkWHKceKS7nZ/ox2WK6OS7Ob8ZGZkM64iPo6/EGj5Yc19vQN
AGiIaPEGszBBWlOpHTPhNm0LB0nMWqqaT87oNYwP8CQuuxDb6rKJ2lffCmZH27Lb
UbQZcH8J+0UhpeaiadPZxH5ATJAcenmVtVVMLVOFnm+eIlxzov9ntpgGYt8hLdXB
ITEG9mMgp3TGS9ZzSifMZ8UGtHdp9QdBg8NEVPFzDOMGxpc/Bftav7RRRuPiAER+
7A5CBid5
=aQkm
-----END PGP SIGNATURE-----
`
const signedMessageWithCriticalNotation = `-----BEGIN PGP MESSAGE-----
owGbwMvMwMH4oOW7S46CznTG09xJDDE3Wl1KUotLuDousDAwcjBYiSmyXL+48d6x
U1PSGUxcj8IUszKBVMpMaWAAAgEGZpAeh9SKxNyCnFS95PzcytRiBi5OAZjyXXzM
f8WYLqv7TXP61Sa4rqT12CI3xaN73YS2pt089f96odCKaEPnWJ3iSGmzJaW/ug10
2Zo8Wj2k4s7t8wt4H3HtTu+y5UZfV3VOO+l//sdE/o+Lsub8FZH7/eOq7OnbNp4n
vwjE8mqJXetNMfj8r2SCyvkEnlVRYR+/mnge+ib56FdJ8uKtqSxyvgA=
=fRXs
-----END PGP MESSAGE-----`
const criticalNotationSigner = `-----BEGIN PGP PUBLIC KEY BLOCK-----
mI0EUmEvTgEEANyWtQQMOybQ9JltDqmaX0WnNPJeLILIM36sw6zL0nfTQ5zXSS3+
fIF6P29lJFxpblWk02PSID5zX/DYU9/zjM2xPO8Oa4xo0cVTOTLj++Ri5mtr//f5
GLsIXxFrBJhD/ghFsL3Op0GXOeLJ9A5bsOn8th7x6JucNKuaRB6bQbSPABEBAAG0
JFRlc3QgTWNUZXN0aW5ndG9uIDx0ZXN0QGV4YW1wbGUuY29tPoi5BBMBAgAjBQJS
YS9OAhsvBwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQSmNhOk1uQJQwDAP6
AgrTyqkRlJVqz2pb46TfbDM2TDF7o9CBnBzIGoxBhlRwpqALz7z2kxBDmwpQa+ki
Bq3jZN/UosY9y8bhwMAlnrDY9jP1gdCo+H0sD48CdXybblNwaYpwqC8VSpDdTndf
9j2wE/weihGp/DAdy/2kyBCaiOY1sjhUfJ1GogF49rC4jQRSYS9OAQQA6R/PtBFa
JaT4jq10yqASk4sqwVMsc6HcifM5lSdxzExFP74naUMMyEsKHP53QxTF0Grqusag
Qg/ZtgT0CN1HUM152y7ACOdp1giKjpMzOTQClqCoclyvWOFB+L/SwGEIJf7LSCEr
woBuJifJc8xAVr0XX0JthoW+uP91eTQ3XpsAEQEAAYkBPQQYAQIACQUCUmEvTgIb
LgCoCRBKY2E6TW5AlJ0gBBkBAgAGBQJSYS9OAAoJEOCE90RsICyXuqIEANmmiRCA
SF7YK7PvFkieJNwzeK0V3F2lGX+uu6Y3Q/Zxdtwc4xR+me/CSBmsURyXTO29OWhP
GLszPH9zSJU9BdDi6v0yNprmFPX/1Ng0Abn/sCkwetvjxC1YIvTLFwtUL/7v6NS2
bZpsUxRTg9+cSrMWWSNjiY9qUKajm1tuzPDZXAUEAMNmAN3xXN/Kjyvj2OK2ck0X
W748sl/tc3qiKPMJ+0AkMF7Pjhmh9nxqE9+QCEl7qinFqqBLjuzgUhBU4QlwX1GD
AtNTq6ihLMD5v1d82ZC7tNatdlDMGWnIdvEMCv2GZcuIqDQ9rXWs49e7tq1NncLY
hz3tYjKhoFTKEIq3y3Pp
=h/aX
-----END PGP PUBLIC KEY BLOCK-----`
const keyv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
Comment: Bob's OpenPGP Transferable Secret Key
lQVYBF2lnPIBDAC5cL9PQoQLTMuhjbYvb4Ncuuo0bfmgPRFywX53jPhoFf4Zg6mv
/seOXpgecTdOcVttfzC8ycIKrt3aQTiwOG/ctaR4Bk/t6ayNFfdUNxHWk4WCKzdz
/56fW2O0F23qIRd8UUJp5IIlN4RDdRCtdhVQIAuzvp2oVy/LaS2kxQoKvph/5pQ/
5whqsyroEWDJoSV0yOb25B/iwk/pLUFoyhDG9bj0kIzDxrEqW+7Ba8nocQlecMF3
X5KMN5kp2zraLv9dlBBpWW43XktjcCZgMy20SouraVma8Je/ECwUWYUiAZxLIlMv
9CurEOtxUw6N3RdOtLmYZS9uEnn5y1UkF88o8Nku890uk6BrewFzJyLAx5wRZ4F0
qV/yq36UWQ0JB/AUGhHVPdFf6pl6eaxBwT5GXvbBUibtf8YI2og5RsgTWtXfU7eb
SGXrl5ZMpbA6mbfhd0R8aPxWfmDWiIOhBufhMCvUHh1sApMKVZnvIff9/0Dca3wb
vLIwa3T4CyshfT0AEQEAAQAL/RZqbJW2IqQDCnJi4Ozm++gPqBPiX1RhTWSjwxfM
cJKUZfzLj414rMKm6Jh1cwwGY9jekROhB9WmwaaKT8HtcIgrZNAlYzANGRCM4TLK
3VskxfSwKKna8l+s+mZglqbAjUg3wmFuf9Tj2xcUZYmyRm1DEmcN2ZzpvRtHgX7z
Wn1mAKUlSDJZSQks0zjuMNbupcpyJokdlkUg2+wBznBOTKzgMxVNC9b2g5/tMPUs
hGGWmF1UH+7AHMTaS6dlmr2ZBIyogdnfUqdNg5sZwsxSNrbglKP4sqe7X61uEAIQ
bD7rT3LonLbhkrj3I8wilUD8usIwt5IecoHhd9HziqZjRCc1BUBkboUEoyedbDV4
i4qfsFZ6CEWoLuD5pW7dEp0M+WeuHXO164Rc+LnH6i1VQrpb1Okl4qO6ejIpIjBI
1t3GshtUu/mwGBBxs60KBX5g77mFQ9lLCRj8lSYqOsHRKBhUp4qM869VA+fD0BRP
fqPT0I9IH4Oa/A3jYJcg622GwQYA1LhnP208Waf6PkQSJ6kyr8ymY1yVh9VBE/g6
fRDYA+pkqKnw9wfH2Qho3ysAA+OmVOX8Hldg+Pc0Zs0e5pCavb0En8iFLvTA0Q2E
LR5rLue9uD7aFuKFU/VdcddY9Ww/vo4k5p/tVGp7F8RYCFn9rSjIWbfvvZi1q5Tx
+akoZbga+4qQ4WYzB/obdX6SCmi6BndcQ1QdjCCQU6gpYx0MddVERbIp9+2SXDyL
hpxjSyz+RGsZi/9UAshT4txP4+MZBgDfK3ZqtW+h2/eMRxkANqOJpxSjMyLO/FXN
WxzTDYeWtHNYiAlOwlQZEPOydZFty9IVzzNFQCIUCGjQ/nNyhw7adSgUk3+BXEx/
MyJPYY0BYuhLxLYcrfQ9nrhaVKxRJj25SVHj2ASsiwGJRZW4CC3uw40OYxfKEvNC
mer/VxM3kg8qqGf9KUzJ1dVdAvjyx2Hz6jY2qWCyRQ6IMjWHyd43C4r3jxooYKUC
YnstRQyb/gCSKahveSEjo07CiXMr88UGALwzEr3npFAsPW3osGaFLj49y1oRe11E
he9gCHFm+fuzbXrWmdPjYU5/ZdqdojzDqfu4ThfnipknpVUM1o6MQqkjM896FHm8
zbKVFSMhEP6DPHSCexMFrrSgN03PdwHTO6iBaIBBFqmGY01tmJ03SxvSpiBPON9P
NVvy/6UZFedTq8A07OUAxO62YUSNtT5pmK2vzs3SAZJmbFbMh+NN204TRI72GlqT
t5hcfkuv8hrmwPS/ZR6q312mKQ6w/1pqO9qitCFCb2IgQmFiYmFnZSA8Ym9iQG9w
ZW5wZ3AuZXhhbXBsZT6JAc4EEwEKADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgEC
F4AWIQTRpm4aI7GCyZgPeIz7/MgqAV5zMAUCXaWe+gAKCRD7/MgqAV5zMG9sC/9U
2T3RrqEbw533FPNfEflhEVRIZ8gDXKM8hU6cqqEzCmzZT6xYTe6sv4y+PJBGXJFX
yhj0g6FDkSyboM5litOcTupURObVqMgA/Y4UKERznm4fzzH9qek85c4ljtLyNufe
doL2pp3vkGtn7eD0QFRaLLmnxPKQ/TlZKdLE1G3u8Uot8QHicaR6GnAdc5UXQJE3
BiV7jZuDyWmZ1cUNwJkKL6oRtp+ZNDOQCrLNLecKHcgCqrpjSQG5oouba1I1Q6Vl
sP44dhA1nkmLHtxlTOzpeHj4jnk1FaXmyasurrrI5CgU/L2Oi39DGKTH/A/cywDN
4ZplIQ9zR8enkbXquUZvFDe+Xz+6xRXtb5MwQyWODB3nHw85HocLwRoIN9WdQEI+
L8a/56AuOwhs8llkSuiITjR7r9SgKJC2WlAHl7E8lhJ3VDW3ELC56KH308d6mwOG
ZRAqIAKzM1T5FGjMBhq7ZV0eqdEntBh3EcOIfj2M8rg1MzJv+0mHZOIjByawikad
BVgEXaWc8gEMANYwv1xsYyunXYK0X1vY/rP1NNPvhLyLIE7NpK90YNBj+xS1ldGD
bUdZqZeef2xJe8gMQg05DoD1DF3GipZ0Ies65beh+d5hegb7N4pzh0LzrBrVNHar
29b5ExdI7i4iYD5TO6Vr/qTUOiAN/byqELEzAb+L+b2DVz/RoCm4PIp1DU9ewcc2
WB38Ofqut3nLYA5tqJ9XvAiEQme+qAVcM3ZFcaMt4I4dXhDZZNg+D9LiTWcxdUPB
leu8iwDRjAgyAhPzpFp+nWoqWA81uIiULWD1Fj+IVoY3ZvgivoYOiEFBJ9lbb4te
g9m5UT/AaVDTWuHzbspVlbiVe+qyB77C2daWzNyx6UYBPLOo4r0t0c91kbNE5lgj
Z7xz6los0N1U8vq91EFSeQJoSQ62XWavYmlCLmdNT6BNfgh4icLsT7Vr1QMX9jzn
JtTPxdXytSdHvpSpULsqJ016l0dtmONcK3z9mj5N5z0k1tg1AH970TGYOe2aUcSx
IRDMXDOPyzEfjwARAQABAAv9F2CwsjS+Sjh1M1vegJbZjei4gF1HHpEM0K0PSXsp
SfVvpR4AoSJ4He6CXSMWg0ot8XKtDuZoV9jnJaES5UL9pMAD7JwIOqZm/DYVJM5h
OASCh1c356/wSbFbzRHPtUdZO9Q30WFNJM5pHbCJPjtNoRmRGkf71RxtvHBzy7np
Ga+W6U/NVKHw0i0CYwMI0YlKDakYW3Pm+QL+gHZFvngGweTod0f9l2VLLAmeQR/c
+EZs7lNumhuZ8mXcwhUc9JQIhOkpO+wreDysEFkAcsKbkQP3UDUsA1gFx9pbMzT0
tr1oZq2a4QBtxShHzP/ph7KLpN+6qtjks3xB/yjTgaGmtrwM8tSe0wD1RwXS+/1o
BHpXTnQ7TfeOGUAu4KCoOQLv6ELpKWbRBLWuiPwMdbGpvVFALO8+kvKAg9/r+/ny
zM2GQHY+J3Jh5JxPiJnHfXNZjIKLbFbIPdSKNyJBuazXW8xIa//mEHMI5OcvsZBK
clAIp7LXzjEjKXIwHwDcTn9pBgDpdOKTHOtJ3JUKx0rWVsDH6wq6iKV/FTVSY5jl
zN+puOEsskF1Lfxn9JsJihAVO3yNsp6RvkKtyNlFazaCVKtDAmkjoh60XNxcNRqr
gCnwdpbgdHP6v/hvZY54ZaJjz6L2e8unNEkYLxDt8cmAyGPgH2XgL7giHIp9jrsQ
aS381gnYwNX6wE1aEikgtY91nqJjwPlibF9avSyYQoMtEqM/1UjTjB2KdD/MitK5
fP0VpvuXpNYZedmyq4UOMwdkiNMGAOrfmOeT0olgLrTMT5H97Cn3Yxbk13uXHNu/
ZUZZNe8s+QtuLfUlKAJtLEUutN33TlWQY522FV0m17S+b80xJib3yZVJteVurrh5
HSWHAM+zghQAvCesg5CLXa2dNMkTCmZKgCBvfDLZuZbjFwnwCI6u/NhOY9egKuUf
SA/je/RXaT8m5VxLYMxwqQXKApzD87fv0tLPlVIEvjEsaf992tFEFSNPcG1l/jpd
5AVXw6kKuf85UkJtYR1x2MkQDrqY1QX/XMw00kt8y9kMZUre19aCArcmor+hDhRJ
E3Gt4QJrD9z/bICESw4b4z2DbgD/Xz9IXsA/r9cKiM1h5QMtXvuhyfVeM01enhxM
GbOH3gjqqGNKysx0UODGEwr6AV9hAd8RWXMchJLaExK9J5SRawSg671ObAU24SdY
vMQ9Z4kAQ2+1ReUZzf3ogSMRZtMT+d18gT6L90/y+APZIaoArLPhebIAGq39HLmJ
26x3z0WAgrpA1kNsjXEXkoiZGPLKIGoe3hqJAbYEGAEKACAWIQTRpm4aI7GCyZgP
eIz7/MgqAV5zMAUCXaWc8gIbDAAKCRD7/MgqAV5zMOn/C/9ugt+HZIwX308zI+QX
c5vDLReuzmJ3ieE0DMO/uNSC+K1XEioSIZP91HeZJ2kbT9nn9fuReuoff0T0Dief
rbwcIQQHFFkrqSp1K3VWmUGp2JrUsXFVdjy/fkBIjTd7c5boWljv/6wAsSfiv2V0
JSM8EFU6TYXxswGjFVfc6X97tJNeIrXL+mpSmPPqy2bztcCCHkWS5lNLWQw+R7Vg
71Fe6yBSNVrqC2/imYG2J9zlowjx1XU63Wdgqp2Wxt0l8OmsB/W80S1fRF5G4SDH
s9HXglXXqPsBRZJYfP+VStm9L5P/sKjCcX6WtZR7yS6G8zj/X767MLK/djANvpPd
NVniEke6hM3CNBXYPAMhQBMWhCulcoz+0lxi8L34rMN+Dsbma96psdUrn7uLaB91
6we0CTfF8qqm7BsVAgalon/UUiuMY80U3ueoj3okiSTiHIjD/YtpXSPioC8nMng7
xqAY9Bwizt4FWgXuLm1a4+So4V9j1TRCXd12Uc2l2RNmgDE=
=miES
-----END PGP PRIVATE KEY BLOCK-----
`
const certv5Test = `-----BEGIN PGP PRIVATE KEY BLOCK-----
lGEFXJH05BYAAAAtCSsGAQQB2kcPAQEHQFhZlVcVVtwf+21xNQPX+ecMJJBL0MPd
fj75iux+my8QAAAAAAAiAQCHZ1SnSUmWqxEsoI6facIVZQu6mph3cBFzzTvcm5lA
Ng5ctBhlbW1hLmdvbGRtYW5AZXhhbXBsZS5uZXSIlgUTFggASCIhBRk0e8mHJGQC
X5nfPsLgAA7ZiEiS4fez6kyUAJFZVptUBQJckfTkAhsDBQsJCAcCAyICAQYVCgkI
CwIEFgIDAQIeBwIXgAAA9cAA/jiR3yMsZMeEQ40u6uzEoXa6UXeV/S3wwJAXRJy9
M8s0AP9vuL/7AyTfFXwwzSjDnYmzS0qAhbLDQ643N+MXGBJ2BZxmBVyR9OQSAAAA
MgorBgEEAZdVAQUBAQdA+nysrzml2UCweAqtpDuncSPlvrcBWKU0yfU0YvYWWAoD
AQgHAAAAAAAiAP9OdAPppjU1WwpqjIItkxr+VPQRT8Zm/Riw7U3F6v3OiBFHiHoF
GBYIACwiIQUZNHvJhyRkAl+Z3z7C4AAO2YhIkuH3s+pMlACRWVabVAUCXJH05AIb
DAAAOSQBAP4BOOIR/sGLNMOfeb5fPs/02QMieoiSjIBnijhob2U5AQC+RtOHCHx7
TcIYl5/Uyoi+FOvPLcNw4hOv2nwUzSSVAw==
=IiS2
-----END PGP PRIVATE KEY BLOCK-----
`
const msgv5Test = `-----BEGIN PGP MESSAGE-----
wcDMA3wvqk35PDeyAQv+PcQiLsoYTH30nJYQh3j3cJaO2+jErtVCrIQRIU0+
rmgMddERYST4A9mA0DQIiTI4FQ0Lp440D3BWCgpq3LlNWewGzduaWwym5rN6
cwHz5ccDqOcqbd9X0GXXGy/ZH/ljSgzuVMIytMAXKdF/vrRrVgH/+I7cxvm9
HwnhjMN5dF0j4aEt996H2T7cbtzSr2GN9SWGW8Gyu7I8Zx73hgrGUI7gDiJB
Afaff+P6hfkkHSGOItr94dde8J/7AUF4VEwwxdVVPvsNEFyvv6gRIbYtOCa2
6RE6h1V/QTxW2O7zZgzWALrE2ui0oaYr9QuqQSssd9CdgExLfdPbI+3/ZAnE
v31Idzpk3/6ILiakYHtXkElPXvf46mCNpobty8ysT34irF+fy3C1p3oGwAsx
5VDV9OSFU6z5U+UPbSPYAy9rkc5ZssuIKxCER2oTvZ2L8Q5cfUvEUiJtRGGn
CJlHrVDdp3FssKv2tlKgLkvxJLyoOjuEkj44H1qRk+D02FzmmUT/0sAHAYYx
lTir6mjHeLpcGjn4waUuWIAJyph8SxUexP60bic0L0NBa6Qp5SxxijKsPIDb
FPHxWwfJSDZRrgUyYT7089YFB/ZM4FHyH9TZcnxn0f0xIB7NS6YNDsxzN2zT
EVEYf+De4qT/dQTsdww78Chtcv9JY9r2kDm77dk2MUGHL2j7n8jasbLtgA7h
pn2DMIWLrGamMLWRmlwslolKr1sMV5x8w+5Ias6C33iBMl9phkg42an0gYmc
byVJHvLO/XErtC+GNIJeMg==
=liRq
-----END PGP MESSAGE-----
`
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package s2k implements the various OpenPGP string-to-key transforms as
// specified in RFC 4800 section 3.7.1, and Argon2 specified in
// draft-ietf-openpgp-crypto-refresh-08 section 3.7.1.4.
package s2k // import "github.com/ProtonMail/go-crypto/openpgp/s2k"
import (
"crypto"
"hash"
"io"
"strconv"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"golang.org/x/crypto/argon2"
)
type Mode uint8
// Defines the default S2KMode constants
//
// 0 (simple), 1(salted), 3(iterated), 4(argon2)
const (
SimpleS2K Mode = 0
SaltedS2K Mode = 1
IteratedSaltedS2K Mode = 3
Argon2S2K Mode = 4
GnuS2K Mode = 101
)
const Argon2SaltSize int = 16
// Params contains all the parameters of the s2k packet
type Params struct {
// mode is the mode of s2k function.
// It can be 0 (simple), 1(salted), 3(iterated)
// 2(reserved) 100-110(private/experimental).
mode Mode
// hashId is the ID of the hash function used in any of the modes
hashId byte
// salt is a byte array to use as a salt in hashing process or argon2
saltBytes [Argon2SaltSize]byte
// countByte is used to determine how many rounds of hashing are to
// be performed in s2k mode 3. See RFC 4880 Section 3.7.1.3.
countByte byte
// passes is a parameter in Argon2 to determine the number of iterations
// See RFC the crypto refresh Section 3.7.1.4.
passes byte
// parallelism is a parameter in Argon2 to determine the degree of paralellism
// See RFC the crypto refresh Section 3.7.1.4.
parallelism byte
// memoryExp is a parameter in Argon2 to determine the memory usage
// i.e., 2 ** memoryExp kibibytes
// See RFC the crypto refresh Section 3.7.1.4.
memoryExp byte
}
// encodeCount converts an iterative "count" in the range 1024 to
// 65011712, inclusive, to an encoded count. The return value is the
// octet that is actually stored in the GPG file. encodeCount panics
// if i is not in the above range (encodedCount above takes care to
// pass i in the correct range). See RFC 4880 Section 3.7.7.1.
func encodeCount(i int) uint8 {
if i < 65536 || i > 65011712 {
panic("count arg i outside the required range")
}
for encoded := 96; encoded < 256; encoded++ {
count := decodeCount(uint8(encoded))
if count >= i {
return uint8(encoded)
}
}
return 255
}
// decodeCount returns the s2k mode 3 iterative "count" corresponding to
// the encoded octet c.
func decodeCount(c uint8) int {
return (16 + int(c&15)) << (uint32(c>>4) + 6)
}
// encodeMemory converts the Argon2 "memory" in the range parallelism*8 to
// 2**31, inclusive, to an encoded memory. The return value is the
// octet that is actually stored in the GPG file. encodeMemory panics
// if is not in the above range
// See OpenPGP crypto refresh Section 3.7.1.4.
func encodeMemory(memory uint32, parallelism uint8) uint8 {
if memory < (8*uint32(parallelism)) || memory > uint32(2147483648) {
panic("Memory argument memory is outside the required range")
}
for exp := 3; exp < 31; exp++ {
compare := decodeMemory(uint8(exp))
if compare >= memory {
return uint8(exp)
}
}
return 31
}
// decodeMemory computes the decoded memory in kibibytes as 2**memoryExponent
func decodeMemory(memoryExponent uint8) uint32 {
return uint32(1) << memoryExponent
}
// Simple writes to out the result of computing the Simple S2K function (RFC
// 4880, section 3.7.1.1) using the given hash and input passphrase.
func Simple(out []byte, h hash.Hash, in []byte) {
Salted(out, h, in, nil)
}
var zero [1]byte
// Salted writes to out the result of computing the Salted S2K function (RFC
// 4880, section 3.7.1.2) using the given hash, input passphrase and salt.
func Salted(out []byte, h hash.Hash, in []byte, salt []byte) {
done := 0
var digest []byte
for i := 0; done < len(out); i++ {
h.Reset()
for j := 0; j < i; j++ {
h.Write(zero[:])
}
h.Write(salt)
h.Write(in)
digest = h.Sum(digest[:0])
n := copy(out[done:], digest)
done += n
}
}
// Iterated writes to out the result of computing the Iterated and Salted S2K
// function (RFC 4880, section 3.7.1.3) using the given hash, input passphrase,
// salt and iteration count.
func Iterated(out []byte, h hash.Hash, in []byte, salt []byte, count int) {
combined := make([]byte, len(in)+len(salt))
copy(combined, salt)
copy(combined[len(salt):], in)
if count < len(combined) {
count = len(combined)
}
done := 0
var digest []byte
for i := 0; done < len(out); i++ {
h.Reset()
for j := 0; j < i; j++ {
h.Write(zero[:])
}
written := 0
for written < count {
if written+len(combined) > count {
todo := count - written
h.Write(combined[:todo])
written = count
} else {
h.Write(combined)
written += len(combined)
}
}
digest = h.Sum(digest[:0])
n := copy(out[done:], digest)
done += n
}
}
// Argon2 writes to out the key derived from the password (in) with the Argon2
// function (the crypto refresh, section 3.7.1.4)
func Argon2(out []byte, in []byte, salt []byte, passes uint8, paralellism uint8, memoryExp uint8) {
key := argon2.IDKey(in, salt, uint32(passes), decodeMemory(memoryExp), paralellism, uint32(len(out)))
copy(out[:], key)
}
// Generate generates valid parameters from given configuration.
// It will enforce the Iterated and Salted or Argon2 S2K method.
func Generate(rand io.Reader, c *Config) (*Params, error) {
var params *Params
if c != nil && c.Mode() == Argon2S2K {
// handle Argon2 case
argonConfig := c.Argon2()
params = &Params{
mode: Argon2S2K,
passes: argonConfig.Passes(),
parallelism: argonConfig.Parallelism(),
memoryExp: argonConfig.EncodedMemory(),
}
} else if c != nil && c.PassphraseIsHighEntropy && c.Mode() == SaltedS2K { // Allow SaltedS2K if PassphraseIsHighEntropy
hashId, ok := algorithm.HashToHashId(c.hash())
if !ok {
return nil, errors.UnsupportedError("no such hash")
}
params = &Params{
mode: SaltedS2K,
hashId: hashId,
}
} else { // Enforce IteratedSaltedS2K method otherwise
hashId, ok := algorithm.HashToHashId(c.hash())
if !ok {
return nil, errors.UnsupportedError("no such hash")
}
if c != nil {
c.S2KMode = IteratedSaltedS2K
}
params = &Params{
mode: IteratedSaltedS2K,
hashId: hashId,
countByte: c.EncodedCount(),
}
}
if _, err := io.ReadFull(rand, params.salt()); err != nil {
return nil, err
}
return params, nil
}
// Parse reads a binary specification for a string-to-key transformation from r
// and returns a function which performs that transform. If the S2K is a special
// GNU extension that indicates that the private key is missing, then the error
// returned is errors.ErrDummyPrivateKey.
func Parse(r io.Reader) (f func(out, in []byte), err error) {
params, err := ParseIntoParams(r)
if err != nil {
return nil, err
}
return params.Function()
}
// ParseIntoParams reads a binary specification for a string-to-key
// transformation from r and returns a struct describing the s2k parameters.
func ParseIntoParams(r io.Reader) (params *Params, err error) {
var buf [Argon2SaltSize + 3]byte
_, err = io.ReadFull(r, buf[:1])
if err != nil {
return
}
params = &Params{
mode: Mode(buf[0]),
}
switch params.mode {
case SimpleS2K:
_, err = io.ReadFull(r, buf[:1])
if err != nil {
return nil, err
}
params.hashId = buf[0]
return params, nil
case SaltedS2K:
_, err = io.ReadFull(r, buf[:9])
if err != nil {
return nil, err
}
params.hashId = buf[0]
copy(params.salt(), buf[1:9])
return params, nil
case IteratedSaltedS2K:
_, err = io.ReadFull(r, buf[:10])
if err != nil {
return nil, err
}
params.hashId = buf[0]
copy(params.salt(), buf[1:9])
params.countByte = buf[9]
return params, nil
case Argon2S2K:
_, err = io.ReadFull(r, buf[:Argon2SaltSize+3])
if err != nil {
return nil, err
}
copy(params.salt(), buf[:Argon2SaltSize])
params.passes = buf[Argon2SaltSize]
params.parallelism = buf[Argon2SaltSize+1]
params.memoryExp = buf[Argon2SaltSize+2]
if err := validateArgon2Params(params); err != nil {
return nil, err
}
return params, nil
case GnuS2K:
// This is a GNU extension. See
// https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob;f=doc/DETAILS;h=fe55ae16ab4e26d8356dc574c9e8bc935e71aef1;hb=23191d7851eae2217ecdac6484349849a24fd94a#l1109
if _, err = io.ReadFull(r, buf[:5]); err != nil {
return nil, err
}
params.hashId = buf[0]
if buf[1] == 'G' && buf[2] == 'N' && buf[3] == 'U' && buf[4] == 1 {
return params, nil
}
return nil, errors.UnsupportedError("GNU S2K extension")
}
return nil, errors.UnsupportedError("S2K function")
}
func (params *Params) Mode() Mode {
return params.mode
}
func (params *Params) Dummy() bool {
return params != nil && params.mode == GnuS2K
}
func (params *Params) salt() []byte {
switch params.mode {
case SaltedS2K, IteratedSaltedS2K:
return params.saltBytes[:8]
case Argon2S2K:
return params.saltBytes[:Argon2SaltSize]
default:
return nil
}
}
func (params *Params) Function() (f func(out, in []byte), err error) {
if params.Dummy() {
return nil, errors.ErrDummyPrivateKey("dummy key found")
}
var hashObj crypto.Hash
if params.mode != Argon2S2K {
var ok bool
hashObj, ok = algorithm.HashIdToHashWithSha1(params.hashId)
if !ok {
return nil, errors.UnsupportedError("hash for S2K function: " + strconv.Itoa(int(params.hashId)))
}
if !hashObj.Available() {
return nil, errors.UnsupportedError("hash not available: " + strconv.Itoa(int(hashObj)))
}
}
switch params.mode {
case SimpleS2K:
f := func(out, in []byte) {
Simple(out, hashObj.New(), in)
}
return f, nil
case SaltedS2K:
f := func(out, in []byte) {
Salted(out, hashObj.New(), in, params.salt())
}
return f, nil
case IteratedSaltedS2K:
f := func(out, in []byte) {
Iterated(out, hashObj.New(), in, params.salt(), decodeCount(params.countByte))
}
return f, nil
case Argon2S2K:
f := func(out, in []byte) {
Argon2(out, in, params.salt(), params.passes, params.parallelism, params.memoryExp)
}
return f, nil
}
return nil, errors.UnsupportedError("S2K function")
}
func (params *Params) Serialize(w io.Writer) (err error) {
if _, err = w.Write([]byte{uint8(params.mode)}); err != nil {
return
}
if params.mode != Argon2S2K {
if _, err = w.Write([]byte{params.hashId}); err != nil {
return
}
}
if params.Dummy() {
_, err = w.Write(append([]byte("GNU"), 1))
return
}
if params.mode > 0 {
if _, err = w.Write(params.salt()); err != nil {
return
}
if params.mode == IteratedSaltedS2K {
_, err = w.Write([]byte{params.countByte})
}
if params.mode == Argon2S2K {
_, err = w.Write([]byte{params.passes, params.parallelism, params.memoryExp})
}
}
return
}
// Serialize salts and stretches the given passphrase and writes the
// resulting key into key. It also serializes an S2K descriptor to
// w. The key stretching can be configured with c, which may be
// nil. In that case, sensible defaults will be used.
func Serialize(w io.Writer, key []byte, rand io.Reader, passphrase []byte, c *Config) error {
params, err := Generate(rand, c)
if err != nil {
return err
}
err = params.Serialize(w)
if err != nil {
return err
}
f, err := params.Function()
if err != nil {
return err
}
f(key, passphrase)
return nil
}
// validateArgon2Params checks that the argon2 parameters are valid according to RFC9580.
func validateArgon2Params(params *Params) error {
// The number of passes t and the degree of parallelism p MUST be non-zero.
if params.parallelism == 0 {
return errors.StructuralError("invalid argon2 params: parallelism is 0")
}
if params.passes == 0 {
return errors.StructuralError("invalid argon2 params: iterations is 0")
}
// The encoded memory size MUST be a value from 3+ceil(log2(p)) to 31,
// such that the decoded memory size m is a value from 8*p to 2^31.
if params.memoryExp > 31 || decodeMemory(params.memoryExp) < 8*uint32(params.parallelism) {
return errors.StructuralError("invalid argon2 params: memory is out of bounds")
}
return nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_cache.go
================================================
package s2k
// Cache stores keys derived with s2k functions from one passphrase
// to avoid recomputation if multiple items are encrypted with
// the same parameters.
type Cache map[Params][]byte
// GetOrComputeDerivedKey tries to retrieve the key
// for the given s2k parameters from the cache.
// If there is no hit, it derives the key with the s2k function from the passphrase,
// updates the cache, and returns the key.
func (c *Cache) GetOrComputeDerivedKey(passphrase []byte, params *Params, expectedKeySize int) ([]byte, error) {
key, found := (*c)[*params]
if !found || len(key) != expectedKeySize {
var err error
derivedKey := make([]byte, expectedKeySize)
s2k, err := params.Function()
if err != nil {
return nil, err
}
s2k(derivedKey, passphrase)
(*c)[*params] = key
return derivedKey, nil
}
return key, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/s2k/s2k_config.go
================================================
package s2k
import "crypto"
// Config collects configuration parameters for s2k key-stretching
// transformations. A nil *Config is valid and results in all default
// values.
type Config struct {
// S2K (String to Key) mode, used for key derivation in the context of secret key encryption
// and passphrase-encrypted data. Either s2k.Argon2S2K or s2k.IteratedSaltedS2K may be used.
// If the passphrase is a high-entropy key, indicated by setting PassphraseIsHighEntropy to true,
// s2k.SaltedS2K can also be used.
// Note: Argon2 is the strongest option but not all OpenPGP implementations are compatible with it
//(pending standardisation).
// 0 (simple), 1(salted), 3(iterated), 4(argon2)
// 2(reserved) 100-110(private/experimental).
S2KMode Mode
// Only relevant if S2KMode is not set to s2k.Argon2S2K.
// Hash is the default hash function to be used. If
// nil, SHA256 is used.
Hash crypto.Hash
// Argon2 parameters for S2K (String to Key).
// Only relevant if S2KMode is set to s2k.Argon2S2K.
// If nil, default parameters are used.
// For more details on the choice of parameters, see https://tools.ietf.org/html/rfc9106#section-4.
Argon2Config *Argon2Config
// Only relevant if S2KMode is set to s2k.IteratedSaltedS2K.
// Iteration count for Iterated S2K (String to Key). It
// determines the strength of the passphrase stretching when
// the said passphrase is hashed to produce a key. S2KCount
// should be between 65536 and 65011712, inclusive. If Config
// is nil or S2KCount is 0, the value 16777216 used. Not all
// values in the above range can be represented. S2KCount will
// be rounded up to the next representable value if it cannot
// be encoded exactly. When set, it is strongly encrouraged to
// use a value that is at least 65536. See RFC 4880 Section
// 3.7.1.3.
S2KCount int
// Indicates whether the passphrase passed by the application is a
// high-entropy key (e.g. it's randomly generated or derived from
// another passphrase using a strong key derivation function).
// When true, allows the S2KMode to be s2k.SaltedS2K.
// When the passphrase is not a high-entropy key, using SaltedS2K is
// insecure, and not allowed by draft-ietf-openpgp-crypto-refresh-08.
PassphraseIsHighEntropy bool
}
// Argon2Config stores the Argon2 parameters
// A nil *Argon2Config is valid and results in all default
type Argon2Config struct {
NumberOfPasses uint8
DegreeOfParallelism uint8
// Memory specifies the desired Argon2 memory usage in kibibytes.
// For example memory=64*1024 sets the memory cost to ~64 MB.
Memory uint32
}
func (c *Config) Mode() Mode {
if c == nil {
return IteratedSaltedS2K
}
return c.S2KMode
}
func (c *Config) hash() crypto.Hash {
if c == nil || uint(c.Hash) == 0 {
return crypto.SHA256
}
return c.Hash
}
func (c *Config) Argon2() *Argon2Config {
if c == nil || c.Argon2Config == nil {
return nil
}
return c.Argon2Config
}
// EncodedCount get encoded count
func (c *Config) EncodedCount() uint8 {
if c == nil || c.S2KCount == 0 {
return 224 // The common case. Corresponding to 16777216
}
i := c.S2KCount
switch {
case i < 65536:
i = 65536
case i > 65011712:
i = 65011712
}
return encodeCount(i)
}
func (c *Argon2Config) Passes() uint8 {
if c == nil || c.NumberOfPasses == 0 {
return 3
}
return c.NumberOfPasses
}
func (c *Argon2Config) Parallelism() uint8 {
if c == nil || c.DegreeOfParallelism == 0 {
return 4
}
return c.DegreeOfParallelism
}
func (c *Argon2Config) EncodedMemory() uint8 {
if c == nil || c.Memory == 0 {
return 16 // 64 MiB of RAM
}
memory := c.Memory
lowerBound := uint32(c.Parallelism()) * 8
upperBound := uint32(2147483648)
switch {
case memory < lowerBound:
memory = lowerBound
case memory > upperBound:
memory = upperBound
}
return encodeMemory(memory, c.Parallelism())
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/write.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package openpgp
import (
"crypto"
"hash"
"io"
"strconv"
"time"
"github.com/ProtonMail/go-crypto/openpgp/armor"
"github.com/ProtonMail/go-crypto/openpgp/errors"
"github.com/ProtonMail/go-crypto/openpgp/internal/algorithm"
"github.com/ProtonMail/go-crypto/openpgp/packet"
)
// DetachSign signs message with the private key from signer (which must
// already have been decrypted) and writes the signature to w.
// If config is nil, sensible defaults will be used.
func DetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
return detachSign(w, signer, message, packet.SigTypeBinary, config)
}
// ArmoredDetachSign signs message with the private key from signer (which
// must already have been decrypted) and writes an armored signature to w.
// If config is nil, sensible defaults will be used.
func ArmoredDetachSign(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) (err error) {
return armoredDetachSign(w, signer, message, packet.SigTypeBinary, config)
}
// DetachSignText signs message (after canonicalising the line endings) with
// the private key from signer (which must already have been decrypted) and
// writes the signature to w.
// If config is nil, sensible defaults will be used.
func DetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
return detachSign(w, signer, message, packet.SigTypeText, config)
}
// ArmoredDetachSignText signs message (after canonicalising the line endings)
// with the private key from signer (which must already have been decrypted)
// and writes an armored signature to w.
// If config is nil, sensible defaults will be used.
func ArmoredDetachSignText(w io.Writer, signer *Entity, message io.Reader, config *packet.Config) error {
return armoredDetachSign(w, signer, message, packet.SigTypeText, config)
}
func armoredDetachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
out, err := armor.Encode(w, SignatureType, nil)
if err != nil {
return
}
err = detachSign(out, signer, message, sigType, config)
if err != nil {
return
}
return out.Close()
}
func detachSign(w io.Writer, signer *Entity, message io.Reader, sigType packet.SignatureType, config *packet.Config) (err error) {
signingKey, ok := signer.SigningKeyById(config.Now(), config.SigningKey())
if !ok {
return errors.InvalidArgumentError("no valid signing keys")
}
if signingKey.PrivateKey == nil {
return errors.InvalidArgumentError("signing key doesn't have a private key")
}
if signingKey.PrivateKey.Encrypted {
return errors.InvalidArgumentError("signing key is encrypted")
}
if _, ok := algorithm.HashToHashId(config.Hash()); !ok {
return errors.InvalidArgumentError("invalid hash function")
}
sig := createSignaturePacket(signingKey.PublicKey, sigType, config)
h, err := sig.PrepareSign(config)
if err != nil {
return
}
wrappedHash, err := wrapHashForSignature(h, sig.SigType)
if err != nil {
return
}
if _, err = io.Copy(wrappedHash, message); err != nil {
return err
}
err = sig.Sign(h, signingKey.PrivateKey, config)
if err != nil {
return
}
return sig.Serialize(w)
}
// FileHints contains metadata about encrypted files. This metadata is, itself,
// encrypted.
type FileHints struct {
// IsBinary can be set to hint that the contents are binary data.
IsBinary bool
// FileName hints at the name of the file that should be written. It's
// truncated to 255 bytes if longer. It may be empty to suggest that the
// file should not be written to disk. It may be equal to "_CONSOLE" to
// suggest the data should not be written to disk.
FileName string
// ModTime contains the modification time of the file, or the zero time if not applicable.
ModTime time.Time
}
// SymmetricallyEncrypt acts like gpg -c: it encrypts a file with a passphrase.
// The resulting WriteCloser must be closed after the contents of the file have
// been written.
// If config is nil, sensible defaults will be used.
func SymmetricallyEncrypt(ciphertext io.Writer, passphrase []byte, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
if hints == nil {
hints = &FileHints{}
}
key, err := packet.SerializeSymmetricKeyEncrypted(ciphertext, passphrase, config)
if err != nil {
return
}
var w io.WriteCloser
cipherSuite := packet.CipherSuite{
Cipher: config.Cipher(),
Mode: config.AEAD().Mode(),
}
w, err = packet.SerializeSymmetricallyEncrypted(ciphertext, config.Cipher(), config.AEAD() != nil, cipherSuite, key, config)
if err != nil {
return
}
literalData := w
if algo := config.Compression(); algo != packet.CompressionNone {
var compConfig *packet.CompressionConfig
if config != nil {
compConfig = config.CompressionConfig
}
literalData, err = packet.SerializeCompressed(w, algo, compConfig)
if err != nil {
return
}
}
var epochSeconds uint32
if !hints.ModTime.IsZero() {
epochSeconds = uint32(hints.ModTime.Unix())
}
return packet.SerializeLiteral(literalData, hints.IsBinary, hints.FileName, epochSeconds)
}
// intersectPreferences mutates and returns a prefix of a that contains only
// the values in the intersection of a and b. The order of a is preserved.
func intersectPreferences(a []uint8, b []uint8) (intersection []uint8) {
var j int
for _, v := range a {
for _, v2 := range b {
if v == v2 {
a[j] = v
j++
break
}
}
}
return a[:j]
}
// intersectPreferences mutates and returns a prefix of a that contains only
// the values in the intersection of a and b. The order of a is preserved.
func intersectCipherSuites(a [][2]uint8, b [][2]uint8) (intersection [][2]uint8) {
var j int
for _, v := range a {
for _, v2 := range b {
if v[0] == v2[0] && v[1] == v2[1] {
a[j] = v
j++
break
}
}
}
return a[:j]
}
func hashToHashId(h crypto.Hash) uint8 {
v, ok := algorithm.HashToHashId(h)
if !ok {
panic("tried to convert unknown hash")
}
return v
}
// EncryptText encrypts a message to a number of recipients and, optionally,
// signs it. Optional information is contained in 'hints', also encrypted, that
// aids the recipients in processing the message. The resulting WriteCloser
// must be closed after the contents of the file have been written. If config
// is nil, sensible defaults will be used. The signing is done in text mode.
func EncryptText(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeText, config)
}
// Encrypt encrypts a message to a number of recipients and, optionally, signs
// it. hints contains optional information, that is also encrypted, that aids
// the recipients in processing the message. The resulting WriteCloser must
// be closed after the contents of the file have been written.
// If config is nil, sensible defaults will be used.
func Encrypt(ciphertext io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
return encrypt(ciphertext, ciphertext, to, signed, hints, packet.SigTypeBinary, config)
}
// EncryptSplit encrypts a message to a number of recipients and, optionally, signs
// it. hints contains optional information, that is also encrypted, that aids
// the recipients in processing the message. The resulting WriteCloser must
// be closed after the contents of the file have been written.
// If config is nil, sensible defaults will be used.
func EncryptSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeBinary, config)
}
// EncryptTextSplit encrypts a message to a number of recipients and, optionally, signs
// it. hints contains optional information, that is also encrypted, that aids
// the recipients in processing the message. The resulting WriteCloser must
// be closed after the contents of the file have been written.
// If config is nil, sensible defaults will be used.
func EncryptTextSplit(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, config *packet.Config) (plaintext io.WriteCloser, err error) {
return encrypt(keyWriter, dataWriter, to, signed, hints, packet.SigTypeText, config)
}
// writeAndSign writes the data as a payload package and, optionally, signs
// it. hints contains optional information, that is also encrypted,
// that aids the recipients in processing the message. The resulting
// WriteCloser must be closed after the contents of the file have been
// written. If config is nil, sensible defaults will be used.
func writeAndSign(payload io.WriteCloser, candidateHashes []uint8, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) {
var signer *packet.PrivateKey
if signed != nil {
signKey, ok := signed.SigningKeyById(config.Now(), config.SigningKey())
if !ok {
return nil, errors.InvalidArgumentError("no valid signing keys")
}
signer = signKey.PrivateKey
if signer == nil {
return nil, errors.InvalidArgumentError("no private key in signing key")
}
if signer.Encrypted {
return nil, errors.InvalidArgumentError("signing key must be decrypted")
}
}
var hash crypto.Hash
for _, hashId := range candidateHashes {
if h, ok := algorithm.HashIdToHash(hashId); ok && h.Available() {
hash = h
break
}
}
// If the hash specified by config is a candidate, we'll use that.
if configuredHash := config.Hash(); configuredHash.Available() {
for _, hashId := range candidateHashes {
if h, ok := algorithm.HashIdToHash(hashId); ok && h == configuredHash {
hash = h
break
}
}
}
if hash == 0 {
hashId := candidateHashes[0]
name, ok := algorithm.HashIdToString(hashId)
if !ok {
name = "#" + strconv.Itoa(int(hashId))
}
return nil, errors.InvalidArgumentError("cannot encrypt because no candidate hash functions are compiled in. (Wanted " + name + " in this case.)")
}
var salt []byte
if signer != nil {
var opsVersion = 3
if signer.Version == 6 {
opsVersion = signer.Version
}
ops := &packet.OnePassSignature{
Version: opsVersion,
SigType: sigType,
Hash: hash,
PubKeyAlgo: signer.PubKeyAlgo,
KeyId: signer.KeyId,
IsLast: true,
}
if opsVersion == 6 {
ops.KeyFingerprint = signer.Fingerprint
salt, err = packet.SignatureSaltForHash(hash, config.Random())
if err != nil {
return nil, err
}
ops.Salt = salt
}
if err := ops.Serialize(payload); err != nil {
return nil, err
}
}
if hints == nil {
hints = &FileHints{}
}
w := payload
if signer != nil {
// If we need to write a signature packet after the literal
// data then we need to stop literalData from closing
// encryptedData.
w = noOpCloser{w}
}
var epochSeconds uint32
if !hints.ModTime.IsZero() {
epochSeconds = uint32(hints.ModTime.Unix())
}
literalData, err := packet.SerializeLiteral(w, hints.IsBinary, hints.FileName, epochSeconds)
if err != nil {
return nil, err
}
if signer != nil {
h, wrappedHash, err := hashForSignature(hash, sigType, salt)
if err != nil {
return nil, err
}
metadata := &packet.LiteralData{
Format: 'u',
FileName: hints.FileName,
Time: epochSeconds,
}
if hints.IsBinary {
metadata.Format = 'b'
}
return signatureWriter{payload, literalData, hash, wrappedHash, h, salt, signer, sigType, config, metadata}, nil
}
return literalData, nil
}
// encrypt encrypts a message to a number of recipients and, optionally, signs
// it. hints contains optional information, that is also encrypted, that aids
// the recipients in processing the message. The resulting WriteCloser must
// be closed after the contents of the file have been written.
// If config is nil, sensible defaults will be used.
func encrypt(keyWriter io.Writer, dataWriter io.Writer, to []*Entity, signed *Entity, hints *FileHints, sigType packet.SignatureType, config *packet.Config) (plaintext io.WriteCloser, err error) {
if len(to) == 0 {
return nil, errors.InvalidArgumentError("no encryption recipient provided")
}
// These are the possible ciphers that we'll use for the message.
candidateCiphers := []uint8{
uint8(packet.CipherAES256),
uint8(packet.CipherAES128),
}
// These are the possible hash functions that we'll use for the signature.
candidateHashes := []uint8{
hashToHashId(crypto.SHA256),
hashToHashId(crypto.SHA384),
hashToHashId(crypto.SHA512),
hashToHashId(crypto.SHA3_256),
hashToHashId(crypto.SHA3_512),
}
// Prefer GCM if everyone supports it
candidateCipherSuites := [][2]uint8{
{uint8(packet.CipherAES256), uint8(packet.AEADModeGCM)},
{uint8(packet.CipherAES256), uint8(packet.AEADModeEAX)},
{uint8(packet.CipherAES256), uint8(packet.AEADModeOCB)},
{uint8(packet.CipherAES128), uint8(packet.AEADModeGCM)},
{uint8(packet.CipherAES128), uint8(packet.AEADModeEAX)},
{uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)},
}
candidateCompression := []uint8{
uint8(packet.CompressionNone),
uint8(packet.CompressionZIP),
uint8(packet.CompressionZLIB),
}
encryptKeys := make([]Key, len(to))
// AEAD is used only if config enables it and every key supports it
aeadSupported := config.AEAD() != nil
for i := range to {
var ok bool
encryptKeys[i], ok = to[i].EncryptionKey(config.Now())
if !ok {
return nil, errors.InvalidArgumentError("cannot encrypt a message to key id " + strconv.FormatUint(to[i].PrimaryKey.KeyId, 16) + " because it has no valid encryption keys")
}
primarySelfSignature, _ := to[i].PrimarySelfSignature()
if primarySelfSignature == nil {
return nil, errors.InvalidArgumentError("entity without a self-signature")
}
if !primarySelfSignature.SEIPDv2 {
aeadSupported = false
}
candidateCiphers = intersectPreferences(candidateCiphers, primarySelfSignature.PreferredSymmetric)
candidateHashes = intersectPreferences(candidateHashes, primarySelfSignature.PreferredHash)
candidateCipherSuites = intersectCipherSuites(candidateCipherSuites, primarySelfSignature.PreferredCipherSuites)
candidateCompression = intersectPreferences(candidateCompression, primarySelfSignature.PreferredCompression)
}
// In the event that the intersection of supported algorithms is empty we use the ones
// labelled as MUST that every implementation supports.
if len(candidateCiphers) == 0 {
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.3
candidateCiphers = []uint8{uint8(packet.CipherAES128)}
}
if len(candidateHashes) == 0 {
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#hash-algos
candidateHashes = []uint8{hashToHashId(crypto.SHA256)}
}
if len(candidateCipherSuites) == 0 {
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.6
candidateCipherSuites = [][2]uint8{{uint8(packet.CipherAES128), uint8(packet.AEADModeOCB)}}
}
cipher := packet.CipherFunction(candidateCiphers[0])
aeadCipherSuite := packet.CipherSuite{
Cipher: packet.CipherFunction(candidateCipherSuites[0][0]),
Mode: packet.AEADMode(candidateCipherSuites[0][1]),
}
// If the cipher specified by config is a candidate, we'll use that.
configuredCipher := config.Cipher()
for _, c := range candidateCiphers {
cipherFunc := packet.CipherFunction(c)
if cipherFunc == configuredCipher {
cipher = cipherFunc
break
}
}
var symKey []byte
if aeadSupported {
symKey = make([]byte, aeadCipherSuite.Cipher.KeySize())
} else {
symKey = make([]byte, cipher.KeySize())
}
if _, err := io.ReadFull(config.Random(), symKey); err != nil {
return nil, err
}
for _, key := range encryptKeys {
if err := packet.SerializeEncryptedKeyAEAD(keyWriter, key.PublicKey, cipher, aeadSupported, symKey, config); err != nil {
return nil, err
}
}
var payload io.WriteCloser
payload, err = packet.SerializeSymmetricallyEncrypted(dataWriter, cipher, aeadSupported, aeadCipherSuite, symKey, config)
if err != nil {
return
}
payload, err = handleCompression(payload, candidateCompression, config)
if err != nil {
return nil, err
}
return writeAndSign(payload, candidateHashes, signed, hints, sigType, config)
}
// Sign signs a message. The resulting WriteCloser must be closed after the
// contents of the file have been written. hints contains optional information
// that aids the recipients in processing the message.
// If config is nil, sensible defaults will be used.
func Sign(output io.Writer, signed *Entity, hints *FileHints, config *packet.Config) (input io.WriteCloser, err error) {
if signed == nil {
return nil, errors.InvalidArgumentError("no signer provided")
}
// These are the possible hash functions that we'll use for the signature.
candidateHashes := []uint8{
hashToHashId(crypto.SHA256),
hashToHashId(crypto.SHA384),
hashToHashId(crypto.SHA512),
hashToHashId(crypto.SHA3_256),
hashToHashId(crypto.SHA3_512),
}
defaultHashes := candidateHashes[0:1]
primarySelfSignature, _ := signed.PrimarySelfSignature()
if primarySelfSignature == nil {
return nil, errors.StructuralError("signed entity has no self-signature")
}
preferredHashes := primarySelfSignature.PreferredHash
if len(preferredHashes) == 0 {
preferredHashes = defaultHashes
}
candidateHashes = intersectPreferences(candidateHashes, preferredHashes)
if len(candidateHashes) == 0 {
return nil, errors.StructuralError("cannot sign because signing key shares no common algorithms with candidate hashes")
}
return writeAndSign(noOpCloser{output}, candidateHashes, signed, hints, packet.SigTypeBinary, config)
}
// signatureWriter hashes the contents of a message while passing it along to
// literalData. When closed, it closes literalData, writes a signature packet
// to encryptedData and then also closes encryptedData.
type signatureWriter struct {
encryptedData io.WriteCloser
literalData io.WriteCloser
hashType crypto.Hash
wrappedHash hash.Hash
h hash.Hash
salt []byte // v6 only
signer *packet.PrivateKey
sigType packet.SignatureType
config *packet.Config
metadata *packet.LiteralData // V5 signatures protect document metadata
}
func (s signatureWriter) Write(data []byte) (int, error) {
s.wrappedHash.Write(data)
switch s.sigType {
case packet.SigTypeBinary:
return s.literalData.Write(data)
case packet.SigTypeText:
flag := 0
return writeCanonical(s.literalData, data, &flag)
}
return 0, errors.UnsupportedError("unsupported signature type: " + strconv.Itoa(int(s.sigType)))
}
func (s signatureWriter) Close() error {
sig := createSignaturePacket(&s.signer.PublicKey, s.sigType, s.config)
sig.Hash = s.hashType
sig.Metadata = s.metadata
if err := sig.SetSalt(s.salt); err != nil {
return err
}
if err := sig.Sign(s.h, s.signer, s.config); err != nil {
return err
}
if err := s.literalData.Close(); err != nil {
return err
}
if err := sig.Serialize(s.encryptedData); err != nil {
return err
}
return s.encryptedData.Close()
}
func createSignaturePacket(signer *packet.PublicKey, sigType packet.SignatureType, config *packet.Config) *packet.Signature {
sigLifetimeSecs := config.SigLifetime()
return &packet.Signature{
Version: signer.Version,
SigType: sigType,
PubKeyAlgo: signer.PubKeyAlgo,
Hash: config.Hash(),
CreationTime: config.Now(),
IssuerKeyId: &signer.KeyId,
IssuerFingerprint: signer.Fingerprint,
Notations: config.Notations(),
SigLifetimeSecs: &sigLifetimeSecs,
}
}
// noOpCloser is like an ioutil.NopCloser, but for an io.Writer.
// TODO: we have two of these in OpenPGP packages alone. This probably needs
// to be promoted somewhere more common.
type noOpCloser struct {
w io.Writer
}
func (c noOpCloser) Write(data []byte) (n int, err error) {
return c.w.Write(data)
}
func (c noOpCloser) Close() error {
return nil
}
func handleCompression(compressed io.WriteCloser, candidateCompression []uint8, config *packet.Config) (data io.WriteCloser, err error) {
data = compressed
confAlgo := config.Compression()
if confAlgo == packet.CompressionNone {
return
}
// Set algorithm labelled as MUST as fallback
// https://www.ietf.org/archive/id/draft-ietf-openpgp-crypto-refresh-07.html#section-9.4
finalAlgo := packet.CompressionNone
// if compression specified by config available we will use it
for _, c := range candidateCompression {
if uint8(confAlgo) == c {
finalAlgo = confAlgo
break
}
}
if finalAlgo != packet.CompressionNone {
var compConfig *packet.CompressionConfig
if config != nil {
compConfig = config.CompressionConfig
}
data, err = packet.SerializeCompressed(compressed, finalAlgo, compConfig)
if err != nil {
return
}
}
return data, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/x25519/x25519.go
================================================
package x25519
import (
"crypto/sha256"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x25519lib "github.com/cloudflare/circl/dh/x25519"
"golang.org/x/crypto/hkdf"
)
const (
hkdfInfo = "OpenPGP X25519"
aes128KeySize = 16
// The size of a public or private key in bytes.
KeySize = x25519lib.Size
)
type PublicKey struct {
// Point represents the encoded elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Secret represents the secret of the private key.
Secret []byte
}
// NewPrivateKey creates a new empty private key including the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Validate validates that the provided public key matches the private key.
func Validate(pk *PrivateKey) (err error) {
var expectedPublicKey, privateKey x25519lib.Key
subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
x25519lib.KeyGen(&expectedPublicKey, &privateKey)
if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
return errors.KeyInvalidError("x25519: invalid key")
}
return nil
}
// GenerateKey generates a new x25519 key pair.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
var privateKey, publicKey x25519lib.Key
privateKeyOut := new(PrivateKey)
err := generateKey(rand, &privateKey, &publicKey)
if err != nil {
return nil, err
}
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Secret = privateKey[:]
return privateKeyOut, nil
}
func generateKey(rand io.Reader, privateKey *x25519lib.Key, publicKey *x25519lib.Key) error {
maxRounds := 10
isZero := true
for round := 0; isZero; round++ {
if round == maxRounds {
return errors.InvalidArgumentError("x25519: zero keys only, randomness source might be corrupt")
}
_, err := io.ReadFull(rand, privateKey[:])
if err != nil {
return err
}
isZero = constantTimeIsZero(privateKey[:])
}
x25519lib.KeyGen(publicKey, privateKey)
return nil
}
// Encrypt encrypts a sessionKey with x25519 according to
// the OpenPGP crypto refresh specification section 5.1.6. The function assumes that the
// sessionKey has the correct format and padding according to the specification.
func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
var ephemeralPrivate, ephemeralPublic, staticPublic, shared x25519lib.Key
// Check that the input static public key has 32 bytes
if len(publicKey.Point) != KeySize {
err = errors.KeyInvalidError("x25519: the public key has the wrong size")
return
}
copy(staticPublic[:], publicKey.Point)
// Generate ephemeral keyPair
err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic)
if err != nil {
return
}
// Compute shared key
ok := x25519lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
if !ok {
err = errors.KeyInvalidError("x25519: the public key is a low order point")
return
}
// Derive the encryption key from the shared secret
encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
ephemeralPublicKey = &PublicKey{
Point: ephemeralPublic[:],
}
// Encrypt the sessionKey with aes key wrapping
encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
return
}
// Decrypt decrypts a session key stored in ciphertext with the provided x25519
// private key and ephemeral public key.
func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
var ephemeralPublic, staticPrivate, shared x25519lib.Key
// Check that the input ephemeral public key has 32 bytes
if len(ephemeralPublicKey.Point) != KeySize {
err = errors.KeyInvalidError("x25519: the public key has the wrong size")
return
}
copy(ephemeralPublic[:], ephemeralPublicKey.Point)
subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
// Compute shared key
ok := x25519lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
if !ok {
err = errors.KeyInvalidError("x25519: the ephemeral public key is a low order point")
return
}
// Derive the encryption key from the shared secret
encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
// Decrypt the session key with aes key wrapping
encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
return
}
func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
inputKey := make([]byte, 3*KeySize)
// ephemeral public key | recipient public key | shared secret
subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
hkdfReader := hkdf.New(sha256.New, inputKey, []byte{}, []byte(hkdfInfo))
encryptionKey := make([]byte, aes128KeySize)
_, _ = io.ReadFull(hkdfReader, encryptionKey)
return encryptionKey
}
func constantTimeIsZero(bytes []byte) bool {
isZero := byte(0)
for _, b := range bytes {
isZero |= b
}
return isZero == 0
}
// ENCODING/DECODING ciphertexts:
// EncodeFieldsLength returns the length of the ciphertext encoding
// given the encrypted session key.
func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
lenCipherFunction := 0
if !v6 {
lenCipherFunction = 1
}
return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
}
// EncodeField encodes x25519 session key encryption fields as
// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
// and writes it to writer.
func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
lenAlgorithm := 0
if !v6 {
lenAlgorithm = 1
}
if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
return err
}
if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
return err
}
if !v6 {
if _, err = writer.Write([]byte{cipherFunction}); err != nil {
return err
}
}
_, err = writer.Write(encryptedSessionKey)
return err
}
// DecodeField decodes a x25519 session key encryption as
// ephemeral x25519 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
var buf [1]byte
ephemeralPublicKey = &PublicKey{
Point: make([]byte, KeySize),
}
// 32 octets representing an ephemeral x25519 public key.
if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
return nil, nil, 0, err
}
// A one-octet size of the following fields.
if _, err = io.ReadFull(reader, buf[:]); err != nil {
return nil, nil, 0, err
}
followingLen := buf[0]
// The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
if !v6 {
if _, err = io.ReadFull(reader, buf[:]); err != nil {
return nil, nil, 0, err
}
cipherFunction = buf[0]
followingLen -= 1
}
// The encrypted session key.
encryptedSessionKey = make([]byte, followingLen)
if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
return nil, nil, 0, err
}
return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
}
================================================
FILE: vendor/github.com/ProtonMail/go-crypto/openpgp/x448/x448.go
================================================
package x448
import (
"crypto/sha512"
"crypto/subtle"
"io"
"github.com/ProtonMail/go-crypto/openpgp/aes/keywrap"
"github.com/ProtonMail/go-crypto/openpgp/errors"
x448lib "github.com/cloudflare/circl/dh/x448"
"golang.org/x/crypto/hkdf"
)
const (
hkdfInfo = "OpenPGP X448"
aes256KeySize = 32
// The size of a public or private key in bytes.
KeySize = x448lib.Size
)
type PublicKey struct {
// Point represents the encoded elliptic curve point of the public key.
Point []byte
}
type PrivateKey struct {
PublicKey
// Secret represents the secret of the private key.
Secret []byte
}
// NewPrivateKey creates a new empty private key including the public key.
func NewPrivateKey(key PublicKey) *PrivateKey {
return &PrivateKey{
PublicKey: key,
}
}
// Validate validates that the provided public key matches
// the private key.
func Validate(pk *PrivateKey) (err error) {
var expectedPublicKey, privateKey x448lib.Key
subtle.ConstantTimeCopy(1, privateKey[:], pk.Secret)
x448lib.KeyGen(&expectedPublicKey, &privateKey)
if subtle.ConstantTimeCompare(expectedPublicKey[:], pk.PublicKey.Point) == 0 {
return errors.KeyInvalidError("x448: invalid key")
}
return nil
}
// GenerateKey generates a new x448 key pair.
func GenerateKey(rand io.Reader) (*PrivateKey, error) {
var privateKey, publicKey x448lib.Key
privateKeyOut := new(PrivateKey)
err := generateKey(rand, &privateKey, &publicKey)
if err != nil {
return nil, err
}
privateKeyOut.PublicKey.Point = publicKey[:]
privateKeyOut.Secret = privateKey[:]
return privateKeyOut, nil
}
func generateKey(rand io.Reader, privateKey *x448lib.Key, publicKey *x448lib.Key) error {
maxRounds := 10
isZero := true
for round := 0; isZero; round++ {
if round == maxRounds {
return errors.InvalidArgumentError("x448: zero keys only, randomness source might be corrupt")
}
_, err := io.ReadFull(rand, privateKey[:])
if err != nil {
return err
}
isZero = constantTimeIsZero(privateKey[:])
}
x448lib.KeyGen(publicKey, privateKey)
return nil
}
// Encrypt encrypts a sessionKey with x448 according to
// the OpenPGP crypto refresh specification section 5.1.7. The function assumes that the
// sessionKey has the correct format and padding according to the specification.
func Encrypt(rand io.Reader, publicKey *PublicKey, sessionKey []byte) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, err error) {
var ephemeralPrivate, ephemeralPublic, staticPublic, shared x448lib.Key
// Check that the input static public key has 56 bytes.
if len(publicKey.Point) != KeySize {
err = errors.KeyInvalidError("x448: the public key has the wrong size")
return nil, nil, err
}
copy(staticPublic[:], publicKey.Point)
// Generate ephemeral keyPair.
if err = generateKey(rand, &ephemeralPrivate, &ephemeralPublic); err != nil {
return nil, nil, err
}
// Compute shared key.
ok := x448lib.Shared(&shared, &ephemeralPrivate, &staticPublic)
if !ok {
err = errors.KeyInvalidError("x448: the public key is a low order point")
return nil, nil, err
}
// Derive the encryption key from the shared secret.
encryptionKey := applyHKDF(ephemeralPublic[:], publicKey.Point[:], shared[:])
ephemeralPublicKey = &PublicKey{
Point: ephemeralPublic[:],
}
// Encrypt the sessionKey with aes key wrapping.
encryptedSessionKey, err = keywrap.Wrap(encryptionKey, sessionKey)
if err != nil {
return nil, nil, err
}
return ephemeralPublicKey, encryptedSessionKey, nil
}
// Decrypt decrypts a session key stored in ciphertext with the provided x448
// private key and ephemeral public key.
func Decrypt(privateKey *PrivateKey, ephemeralPublicKey *PublicKey, ciphertext []byte) (encodedSessionKey []byte, err error) {
var ephemeralPublic, staticPrivate, shared x448lib.Key
// Check that the input ephemeral public key has 56 bytes.
if len(ephemeralPublicKey.Point) != KeySize {
err = errors.KeyInvalidError("x448: the public key has the wrong size")
return nil, err
}
copy(ephemeralPublic[:], ephemeralPublicKey.Point)
subtle.ConstantTimeCopy(1, staticPrivate[:], privateKey.Secret)
// Compute shared key.
ok := x448lib.Shared(&shared, &staticPrivate, &ephemeralPublic)
if !ok {
err = errors.KeyInvalidError("x448: the ephemeral public key is a low order point")
return nil, err
}
// Derive the encryption key from the shared secret.
encryptionKey := applyHKDF(ephemeralPublicKey.Point[:], privateKey.PublicKey.Point[:], shared[:])
// Decrypt the session key with aes key wrapping.
encodedSessionKey, err = keywrap.Unwrap(encryptionKey, ciphertext)
if err != nil {
return nil, err
}
return encodedSessionKey, nil
}
func applyHKDF(ephemeralPublicKey []byte, publicKey []byte, sharedSecret []byte) []byte {
inputKey := make([]byte, 3*KeySize)
// ephemeral public key | recipient public key | shared secret.
subtle.ConstantTimeCopy(1, inputKey[:KeySize], ephemeralPublicKey)
subtle.ConstantTimeCopy(1, inputKey[KeySize:2*KeySize], publicKey)
subtle.ConstantTimeCopy(1, inputKey[2*KeySize:], sharedSecret)
hkdfReader := hkdf.New(sha512.New, inputKey, []byte{}, []byte(hkdfInfo))
encryptionKey := make([]byte, aes256KeySize)
_, _ = io.ReadFull(hkdfReader, encryptionKey)
return encryptionKey
}
func constantTimeIsZero(bytes []byte) bool {
isZero := byte(0)
for _, b := range bytes {
isZero |= b
}
return isZero == 0
}
// ENCODING/DECODING ciphertexts:
// EncodeFieldsLength returns the length of the ciphertext encoding
// given the encrypted session key.
func EncodedFieldsLength(encryptedSessionKey []byte, v6 bool) int {
lenCipherFunction := 0
if !v6 {
lenCipherFunction = 1
}
return KeySize + 1 + len(encryptedSessionKey) + lenCipherFunction
}
// EncodeField encodes x448 session key encryption fields as
// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey
// and writes it to writer.
func EncodeFields(writer io.Writer, ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, v6 bool) (err error) {
lenAlgorithm := 0
if !v6 {
lenAlgorithm = 1
}
if _, err = writer.Write(ephemeralPublicKey.Point); err != nil {
return err
}
if _, err = writer.Write([]byte{byte(len(encryptedSessionKey) + lenAlgorithm)}); err != nil {
return err
}
if !v6 {
if _, err = writer.Write([]byte{cipherFunction}); err != nil {
return err
}
}
if _, err = writer.Write(encryptedSessionKey); err != nil {
return err
}
return nil
}
// DecodeField decodes a x448 session key encryption as
// ephemeral x448 public key | follow byte length | cipherFunction (v3 only) | encryptedSessionKey.
func DecodeFields(reader io.Reader, v6 bool) (ephemeralPublicKey *PublicKey, encryptedSessionKey []byte, cipherFunction byte, err error) {
var buf [1]byte
ephemeralPublicKey = &PublicKey{
Point: make([]byte, KeySize),
}
// 56 octets representing an ephemeral x448 public key.
if _, err = io.ReadFull(reader, ephemeralPublicKey.Point); err != nil {
return nil, nil, 0, err
}
// A one-octet size of the following fields.
if _, err = io.ReadFull(reader, buf[:]); err != nil {
return nil, nil, 0, err
}
followingLen := buf[0]
// The one-octet algorithm identifier, if it was passed (in the case of a v3 PKESK packet).
if !v6 {
if _, err = io.ReadFull(reader, buf[:]); err != nil {
return nil, nil, 0, err
}
cipherFunction = buf[0]
followingLen -= 1
}
// The encrypted session key.
encryptedSessionKey = make([]byte, followingLen)
if _, err = io.ReadFull(reader, encryptedSessionKey); err != nil {
return nil, nil, 0, err
}
return ephemeralPublicKey, encryptedSessionKey, cipherFunction, nil
}
================================================
FILE: vendor/github.com/a8m/envsubst/LICENSE
================================================
MIT License
Copyright (c) 2017 envsubst contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: vendor/github.com/a8m/envsubst/parse/env.go
================================================
package parse
import (
"strings"
)
type Env []string
func (e Env) Get(name string) string {
v, _ := e.Lookup(name)
return v
}
func (e Env) Has(name string) bool {
_, ok := e.Lookup(name)
return ok
}
func (e Env) Lookup(name string) (string, bool) {
prefix := name + "="
for _, pair := range e {
if strings.HasPrefix(pair, prefix) {
return pair[len(prefix):], true
}
}
return "", false
}
================================================
FILE: vendor/github.com/a8m/envsubst/parse/lex.go
================================================
package parse
import (
"fmt"
"strings"
"unicode"
"unicode/utf8"
)
// itemType identifies the type of lex items.
type itemType int
// Pos represents a byte position in the original input text from which
// this template was parsed.
type Pos int
// item represents a token or text string returned from the scanner.
type item struct {
typ itemType // The type of this item.
pos Pos // The starting position, in bytes, of this item in the input string.
val string // The value of this item.
}
func (i item) String() string {
typ := "OP"
if t, ok := tokens[i.typ]; ok {
typ = t
}
return fmt.Sprintf("%s: %.40q", typ, i.val)
}
const (
eof = -1
itemError itemType = iota // error occurred; value is text of error
itemEOF
itemText // plain text
itemPlus // plus('+')
itemDash // dash('-')
itemEquals // equals
itemColonEquals // colon-equals (':=')
itemColonDash // colon-dash(':-')
itemColonPlus // colon-plus(':+')
itemVariable // variable starting with '$', such as '$hello' or '$1'
itemLeftDelim // left action delimiter '${'
itemRightDelim // right action delimiter '}'
)
var tokens = map[itemType]string{
itemEOF: "EOF",
itemError: "ERROR",
itemText: "TEXT",
itemVariable: "VAR",
itemLeftDelim: "START EXP",
itemRightDelim: "END EXP",
}
// stateFn represents the state of the lexer as a function that returns the next state.
type stateFn func(*lexer) stateFn
// lexer holds the state of the scanner
type lexer struct {
input string // the string being lexed
state stateFn // the next lexing function to enter
pos Pos // current position in the input
start Pos // start position of this item
width Pos // width of last rune read from input
lastPos Pos // position of most recent item returned by nextItem
items chan item // channel of lexed items
subsDepth int // depth of substitution
}
// next returns the next rune in the input.
func (l *lexer) next() rune {
if int(l.pos) >= len(l.input) {
l.width = 0
return eof
}
r, w := utf8.DecodeRuneInString(l.input[l.pos:])
l.width = Pos(w)
l.pos += l.width
return r
}
// peek returns but does not consume the next rune in the input.
func (l *lexer) peek() rune {
r := l.next()
l.backup()
return r
}
// backup steps back one rune. Can only be called once per call of next.
func (l *lexer) backup() {
l.pos -= l.width
}
// emit passes an item back to the client.
func (l *lexer) emit(t itemType) {
l.items <- item{t, l.start, l.input[l.start:l.pos]}
l.lastPos = l.start
l.start = l.pos
}
// ignore skips over the pending input before this point.
func (l *lexer) ignore() {
l.start = l.pos
}
// errorf returns an error token and terminates the scan by passing
// back a nil pointer that will be the next state, terminating l.nextItem.
func (l *lexer) errorf(format string, args ...interface{}) stateFn {
l.items <- item{itemError, l.start, fmt.Sprintf(format, args...)}
return nil
}
// nextItem returns the next item from the input.
// Called by the parser, not in the lexing goroutine.
func (l *lexer) nextItem() item {
item := <-l.items
return item
}
// lex creates a new scanner for the input string.
func lex(input string) *lexer {
l := &lexer{
input: input,
items: make(chan item),
}
go l.run()
return l
}
// run runs the state machine for the lexer.
func (l *lexer) run() {
for l.state = lexText; l.state != nil; {
l.state = l.state(l)
}
close(l.items)
}
// lexText scans until encountering with "$" or an opening action delimiter, "${".
func lexText(l *lexer) stateFn {
Loop:
for {
switch r := l.next(); r {
case '$':
l.pos--
// emit the text we've found until here, if any.
if l.pos > l.start {
l.emit(itemText)
}
l.pos++
switch r := l.peek(); {
case r == '$':
// ignore the previous '$'.
l.ignore()
l.next()
l.emit(itemText)
case r == '{':
l.next()
l.subsDepth++
l.emit(itemLeftDelim)
return lexSubstitution
case isAlphaNumeric(r):
return lexVariable
}
case eof:
break Loop
}
}
// Correctly reached EOF.
if l.pos > l.start {
l.emit(itemText)
}
l.emit(itemEOF)
return nil
}
// lexVariable scans a Variable: $Alphanumeric.
// The $ has been scanned.
func lexVariable(l *lexer) stateFn {
var r rune
for {
r = l.next()
if !isAlphaNumeric(r) {
l.backup()
break
}
}
if v := l.input[l.start:l.pos]; v == "_" || v == "$_" {
return lexText
}
l.emit(itemVariable)
if l.subsDepth > 0 {
return lexSubstitution
}
return lexText
}
// lexSubstitution scans the elements inside substitution delimiters.
func lexSubstitution(l *lexer) stateFn {
switch r := l.next(); {
case r == '}':
l.subsDepth--
l.emit(itemRightDelim)
return lexText
case r == eof || isEndOfLine(r):
return l.errorf("closing brace expected")
case isAlphaNumeric(r) && strings.HasPrefix(l.input[l.lastPos:], "${"):
fallthrough
case r == '$':
return lexVariable
case r == '+':
l.emit(itemPlus)
case r == '-':
l.emit(itemDash)
case r == '=':
l.emit(itemEquals)
case r == ':':
switch l.next() {
case '-':
l.emit(itemColonDash)
case '=':
l.emit(itemColonEquals)
case '+':
l.emit(itemColonPlus)
default:
l.emit(itemText)
}
default:
l.emit(itemText)
}
return lexSubstitution
}
// isEndOfLine reports whether r is an end-of-line character.
func isEndOfLine(r rune) bool {
return r == '\r' || r == '\n'
}
// isAlphaNumeric reports whether r is an alphabetic, digit, or underscore.
func isAlphaNumeric(r rune) bool {
return r == '_' || unicode.IsLetter(r) || unicode.IsDigit(r)
}
================================================
FILE: vendor/github.com/a8m/envsubst/parse/node.go
================================================
package parse
import (
"fmt"
)
type Node interface {
Type() NodeType
String() (string, error)
}
// NodeType identifies the type of a node.
type NodeType int
// Type returns itself and provides an easy default implementation
// for embedding in a Node. Embedded in all non-trivial Nodes.
func (t NodeType) Type() NodeType {
return t
}
const (
NodeText NodeType = iota
NodeSubstitution
NodeVariable
)
type TextNode struct {
NodeType
Text string
}
func NewText(text string) *TextNode {
return &TextNode{NodeText, text}
}
func (t *TextNode) String() (string, error) {
return t.Text, nil
}
type VariableNode struct {
NodeType
Ident string
Env Env
Restrict *Restrictions
}
func NewVariable(ident string, env Env, restrict *Restrictions) *VariableNode {
return &VariableNode{NodeVariable, ident, env, restrict}
}
func (t *VariableNode) String() (string, error) {
if err := t.validateNoUnset(); err != nil {
return "", err
}
value := t.Env.Get(t.Ident)
if err := t.validateNoEmpty(value); err != nil {
return "", err
}
return value, nil
}
func (t *VariableNode) isSet() bool {
return t.Env.Has(t.Ident)
}
func (t *VariableNode) validateNoUnset() error {
if t.Restrict.NoUnset && !t.isSet() {
return fmt.Errorf("variable ${%s} not set", t.Ident)
}
return nil
}
func (t *VariableNode) validateNoEmpty(value string) error {
if t.Restrict.NoEmpty && value == "" && t.isSet() {
return fmt.Errorf("variable ${%s} set but empty", t.Ident)
}
return nil
}
type SubstitutionNode struct {
NodeType
ExpType itemType
Variable *VariableNode
Default Node // Default could be variable or text
}
func (t *SubstitutionNode) String() (string, error) {
if t.ExpType >= itemPlus && t.Default != nil {
switch t.ExpType {
case itemColonDash, itemColonEquals:
if s, _ := t.Variable.String(); s != "" {
return s, nil
}
return t.Default.String()
case itemPlus, itemColonPlus:
if t.Variable.isSet() {
return t.Default.String()
}
return "", nil
default:
if !t.Variable.isSet() {
return t.Default.String()
}
}
}
return t.Variable.String()
}
================================================
FILE: vendor/github.com/a8m/envsubst/parse/parse.go
================================================
// Most of the code in this package taken from golang/text/template/parse
package parse
import (
"errors"
"strings"
)
// A mode value is a set of flags (or 0). They control parser behavior.
type Mode int
// Mode for parser behaviour
const (
Quick Mode = iota // stop parsing after first error encoutered and return
AllErrors // report all errors
)
// The restrictions option controls the parsring restriction.
type Restrictions struct {
NoUnset bool
NoEmpty bool
}
// Restrictions specifier
var (
Relaxed = &Restrictions{false, false}
NoEmpty = &Restrictions{false, true}
NoUnset = &Restrictions{true, false}
Strict = &Restrictions{true, true}
)
// Parser type initializer
type Parser struct {
Name string // name of the processing template
Env Env
Restrict *Restrictions
Mode Mode
// parsing state;
lex *lexer
token [3]item // three-token lookahead
peekCount int
nodes []Node
}
// New allocates a new Parser with the given name.
func New(name string, env []string, r *Restrictions) *Parser {
return &Parser{
Name: name,
Env: Env(env),
Restrict: r,
}
}
// Parse parses the given string.
func (p *Parser) Parse(text string) (string, error) {
p.lex = lex(text)
// Build internal array of all unset or empty vars here
var errs []error
// clean parse state
p.nodes = make([]Node, 0)
p.peekCount = 0
if err := p.parse(); err != nil {
switch p.Mode {
case Quick:
return "", err
case AllErrors:
errs = append(errs, err)
}
}
var out string
for _, node := range p.nodes {
s, err := node.String()
if err != nil {
switch p.Mode {
case Quick:
return "", err
case AllErrors:
errs = append(errs, err)
}
}
out += s
}
if len(errs) > 0 {
var b strings.Builder
for i, err := range errs {
if i > 0 {
b.WriteByte('\n')
}
b.WriteString(err.Error())
}
return "", errors.New(b.String())
}
return out, nil
}
// parse is the top-level parser for the template.
// It runs to EOF and return an error if something isn't right.
func (p *Parser) parse() error {
Loop:
for {
switch t := p.next(); t.typ {
case itemEOF:
break Loop
case itemError:
return p.errorf(t.val)
case itemVariable:
varNode := NewVariable(strings.TrimPrefix(t.val, "$"), p.Env, p.Restrict)
p.nodes = append(p.nodes, varNode)
case itemLeftDelim:
if p.peek().typ == itemVariable {
n, err := p.action()
if err != nil {
return err
}
p.nodes = append(p.nodes, n)
continue
}
fallthrough
default:
textNode := NewText(t.val)
p.nodes = append(p.nodes, textNode)
}
}
return nil
}
// Parse substitution. first item is a variable.
func (p *Parser) action() (Node, error) {
var expType itemType
var defaultNode Node
varNode := NewVariable(p.next().val, p.Env, p.Restrict)
Loop:
for {
switch t := p.next(); t.typ {
case itemRightDelim:
break Loop
case itemError:
return nil, p.errorf(t.val)
case itemVariable:
defaultNode = NewVariable(strings.TrimPrefix(t.val, "$"), p.Env, p.Restrict)
case itemText:
n := NewText(t.val)
Text:
for {
switch p.peek().typ {
case itemRightDelim, itemError, itemEOF:
break Text
default:
// patch to accept all kind of chars
n.Text += p.next().val
}
}
defaultNode = n
default:
expType = t.typ
}
}
return &SubstitutionNode{NodeSubstitution, expType, varNode, defaultNode}, nil
}
func (p *Parser) errorf(s string) error {
return errors.New(s)
}
// next returns the next token.
func (p *Parser) next() item {
if p.peekCount > 0 {
p.peekCount--
} else {
p.token[0] = p.lex.nextItem()
}
return p.token[p.peekCount]
}
// backup backs the input stream up one token.
func (p *Parser) backup() {
p.peekCount++
}
// peek returns but does not consume the next token.
func (p *Parser) peek() item {
if p.peekCount > 0 {
return p.token[p.peekCount-1]
}
p.peekCount = 1
p.token[0] = p.lex.nextItem()
return p.token[0]
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/COPYING
================================================
Copyright (C) 2017 Alec Thomas
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/api.go
================================================
package lexer
import (
"fmt"
"io"
"strings"
"unicode/utf8"
)
type TokenType int
const (
// EOF represents an end of file.
EOF TokenType = -(iota + 1)
)
// EOFToken creates a new EOF token at the given position.
func EOFToken(pos Position) Token {
return Token{Type: EOF, Pos: pos}
}
// Definition is the main entry point for lexing.
type Definition interface {
// Symbols returns a map of symbolic names to the corresponding pseudo-runes for those symbols.
// This is the same approach as used by text/scanner. For example, "EOF" might have the rune
// value of -1, "Ident" might be -2, and so on.
Symbols() map[string]TokenType
// Lex an io.Reader.
Lex(filename string, r io.Reader) (Lexer, error)
}
// StringDefinition is an optional interface lexer Definition's can implement
// to offer a fast path for lexing strings.
type StringDefinition interface {
LexString(filename string, input string) (Lexer, error)
}
// BytesDefinition is an optional interface lexer Definition's can implement
// to offer a fast path for lexing byte slices.
type BytesDefinition interface {
LexBytes(filename string, input []byte) (Lexer, error)
}
// A Lexer returns tokens from a source.
type Lexer interface {
// Next consumes and returns the next token.
Next() (Token, error)
}
// SymbolsByRune returns a map of lexer symbol names keyed by rune.
func SymbolsByRune(def Definition) map[TokenType]string {
symbols := def.Symbols()
out := make(map[TokenType]string, len(symbols))
for s, r := range symbols {
out[r] = s
}
return out
}
// NameOfReader attempts to retrieve the filename of a reader.
func NameOfReader(r interface{}) string {
if nr, ok := r.(interface{ Name() string }); ok {
return nr.Name()
}
return ""
}
// Must takes the result of a Definition constructor call and returns the definition, but panics if
// it errors
//
// eg.
//
// lex = lexer.Must(lexer.Build(`Symbol = "symbol" .`))
func Must(def Definition, err error) Definition {
if err != nil {
panic(err)
}
return def
}
// ConsumeAll reads all tokens from a Lexer.
func ConsumeAll(lexer Lexer) ([]Token, error) {
tokens := make([]Token, 0, 1024)
for {
token, err := lexer.Next()
if err != nil {
return nil, err
}
tokens = append(tokens, token)
if token.Type == EOF {
return tokens, nil
}
}
}
// Position of a token.
type Position struct {
Filename string
Offset int
Line int
Column int
}
// Advance the Position based on the number of characters and newlines in "span".
func (p *Position) Advance(span string) {
p.Offset += len(span)
lines := strings.Count(span, "\n")
p.Line += lines
// Update column.
if lines == 0 {
p.Column += utf8.RuneCountInString(span)
} else {
p.Column = utf8.RuneCountInString(span[strings.LastIndex(span, "\n"):])
}
}
func (p Position) GoString() string {
return fmt.Sprintf("Position{Filename: %q, Offset: %d, Line: %d, Column: %d}",
p.Filename, p.Offset, p.Line, p.Column)
}
func (p Position) String() string {
filename := p.Filename
if filename == "" {
return fmt.Sprintf("%d:%d", p.Line, p.Column)
}
return fmt.Sprintf("%s:%d:%d", filename, p.Line, p.Column)
}
// A Token returned by a Lexer.
type Token struct {
// Type of token. This is the value keyed by symbol as returned by Definition.Symbols().
Type TokenType
Value string
Pos Position
}
// EOF returns true if this Token is an EOF token.
func (t Token) EOF() bool {
return t.Type == EOF
}
func (t Token) String() string {
if t.EOF() {
return ""
}
return t.Value
}
func (t Token) GoString() string {
if t.Pos == (Position{}) {
return fmt.Sprintf("Token{%d, %q}", t.Type, t.Value)
}
return fmt.Sprintf("Token@%s{%d, %q}", t.Pos.String(), t.Type, t.Value)
}
// MakeSymbolTable builds a lookup table for checking token ID existence.
//
// For each symbolic name in "types", the returned map will contain the corresponding token ID as a key.
func MakeSymbolTable(def Definition, types ...string) (map[TokenType]bool, error) {
symbols := def.Symbols()
table := make(map[TokenType]bool, len(types))
for _, symbol := range types {
rn, ok := symbols[symbol]
if !ok {
return nil, fmt.Errorf("lexer does not support symbol %q", symbol)
}
table[rn] = true
}
return table, nil
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/codegen.go
================================================
package lexer
import (
"fmt"
"io"
"regexp"
"regexp/syntax"
"sort"
"text/template"
"unicode/utf8"
)
var codegenBackrefRe = regexp.MustCompile(`(\\+)(\d)`)
var codegenTemplate *template.Template = template.Must(template.New("lexgen").Funcs(template.FuncMap{
"IsPush": func(r Rule) string {
if p, ok := r.Action.(ActionPush); ok {
return p.State
}
return ""
},
"IsPop": func(r Rule) bool {
_, ok := r.Action.(ActionPop)
return ok
},
"IsReturn": func(r Rule) bool {
return r == ReturnRule
},
"OrderRules": orderRules,
"HaveBackrefs": func(def *StatefulDefinition, state string) bool {
for _, rule := range def.Rules()[state] {
if codegenBackrefRe.MatchString(rule.Pattern) {
return true
}
}
return false
},
}).Parse(`
// Code generated by Participle. DO NOT EDIT.
package {{.Package}}
import (
"io"
"strings"
"unicode/utf8"
"regexp/syntax"
"github.com/alecthomas/participle/v2"
"github.com/alecthomas/participle/v2/lexer"
)
var _ syntax.Op
var Lexer lexer.Definition = definitionImpl{}
type definitionImpl struct {}
func (definitionImpl) Symbols() map[string]lexer.TokenType {
return map[string]lexer.TokenType{
{{- range $sym, $rn := .Def.Symbols}}
"{{$sym}}": {{$rn}},
{{- end}}
}
}
func (definitionImpl) LexString(filename string, s string) (lexer.Lexer, error) {
return &lexerImpl{
s: s,
pos: lexer.Position{
Filename: filename,
Line: 1,
Column: 1,
},
states: []lexerState{lexerState{name: "Root"}},
}, nil
}
func (d definitionImpl) LexBytes(filename string, b []byte) (lexer.Lexer, error) {
return d.LexString(filename, string(b))
}
func (d definitionImpl) Lex(filename string, r io.Reader) (lexer.Lexer, error) {
s := &strings.Builder{}
_, err := io.Copy(s, r)
if err != nil {
return nil, err
}
return d.LexString(filename, s.String())
}
type lexerState struct {
name string
groups []string
}
type lexerImpl struct {
s string
p int
pos lexer.Position
states []lexerState
}
func (l *lexerImpl) Next() (lexer.Token, error) {
if l.p == len(l.s) {
return lexer.EOFToken(l.pos), nil
}
var (
state = l.states[len(l.states)-1]
groups []int
sym lexer.TokenType
)
switch state.name {
{{- range $state := .Def.Rules|OrderRules}}
case "{{$state.Name}}":
{{- range $i, $rule := $state.Rules}}
{{- if $i}} else {{end -}}
{{- if .Pattern -}}
if match := match{{.Name}}(l.s, l.p); match[1] != 0 {
sym = {{index $.Def.Symbols .Name}}
groups = match[:]
{{- else if .|IsReturn -}}
if true {
{{- end}}
{{- if .|IsPush}}
l.states = append(l.states, lexerState{name: "{{.|IsPush}}"{{if HaveBackrefs $.Def $state.Name}}, groups: l.sgroups(groups){{end}}})
{{- else if (or (.|IsPop) (.|IsReturn))}}
l.states = l.states[:len(l.states)-1]
{{- if .|IsReturn}}
return l.Next()
{{- end}}
{{- else if not .Action}}
{{- else}}
Unsupported action {{.Action}}
{{- end}}
}
{{- end}}
{{- end}}
}
if groups == nil {
sample := []rune(l.s[l.p:])
if len(sample) > 16 {
sample = append(sample[:16], []rune("...")...)
}
return lexer.Token{}, participle.Errorf(l.pos, "invalid input text %q", sample)
}
pos := l.pos
span := l.s[groups[0]:groups[1]]
l.p = groups[1]
l.pos.Advance(span)
return lexer.Token{
Type: sym,
Value: span,
Pos: pos,
}, nil
}
func (l *lexerImpl) sgroups(match []int) []string {
sgroups := make([]string, len(match)/2)
for i := 0; i < len(match)-1; i += 2 {
sgroups[i/2] = l.s[l.p+match[i]:l.p+match[i+1]]
}
return sgroups
}
`))
// ExperimentalGenerateLexer generates Go code implementing the given stateful lexer.
//
// The generated code should in general by around 10x faster and produce zero garbage per token.
//
// NOTE: This is an experimental interface and subject to change.
func ExperimentalGenerateLexer(w io.Writer, pkg string, def *StatefulDefinition) error {
type ctx struct {
Package string
Def *StatefulDefinition
}
rules := def.Rules()
err := codegenTemplate.Execute(w, ctx{pkg, def})
if err != nil {
return err
}
seen := map[string]bool{} // Rules can be duplicated by Include().
for _, rules := range orderRules(rules) {
for _, rule := range rules.Rules {
if rule.Name == "" {
panic(rule)
}
if seen[rule.Name] {
continue
}
seen[rule.Name] = true
fmt.Fprintf(w, "\n")
err := generateRegexMatch(w, rule.Name, rule.Pattern)
if err != nil {
return err
}
}
}
return nil
}
type orderedRule struct {
Name string
Rules []Rule
}
func orderRules(rules Rules) []orderedRule {
orderedRules := []orderedRule{}
for name, rules := range rules {
orderedRules = append(orderedRules, orderedRule{
Name: name,
Rules: rules,
})
}
sort.Slice(orderedRules, func(i, j int) bool {
return orderedRules[i].Name < orderedRules[j].Name
})
return orderedRules
}
func generateRegexMatch(w io.Writer, name, pattern string) error {
re, err := syntax.Parse(pattern, syntax.Perl)
if err != nil {
return err
}
ids := map[string]int{}
idn := 0
reid := func(re *syntax.Regexp) int {
key := re.Op.String() + ":" + re.String()
id, ok := ids[key]
if ok {
return id
}
id = idn
idn++
ids[key] = id
return id
}
exists := func(re *syntax.Regexp) bool {
key := re.Op.String() + ":" + re.String()
_, ok := ids[key]
return ok
}
re = re.Simplify()
fmt.Fprintf(w, "// %s\n", re)
fmt.Fprintf(w, "func match%s(s string, p int) (groups [%d]int) {\n", name, 2*re.MaxCap()+2)
flattened := flatten(re)
// Fast-path a single literal.
if len(flattened) == 1 && re.Op == syntax.OpLiteral {
n := utf8.RuneCountInString(string(re.Rune))
if n == 1 {
fmt.Fprintf(w, "if p < len(s) && s[p] == %q {\n", re.Rune[0])
} else {
fmt.Fprintf(w, "if p+%d < len(s) && s[p:p+%d] == %q {\n", n, n, string(re.Rune))
}
fmt.Fprintf(w, "groups[0] = p\n")
fmt.Fprintf(w, "groups[1] = p + %d\n", n)
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "return\n")
fmt.Fprintf(w, "}\n")
return nil
}
for _, re := range flattened {
if exists(re) {
continue
}
fmt.Fprintf(w, "// %s (%s)\n", re, re.Op)
fmt.Fprintf(w, "l%d := func(s string, p int) int {\n", reid(re))
if re.Flags&syntax.NonGreedy != 0 {
panic("non-greedy match not supported: " + re.String())
}
switch re.Op {
case syntax.OpNoMatch: // matches no strings
fmt.Fprintf(w, "return p\n")
case syntax.OpEmptyMatch: // matches empty string
fmt.Fprintf(w, "if len(s) == 0 { return p }\n")
fmt.Fprintf(w, "return -1\n")
case syntax.OpLiteral: // matches Runes sequence
n := utf8.RuneCountInString(string(re.Rune))
if n == 1 {
fmt.Fprintf(w, "if p < len(s) && s[p] == %q { return p+1 }\n", re.Rune[0])
} else {
fmt.Fprintf(w, "if p+%d < len(s) && s[p:p+%d] == %q { return p+%d }\n", n, n, string(re.Rune), n)
}
fmt.Fprintf(w, "return -1\n")
case syntax.OpCharClass: // matches Runes interpreted as range pair list
fmt.Fprintf(w, "if len(s) <= p { return -1 }\n")
needDecode := false
for i := 0; i < len(re.Rune); i += 2 {
l, r := re.Rune[i], re.Rune[i+1]
ln, rn := utf8.RuneLen(l), utf8.RuneLen(r)
if ln != 1 || rn != 1 {
needDecode = true
break
}
}
if needDecode {
fmt.Fprintf(w, "var (rn rune; n int)\n")
decodeRune(w, "p", "rn", "n")
} else {
fmt.Fprintf(w, "rn := s[p]\n")
}
fmt.Fprintf(w, "switch {\n")
for i := 0; i < len(re.Rune); i += 2 {
l, r := re.Rune[i], re.Rune[i+1]
ln, rn := utf8.RuneLen(l), utf8.RuneLen(r)
if ln == 1 && rn == 1 {
if l == r {
fmt.Fprintf(w, "case rn == %q: return p+1\n", l)
} else {
fmt.Fprintf(w, "case rn >= %q && rn <= %q: return p+1\n", l, r)
}
} else {
if l == r {
fmt.Fprintf(w, "case rn == %q: return p+n\n", l)
} else {
fmt.Fprintf(w, "case rn >= %q && rn <= %q: return p+n\n", l, r)
}
}
}
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "return -1\n")
case syntax.OpAnyCharNotNL: // matches any character except newline
fmt.Fprintf(w, "var (rn rune; n int)\n")
decodeRune(w, "p", "rn", "n")
fmt.Fprintf(w, "if len(s) <= p+n || rn == '\\n' { return -1 }\n")
fmt.Fprintf(w, "return p+n\n")
case syntax.OpAnyChar: // matches any character
fmt.Fprintf(w, "var n int\n")
fmt.Fprintf(w, "if s[p] < utf8.RuneSelf {\n")
fmt.Fprintf(w, " n = 1\n")
fmt.Fprintf(w, "} else {\n")
fmt.Fprintf(w, " _, n = utf8.DecodeRuneInString(s[p:])\n")
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "if len(s) <= p+n { return -1 }\n")
fmt.Fprintf(w, "return p+n\n")
case syntax.OpWordBoundary, syntax.OpNoWordBoundary,
syntax.OpBeginText, syntax.OpEndText,
syntax.OpBeginLine, syntax.OpEndLine:
fmt.Fprintf(w, "var l, u rune = -1, -1\n")
fmt.Fprintf(w, "if p == 0 {\n")
decodeRune(w, "0", "u", "_")
fmt.Fprintf(w, "} else if p == len(s) {\n")
fmt.Fprintf(w, " l, _ = utf8.DecodeLastRuneInString(s)\n")
fmt.Fprintf(w, "} else {\n")
fmt.Fprintf(w, " var ln int\n")
decodeRune(w, "p", "l", "ln")
fmt.Fprintf(w, " if p+ln <= len(s) {\n")
decodeRune(w, "p+ln", "u", "_")
fmt.Fprintf(w, " }\n")
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "op := syntax.EmptyOpContext(l, u)\n")
lut := map[syntax.Op]string{
syntax.OpWordBoundary: "EmptyWordBoundary",
syntax.OpNoWordBoundary: "EmptyNoWordBoundary",
syntax.OpBeginText: "EmptyBeginText",
syntax.OpEndText: "EmptyEndText",
syntax.OpBeginLine: "EmptyBeginLine",
syntax.OpEndLine: "EmptyEndLine",
}
fmt.Fprintf(w, "if op & syntax.%s != 0 { return p }\n", lut[re.Op])
fmt.Fprintf(w, "return -1\n")
case syntax.OpCapture: // capturing subexpression with index Cap, optional name Name
fmt.Fprintf(w, "np := l%d(s, p)\n", reid(re.Sub0[0]))
fmt.Fprintf(w, "if np != -1 {\n")
fmt.Fprintf(w, " groups[%d] = p\n", re.Cap*2)
fmt.Fprintf(w, " groups[%d] = np\n", re.Cap*2+1)
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "return np")
case syntax.OpStar: // matches Sub[0] zero or more times
fmt.Fprintf(w, "for len(s) > p {\n")
fmt.Fprintf(w, "if np := l%d(s, p); np == -1 { return p } else { p = np }\n", reid(re.Sub0[0]))
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "return p\n")
case syntax.OpPlus: // matches Sub[0] one or more times
fmt.Fprintf(w, "if p = l%d(s, p); p == -1 { return -1 }\n", reid(re.Sub0[0]))
fmt.Fprintf(w, "for len(s) > p {\n")
fmt.Fprintf(w, "if np := l%d(s, p); np == -1 { return p } else { p = np }\n", reid(re.Sub0[0]))
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "return p\n")
case syntax.OpQuest: // matches Sub[0] zero or one times
fmt.Fprintf(w, "if np := l%d(s, p); np != -1 { return np }\n", reid(re.Sub0[0]))
fmt.Fprintf(w, "return p\n")
case syntax.OpRepeat: // matches Sub[0] at least Min times, at most Max (Max == -1 is no limit)
panic("??")
case syntax.OpConcat: // matches concatenation of Subs
for _, sub := range re.Sub {
fmt.Fprintf(w, "if p = l%d(s, p); p == -1 { return -1 }\n", reid(sub))
}
fmt.Fprintf(w, "return p\n")
case syntax.OpAlternate: // matches alternation of Subs
for _, sub := range re.Sub {
fmt.Fprintf(w, "if np := l%d(s, p); np != -1 { return np }\n", reid(sub))
}
fmt.Fprintf(w, "return -1\n")
}
fmt.Fprintf(w, "}\n")
}
fmt.Fprintf(w, "np := l%d(s, p)\n", reid(re))
fmt.Fprintf(w, "if np == -1 {\n")
fmt.Fprintf(w, " return\n")
fmt.Fprintf(w, "}\n")
fmt.Fprintf(w, "groups[0] = p\n")
fmt.Fprintf(w, "groups[1] = np\n")
fmt.Fprintf(w, "return\n")
fmt.Fprintf(w, "}\n")
return nil
}
// This exists because of https://github.com/golang/go/issues/31666
func decodeRune(w io.Writer, offset string, rn string, n string) {
fmt.Fprintf(w, "if s[%s] < utf8.RuneSelf {\n", offset)
fmt.Fprintf(w, " %s, %s = rune(s[%s]), 1\n", rn, n, offset)
fmt.Fprintf(w, "} else {\n")
fmt.Fprintf(w, " %s, %s = utf8.DecodeRuneInString(s[%s:])\n", rn, n, offset)
fmt.Fprintf(w, "}\n")
}
func flatten(re *syntax.Regexp) (out []*syntax.Regexp) {
for _, sub := range re.Sub {
out = append(out, flatten(sub)...)
}
out = append(out, re)
return
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/doc.go
================================================
// Package lexer defines interfaces and implementations used by Participle to perform lexing.
//
// The primary interfaces are Definition and Lexer. There are two concrete implementations
// included. The first is one based on Go's text/scanner package. The second is Participle's
// default stateful/modal lexer.
//
// The stateful lexer is based heavily on the approach used by Chroma (and Pygments).
//
// It is a state machine defined by a map of rules keyed by state. Each rule
// is a named regex and optional operation to apply when the rule matches.
//
// As a convenience, any Rule starting with a lowercase letter will be elided from output.
//
// Lexing starts in the "Root" group. Each rule is matched in order, with the first
// successful match producing a lexeme. If the matching rule has an associated Action
// it will be executed.
//
// A state change can be introduced with the Action `Push(state)`. `Pop()` will
// return to the previous state.
//
// To reuse rules from another state, use `Include(state)`.
//
// As a special case, regexes containing backrefs in the form \N (where N is a digit)
// will match the corresponding capture group from the immediate parent group. This
// can be used to parse, among other things, heredocs.
//
// See the README, example and tests in this package for details.
package lexer
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/errors.go
================================================
package lexer
import "fmt"
// This file exists to break circular imports. The types and functions in here
// mirror those in the participle package.
type errorInterface interface {
error
Message() string
Position() Position
}
// Error represents an error while lexing.
//
// It complies with the participle.Error interface.
type Error struct {
Msg string
Pos Position
}
var _ errorInterface = &Error{}
// Creates a new Error at the given position.
func errorf(pos Position, format string, args ...interface{}) *Error {
return &Error{Msg: fmt.Sprintf(format, args...), Pos: pos}
}
func (e *Error) Message() string { return e.Msg } // nolint: golint
func (e *Error) Position() Position { return e.Pos } // nolint: golint
// Error formats the error with FormatError.
func (e *Error) Error() string { return formatError(e.Pos, e.Msg) }
// An error in the form "[:][::] "
func formatError(pos Position, message string) string {
msg := ""
if pos.Filename != "" {
msg += pos.Filename + ":"
}
if pos.Line != 0 || pos.Column != 0 {
msg += fmt.Sprintf("%d:%d:", pos.Line, pos.Column)
}
if msg != "" {
msg += " " + message
} else {
msg = message
}
return msg
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/peek.go
================================================
package lexer
// PeekingLexer supports arbitrary lookahead as well as cloning.
type PeekingLexer struct {
rawCursor RawCursor
cursor int
eof Token
tokens []Token
elide map[TokenType]bool
}
// RawCursor index in the token stream.
type RawCursor int
// Upgrade a Lexer to a PeekingLexer with arbitrary lookahead.
//
// "elide" is a slice of token types to elide from processing.
func Upgrade(lex Lexer, elide ...TokenType) (*PeekingLexer, error) {
r := &PeekingLexer{
elide: make(map[TokenType]bool, len(elide)),
}
for _, rn := range elide {
r.elide[rn] = true
}
for {
t, err := lex.Next()
if err != nil {
return r, err
}
if t.EOF() {
r.eof = t
break
}
r.tokens = append(r.tokens, t)
}
return r, nil
}
// Range returns the slice of tokens between the two cursor points.
func (p *PeekingLexer) Range(rawStart, rawEnd RawCursor) []Token {
return p.tokens[rawStart:rawEnd]
}
// Cursor position in tokens, excluding elided tokens.
func (p *PeekingLexer) Cursor() int {
return p.cursor
}
// RawCursor position in tokens, including elided tokens.
func (p *PeekingLexer) RawCursor() RawCursor {
return p.rawCursor
}
// Next consumes and returns the next token.
func (p *PeekingLexer) Next() Token {
for int(p.rawCursor) < len(p.tokens) {
t := p.tokens[p.rawCursor]
p.rawCursor++
if p.elide[t.Type] {
continue
}
p.cursor++
return t
}
return p.eof
}
// Peek ahead at the next token.
func (p *PeekingLexer) Peek() Token {
for i := int(p.rawCursor); i < len(p.tokens); i++ {
t := p.tokens[i]
if p.elide[t.Type] {
continue
}
return t
}
return p.eof
}
// PeekAny peeks forward over elided and non-elided tokens.
//
// Elided tokens will be returned if they match, otherwise the next
// non-elided token will be returned.
//
// The returned RawCursor position is the location of the returned token.
// Use FastForward to move the internal cursors forward.
func (p *PeekingLexer) PeekAny(match func(Token) bool) (t Token, rawCursor RawCursor) {
tokenCount := RawCursor(len(p.tokens))
for i := p.rawCursor; i < tokenCount; i++ {
t = p.tokens[i]
if match(t) || !p.elide[t.Type] {
return t, i
}
}
return p.eof, tokenCount
}
// FastForward the internal cursors to this RawCursor position.
func (p *PeekingLexer) FastForward(rawCursor RawCursor) {
tokenCount := RawCursor(len(p.tokens))
for ; p.rawCursor <= rawCursor && p.rawCursor < tokenCount; p.rawCursor++ {
t := p.tokens[p.rawCursor]
if p.elide[t.Type] {
continue
}
p.cursor++
}
}
// RawPeek peeks ahead at the next raw token.
//
// Unlike Peek, this will include elided tokens.
func (p *PeekingLexer) RawPeek() Token {
if int(p.rawCursor) < len(p.tokens) {
return p.tokens[p.rawCursor]
}
return p.eof
}
// Clone creates a clone of this PeekingLexer at its current token.
//
// The parent and clone are completely independent.
func (p *PeekingLexer) Clone() *PeekingLexer {
clone := *p
return &clone
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/simple.go
================================================
package lexer
// SimpleRule is a named regular expression.
type SimpleRule struct {
Name string
Pattern string
}
// MustSimple creates a new Stateful lexer with only a single root state.
//
// It panics if there is an error.
func MustSimple(rules []SimpleRule, options ...Option) *StatefulDefinition {
def, err := NewSimple(rules, options...)
if err != nil {
panic(err)
}
return def
}
// NewSimple creates a new Stateful lexer with only a single root state.
func NewSimple(rules []SimpleRule, options ...Option) (*StatefulDefinition, error) {
fullRules := make([]Rule, len(rules))
for i, rule := range rules {
fullRules[i] = Rule{Name: rule.Name, Pattern: rule.Pattern}
}
return New(Rules{"Root": fullRules}, options...)
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/stateful.go
================================================
package lexer
import (
"errors"
"fmt"
"io"
"regexp"
"sort"
"strconv"
"strings"
"sync"
"unicode"
)
var (
backrefReplace = regexp.MustCompile(`(\\+)(\d)`)
)
// Option for modifying how the Lexer works.
type Option func(d *StatefulDefinition)
// A Rule matching input and possibly changing state.
type Rule struct {
Name string
Pattern string
Action Action
}
// Rules grouped by name.
type Rules map[string][]Rule
// compiledRule is a Rule with its pattern compiled.
type compiledRule struct {
Rule
ignore bool
RE *regexp.Regexp
}
// compiledRules grouped by name.
type compiledRules map[string][]compiledRule
// A Action is applied when a rule matches.
type Action interface {
// Actions are responsible for validating the match. ie. if they consumed any input.
applyAction(lexer *StatefulLexer, groups []string) error
}
// RulesAction is an optional interface that Actions can implement.
//
// It is applied during rule construction to mutate the rule map.
type RulesAction interface {
applyRules(state string, rule int, rules compiledRules) error
}
// InitialState overrides the default initial state of "Root".
func InitialState(state string) Option {
return func(d *StatefulDefinition) {
d.initialState = state
}
}
// MatchLongest causes the Lexer to continue checking rules past the first match.
// If any subsequent rule has a longer match, it will be used instead.
func MatchLongest() Option {
return func(d *StatefulDefinition) {
d.matchLongest = true
}
}
// ActionPop pops to the previous state when the Rule matches.
type ActionPop struct{}
func (p ActionPop) applyAction(lexer *StatefulLexer, groups []string) error {
if groups[0] == "" {
return errors.New("did not consume any input")
}
lexer.stack = lexer.stack[:len(lexer.stack)-1]
return nil
}
// Pop to the previous state.
func Pop() Action {
return ActionPop{}
}
// ReturnRule signals the lexer to return immediately.
var ReturnRule = Rule{"returnToParent", "", nil}
// Return to the parent state.
//
// Useful as the last rule in a sub-state.
func Return() Rule { return ReturnRule }
// ActionPush pushes the current state and switches to "State" when the Rule matches.
type ActionPush struct{ State string }
func (p ActionPush) applyAction(lexer *StatefulLexer, groups []string) error {
if groups[0] == "" {
return errors.New("did not consume any input")
}
lexer.stack = append(lexer.stack, lexerState{name: p.State, groups: groups})
return nil
}
// Push to the given state.
//
// The target state will then be the set of rules used for matching
// until another Push or Pop is encountered.
func Push(state string) Action {
return ActionPush{state}
}
type include struct{ state string }
func (i include) applyAction(lexer *StatefulLexer, groups []string) error {
panic("should not be called")
}
func (i include) applyRules(state string, rule int, rules compiledRules) error {
includedRules, ok := rules[i.state]
if !ok {
return fmt.Errorf("invalid include state %q", i.state)
}
clone := make([]compiledRule, len(includedRules))
copy(clone, includedRules)
rules[state] = append(rules[state][:rule], append(clone, rules[state][rule+1:]...)...) // nolint: makezero
return nil
}
// Include rules from another state in this one.
func Include(state string) Rule {
return Rule{Action: include{state}}
}
// StatefulDefinition is the lexer.Definition.
type StatefulDefinition struct {
rules compiledRules
symbols map[string]TokenType
// Map of key->*regexp.Regexp
backrefCache sync.Map
initialState string
matchLongest bool
}
// MustStateful creates a new stateful lexer and panics if it is incorrect.
func MustStateful(rules Rules, options ...Option) *StatefulDefinition {
def, err := New(rules, options...)
if err != nil {
panic(err)
}
return def
}
// New constructs a new stateful lexer from rules.
func New(rules Rules, options ...Option) (*StatefulDefinition, error) {
compiled := compiledRules{}
for key, set := range rules {
for i, rule := range set {
pattern := "^(?:" + rule.Pattern + ")"
var (
re *regexp.Regexp
err error
)
var match = backrefReplace.FindStringSubmatch(rule.Pattern)
if match == nil || len(match[1])%2 == 0 {
re, err = regexp.Compile(pattern)
if err != nil {
return nil, fmt.Errorf("%s.%d: %s", key, i, err)
}
}
compiled[key] = append(compiled[key], compiledRule{
Rule: rule,
ignore: len(rule.Name) > 0 && unicode.IsLower(rune(rule.Name[0])),
RE: re,
})
}
}
restart:
for state, rules := range compiled {
for i, rule := range rules {
if action, ok := rule.Action.(RulesAction); ok {
if err := action.applyRules(state, i, compiled); err != nil {
return nil, fmt.Errorf("%s.%d: %s", state, i, err)
}
goto restart
}
}
}
keys := make([]string, 0, len(compiled))
for key := range compiled {
keys = append(keys, key)
}
symbols := map[string]TokenType{
"EOF": EOF,
}
sort.Strings(keys)
duplicates := map[string]compiledRule{}
rn := EOF - 1
for _, key := range keys {
for i, rule := range compiled[key] {
if dup, ok := duplicates[rule.Name]; ok && rule.Pattern != dup.Pattern {
panic(fmt.Sprintf("duplicate key %q with different patterns %q != %q", rule.Name, rule.Pattern, dup.Pattern))
}
duplicates[rule.Name] = rule
compiled[key][i] = rule
symbols[rule.Name] = rn
rn--
}
}
d := &StatefulDefinition{
initialState: "Root",
rules: compiled,
symbols: symbols,
}
for _, option := range options {
option(d)
}
return d, nil
}
// Rules returns the user-provided Rules used to construct the lexer.
func (d *StatefulDefinition) Rules() Rules {
out := Rules{}
for state, rules := range d.rules {
for _, rule := range rules {
out[state] = append(out[state], rule.Rule)
}
}
return out
}
// LexString is a fast-path implementation for lexing strings.
func (d *StatefulDefinition) LexString(filename string, s string) (Lexer, error) {
return &StatefulLexer{
def: d,
data: s,
stack: []lexerState{{name: d.initialState}},
pos: Position{
Filename: filename,
Line: 1,
Column: 1,
},
}, nil
}
func (d *StatefulDefinition) Lex(filename string, r io.Reader) (Lexer, error) { // nolint: golint
w := &strings.Builder{}
_, err := io.Copy(w, r)
if err != nil {
return nil, err
}
return d.LexString(filename, w.String())
}
func (d *StatefulDefinition) Symbols() map[string]TokenType { // nolint: golint
return d.symbols
}
type lexerState struct {
name string
groups []string
}
// StatefulLexer implementation.
type StatefulLexer struct {
stack []lexerState
def *StatefulDefinition
data string
pos Position
}
func (l *StatefulLexer) Next() (Token, error) { // nolint: golint
parent := l.stack[len(l.stack)-1]
rules := l.def.rules[parent.name]
next:
for len(l.data) > 0 {
var (
rule *compiledRule
m []int
match []int
)
for i, candidate := range rules {
// Special case "Return()".
if candidate.Rule == ReturnRule {
l.stack = l.stack[:len(l.stack)-1]
parent = l.stack[len(l.stack)-1]
rules = l.def.rules[parent.name]
continue next
}
re, err := l.getPattern(candidate)
if err != nil {
return Token{}, errorf(l.pos, "rule %q: %s", candidate.Name, err)
}
m = re.FindStringSubmatchIndex(l.data)
if m != nil && (match == nil || m[1] > match[1]) {
match = m
rule = &rules[i]
if !l.def.matchLongest {
break
}
}
}
if match == nil || rule == nil {
sample := []rune(l.data)
if len(sample) > 16 {
sample = append(sample[:16], []rune("...")...)
}
return Token{}, errorf(l.pos, "invalid input text %q", string(sample))
}
if rule.Action != nil {
groups := make([]string, 0, len(match)/2)
for i := 0; i < len(match); i += 2 {
groups = append(groups, l.data[match[i]:match[i+1]])
}
if err := rule.Action.applyAction(l, groups); err != nil {
return Token{}, errorf(l.pos, "rule %q: %s", rule.Name, err)
}
} else if match[0] == match[1] {
return Token{}, errorf(l.pos, "rule %q did not match any input", rule.Name)
}
span := l.data[match[0]:match[1]]
l.data = l.data[match[1]:]
// l.groups = groups
// Update position.
pos := l.pos
l.pos.Advance(span)
if rule.ignore {
parent = l.stack[len(l.stack)-1]
rules = l.def.rules[parent.name]
continue
}
return Token{
Type: l.def.symbols[rule.Name],
Value: span,
Pos: pos,
}, nil
}
return EOFToken(l.pos), nil
}
func (l *StatefulLexer) getPattern(candidate compiledRule) (*regexp.Regexp, error) {
if candidate.RE != nil {
return candidate.RE, nil
}
// We don't have a compiled RE. This means there are back-references
// that need to be substituted first.
parent := l.stack[len(l.stack)-1]
key := candidate.Pattern + "\000" + strings.Join(parent.groups, "\000")
cached, ok := l.def.backrefCache.Load(key)
if ok {
return cached.(*regexp.Regexp), nil
}
var (
re *regexp.Regexp
err error
)
pattern := backrefReplace.ReplaceAllStringFunc(candidate.Pattern, func(s string) string {
var rematch = backrefReplace.FindStringSubmatch(s)
n, nerr := strconv.ParseInt(rematch[2], 10, 64)
if nerr != nil {
err = nerr
return s
}
if len(parent.groups) == 0 || int(n) >= len(parent.groups) {
err = fmt.Errorf("invalid group %d from parent with %d groups", n, len(parent.groups))
return s
}
// concatenate the leading \\\\ which are already escaped to the quoted match.
return rematch[1][:len(rematch[1])-1] + regexp.QuoteMeta(parent.groups[n])
})
if err == nil {
re, err = regexp.Compile("^(?:" + pattern + ")")
}
if err != nil {
return nil, fmt.Errorf("invalid backref expansion: %q: %s", pattern, err)
}
l.def.backrefCache.Store(key, re)
return re, nil
}
================================================
FILE: vendor/github.com/alecthomas/participle/v2/lexer/text_scanner.go
================================================
package lexer
import (
"bytes"
"io"
"strings"
"text/scanner"
)
// TextScannerLexer is a lexer that uses the text/scanner module.
var (
TextScannerLexer Definition = &textScannerLexerDefinition{}
// DefaultDefinition defines properties for the default lexer.
DefaultDefinition = TextScannerLexer
)
// NewTextScannerLexer constructs a Definition that uses an underlying scanner.Scanner
//
// "configure" will be called after the scanner.Scanner.Init(r) is called. If "configure"
// is nil a default scanner.Scanner will be used.
func NewTextScannerLexer(configure func(*scanner.Scanner)) Definition {
return &textScannerLexerDefinition{configure: configure}
}
type textScannerLexerDefinition struct {
configure func(*scanner.Scanner)
}
func (d *textScannerLexerDefinition) Lex(filename string, r io.Reader) (Lexer, error) {
l := Lex(filename, r)
if d.configure != nil {
d.configure(l.(*textScannerLexer).scanner)
}
return l, nil
}
func (d *textScannerLexerDefinition) Symbols() map[string]TokenType {
return map[string]TokenType{
"EOF": EOF,
"Char": scanner.Char,
"Ident": scanner.Ident,
"Int": scanner.Int,
"Float": scanner.Float,
"String": scanner.String,
"RawString": scanner.RawString,
"Comment": scanner.Comment,
}
}
// textScannerLexer is a Lexer based on text/scanner.Scanner
type textScannerLexer struct {
scanner *scanner.Scanner
filename string
err error
}
// Lex an io.Reader with text/scanner.Scanner.
//
// This provides very fast lexing of source code compatible with Go tokens.
//
// Note that this differs from text/scanner.Scanner in that string tokens will be unquoted.
func Lex(filename string, r io.Reader) Lexer {
s := &scanner.Scanner{}
s.Init(r)
lexer := lexWithScanner(filename, s)
lexer.scanner.Error = func(s *scanner.Scanner, msg string) {
lexer.err = errorf(Position(lexer.scanner.Pos()), msg)
}
return lexer
}
// LexWithScanner creates a Lexer from a user-provided scanner.Scanner.
//
// Useful if you need to customise the Scanner.
func LexWithScanner(filename string, scan *scanner.Scanner) Lexer {
return lexWithScanner(filename, scan)
}
func lexWithScanner(filename string, scan *scanner.Scanner) *textScannerLexer {
scan.Filename = filename
lexer := &textScannerLexer{
filename: filename,
scanner: scan,
}
return lexer
}
// LexBytes returns a new default lexer over bytes.
func LexBytes(filename string, b []byte) Lexer {
return Lex(filename, bytes.NewReader(b))
}
// LexString returns a new default lexer over a string.
func LexString(filename, s string) Lexer {
return Lex(filename, strings.NewReader(s))
}
func (t *textScannerLexer) Next() (Token, error) {
typ := t.scanner.Scan()
text := t.scanner.TokenText()
pos := Position(t.scanner.Position)
pos.Filename = t.filename
if t.err != nil {
return Token{}, t.err
}
return Token{
Type: TokenType(typ),
Value: text,
Pos: pos,
}, nil
}
================================================
FILE: vendor/github.com/armon/go-metrics/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
/metrics.out
.idea
================================================
FILE: vendor/github.com/armon/go-metrics/.travis.yml
================================================
language: go
go:
- "1.x"
env:
- GO111MODULE=on
install:
- go get ./...
script:
- go test ./...
================================================
FILE: vendor/github.com/armon/go-metrics/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2013 Armon Dadgar
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/armon/go-metrics/README.md
================================================
go-metrics
==========
This library provides a `metrics` package which can be used to instrument code,
expose application metrics, and profile runtime performance in a flexible manner.
Current API: [](https://godoc.org/github.com/armon/go-metrics)
Sinks
-----
The `metrics` package makes use of a `MetricSink` interface to support delivery
to any type of backend. Currently the following sinks are provided:
* StatsiteSink : Sinks to a [statsite](https://github.com/armon/statsite/) instance (TCP)
* StatsdSink: Sinks to a [StatsD](https://github.com/etsy/statsd/) / statsite instance (UDP)
* PrometheusSink: Sinks to a [Prometheus](http://prometheus.io/) metrics endpoint (exposed via HTTP for scrapes)
* InmemSink : Provides in-memory aggregation, can be used to export stats
* FanoutSink : Sinks to multiple sinks. Enables writing to multiple statsite instances for example.
* BlackholeSink : Sinks to nowhere
In addition to the sinks, the `InmemSignal` can be used to catch a signal,
and dump a formatted output of recent metrics. For example, when a process gets
a SIGUSR1, it can dump to stderr recent performance metrics for debugging.
Labels
------
Most metrics do have an equivalent ending with `WithLabels`, such methods
allow to push metrics with labels and use some features of underlying Sinks
(ex: translated into Prometheus labels).
Since some of these labels may increase greatly cardinality of metrics, the
library allow to filter labels using a blacklist/whitelist filtering system
which is global to all metrics.
* If `Config.AllowedLabels` is not nil, then only labels specified in this value will be sent to underlying Sink, otherwise, all labels are sent by default.
* If `Config.BlockedLabels` is not nil, any label specified in this value will not be sent to underlying Sinks.
By default, both `Config.AllowedLabels` and `Config.BlockedLabels` are nil, meaning that
no tags are filetered at all, but it allow to a user to globally block some tags with high
cardinality at application level.
Examples
--------
Here is an example of using the package:
```go
func SlowMethod() {
// Profiling the runtime of a method
defer metrics.MeasureSince([]string{"SlowMethod"}, time.Now())
}
// Configure a statsite sink as the global metrics sink
sink, _ := metrics.NewStatsiteSink("statsite:8125")
metrics.NewGlobal(metrics.DefaultConfig("service-name"), sink)
// Emit a Key/Value pair
metrics.EmitKey([]string{"questions", "meaning of life"}, 42)
```
Here is an example of setting up a signal handler:
```go
// Setup the inmem sink and signal handler
inm := metrics.NewInmemSink(10*time.Second, time.Minute)
sig := metrics.DefaultInmemSignal(inm)
metrics.NewGlobal(metrics.DefaultConfig("service-name"), inm)
// Run some code
inm.SetGauge([]string{"foo"}, 42)
inm.EmitKey([]string{"bar"}, 30)
inm.IncrCounter([]string{"baz"}, 42)
inm.IncrCounter([]string{"baz"}, 1)
inm.IncrCounter([]string{"baz"}, 80)
inm.AddSample([]string{"method", "wow"}, 42)
inm.AddSample([]string{"method", "wow"}, 100)
inm.AddSample([]string{"method", "wow"}, 22)
....
```
When a signal comes in, output like the following will be dumped to stderr:
[2014-01-28 14:57:33.04 -0800 PST][G] 'foo': 42.000
[2014-01-28 14:57:33.04 -0800 PST][P] 'bar': 30.000
[2014-01-28 14:57:33.04 -0800 PST][C] 'baz': Count: 3 Min: 1.000 Mean: 41.000 Max: 80.000 Stddev: 39.509
[2014-01-28 14:57:33.04 -0800 PST][S] 'method.wow': Count: 3 Min: 22.000 Mean: 54.667 Max: 100.000 Stddev: 40.513
================================================
FILE: vendor/github.com/armon/go-metrics/const_unix.go
================================================
// +build !windows
package metrics
import (
"syscall"
)
const (
// DefaultSignal is used with DefaultInmemSignal
DefaultSignal = syscall.SIGUSR1
)
================================================
FILE: vendor/github.com/armon/go-metrics/const_windows.go
================================================
// +build windows
package metrics
import (
"syscall"
)
const (
// DefaultSignal is used with DefaultInmemSignal
// Windows has no SIGUSR1, use SIGBREAK
DefaultSignal = syscall.Signal(21)
)
================================================
FILE: vendor/github.com/armon/go-metrics/inmem.go
================================================
package metrics
import (
"bytes"
"fmt"
"math"
"net/url"
"strings"
"sync"
"time"
)
var spaceReplacer = strings.NewReplacer(" ", "_")
// InmemSink provides a MetricSink that does in-memory aggregation
// without sending metrics over a network. It can be embedded within
// an application to provide profiling information.
type InmemSink struct {
// How long is each aggregation interval
interval time.Duration
// Retain controls how many metrics interval we keep
retain time.Duration
// maxIntervals is the maximum length of intervals.
// It is retain / interval.
maxIntervals int
// intervals is a slice of the retained intervals
intervals []*IntervalMetrics
intervalLock sync.RWMutex
rateDenom float64
}
// IntervalMetrics stores the aggregated metrics
// for a specific interval
type IntervalMetrics struct {
sync.RWMutex
// The start time of the interval
Interval time.Time
// Gauges maps the key to the last set value
Gauges map[string]GaugeValue
// Points maps the string to the list of emitted values
// from EmitKey
Points map[string][]float32
// Counters maps the string key to a sum of the counter
// values
Counters map[string]SampledValue
// Samples maps the key to an AggregateSample,
// which has the rolled up view of a sample
Samples map[string]SampledValue
// done is closed when this interval has ended, and a new IntervalMetrics
// has been created to receive any future metrics.
done chan struct{}
}
// NewIntervalMetrics creates a new IntervalMetrics for a given interval
func NewIntervalMetrics(intv time.Time) *IntervalMetrics {
return &IntervalMetrics{
Interval: intv,
Gauges: make(map[string]GaugeValue),
Points: make(map[string][]float32),
Counters: make(map[string]SampledValue),
Samples: make(map[string]SampledValue),
done: make(chan struct{}),
}
}
// AggregateSample is used to hold aggregate metrics
// about a sample
type AggregateSample struct {
Count int // The count of emitted pairs
Rate float64 // The values rate per time unit (usually 1 second)
Sum float64 // The sum of values
SumSq float64 `json:"-"` // The sum of squared values
Min float64 // Minimum value
Max float64 // Maximum value
LastUpdated time.Time `json:"-"` // When value was last updated
}
// Computes a Stddev of the values
func (a *AggregateSample) Stddev() float64 {
num := (float64(a.Count) * a.SumSq) - math.Pow(a.Sum, 2)
div := float64(a.Count * (a.Count - 1))
if div == 0 {
return 0
}
return math.Sqrt(num / div)
}
// Computes a mean of the values
func (a *AggregateSample) Mean() float64 {
if a.Count == 0 {
return 0
}
return a.Sum / float64(a.Count)
}
// Ingest is used to update a sample
func (a *AggregateSample) Ingest(v float64, rateDenom float64) {
a.Count++
a.Sum += v
a.SumSq += (v * v)
if v < a.Min || a.Count == 1 {
a.Min = v
}
if v > a.Max || a.Count == 1 {
a.Max = v
}
a.Rate = float64(a.Sum) / rateDenom
a.LastUpdated = time.Now()
}
func (a *AggregateSample) String() string {
if a.Count == 0 {
return "Count: 0"
} else if a.Stddev() == 0 {
return fmt.Sprintf("Count: %d Sum: %0.3f LastUpdated: %s", a.Count, a.Sum, a.LastUpdated)
} else {
return fmt.Sprintf("Count: %d Min: %0.3f Mean: %0.3f Max: %0.3f Stddev: %0.3f Sum: %0.3f LastUpdated: %s",
a.Count, a.Min, a.Mean(), a.Max, a.Stddev(), a.Sum, a.LastUpdated)
}
}
// NewInmemSinkFromURL creates an InmemSink from a URL. It is used
// (and tested) from NewMetricSinkFromURL.
func NewInmemSinkFromURL(u *url.URL) (MetricSink, error) {
params := u.Query()
interval, err := time.ParseDuration(params.Get("interval"))
if err != nil {
return nil, fmt.Errorf("Bad 'interval' param: %s", err)
}
retain, err := time.ParseDuration(params.Get("retain"))
if err != nil {
return nil, fmt.Errorf("Bad 'retain' param: %s", err)
}
return NewInmemSink(interval, retain), nil
}
// NewInmemSink is used to construct a new in-memory sink.
// Uses an aggregation interval and maximum retention period.
func NewInmemSink(interval, retain time.Duration) *InmemSink {
rateTimeUnit := time.Second
i := &InmemSink{
interval: interval,
retain: retain,
maxIntervals: int(retain / interval),
rateDenom: float64(interval.Nanoseconds()) / float64(rateTimeUnit.Nanoseconds()),
}
i.intervals = make([]*IntervalMetrics, 0, i.maxIntervals)
return i
}
func (i *InmemSink) SetGauge(key []string, val float32) {
i.SetGaugeWithLabels(key, val, nil)
}
func (i *InmemSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
k, name := i.flattenKeyLabels(key, labels)
intv := i.getInterval()
intv.Lock()
defer intv.Unlock()
intv.Gauges[k] = GaugeValue{Name: name, Value: val, Labels: labels}
}
func (i *InmemSink) EmitKey(key []string, val float32) {
k := i.flattenKey(key)
intv := i.getInterval()
intv.Lock()
defer intv.Unlock()
vals := intv.Points[k]
intv.Points[k] = append(vals, val)
}
func (i *InmemSink) IncrCounter(key []string, val float32) {
i.IncrCounterWithLabels(key, val, nil)
}
func (i *InmemSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
k, name := i.flattenKeyLabels(key, labels)
intv := i.getInterval()
intv.Lock()
defer intv.Unlock()
agg, ok := intv.Counters[k]
if !ok {
agg = SampledValue{
Name: name,
AggregateSample: &AggregateSample{},
Labels: labels,
}
intv.Counters[k] = agg
}
agg.Ingest(float64(val), i.rateDenom)
}
func (i *InmemSink) AddSample(key []string, val float32) {
i.AddSampleWithLabels(key, val, nil)
}
func (i *InmemSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
k, name := i.flattenKeyLabels(key, labels)
intv := i.getInterval()
intv.Lock()
defer intv.Unlock()
agg, ok := intv.Samples[k]
if !ok {
agg = SampledValue{
Name: name,
AggregateSample: &AggregateSample{},
Labels: labels,
}
intv.Samples[k] = agg
}
agg.Ingest(float64(val), i.rateDenom)
}
// Data is used to retrieve all the aggregated metrics
// Intervals may be in use, and a read lock should be acquired
func (i *InmemSink) Data() []*IntervalMetrics {
// Get the current interval, forces creation
i.getInterval()
i.intervalLock.RLock()
defer i.intervalLock.RUnlock()
n := len(i.intervals)
intervals := make([]*IntervalMetrics, n)
copy(intervals[:n-1], i.intervals[:n-1])
current := i.intervals[n-1]
// make its own copy for current interval
intervals[n-1] = &IntervalMetrics{}
copyCurrent := intervals[n-1]
current.RLock()
*copyCurrent = *current
// RWMutex is not safe to copy, so create a new instance on the copy
copyCurrent.RWMutex = sync.RWMutex{}
copyCurrent.Gauges = make(map[string]GaugeValue, len(current.Gauges))
for k, v := range current.Gauges {
copyCurrent.Gauges[k] = v
}
// saved values will be not change, just copy its link
copyCurrent.Points = make(map[string][]float32, len(current.Points))
for k, v := range current.Points {
copyCurrent.Points[k] = v
}
copyCurrent.Counters = make(map[string]SampledValue, len(current.Counters))
for k, v := range current.Counters {
copyCurrent.Counters[k] = v.deepCopy()
}
copyCurrent.Samples = make(map[string]SampledValue, len(current.Samples))
for k, v := range current.Samples {
copyCurrent.Samples[k] = v.deepCopy()
}
current.RUnlock()
return intervals
}
// getInterval returns the current interval. A new interval is created if no
// previous interval exists, or if the current time is beyond the window for the
// current interval.
func (i *InmemSink) getInterval() *IntervalMetrics {
intv := time.Now().Truncate(i.interval)
// Attempt to return the existing interval first, because it only requires
// a read lock.
i.intervalLock.RLock()
n := len(i.intervals)
if n > 0 && i.intervals[n-1].Interval == intv {
defer i.intervalLock.RUnlock()
return i.intervals[n-1]
}
i.intervalLock.RUnlock()
i.intervalLock.Lock()
defer i.intervalLock.Unlock()
// Re-check for an existing interval now that the lock is re-acquired.
n = len(i.intervals)
if n > 0 && i.intervals[n-1].Interval == intv {
return i.intervals[n-1]
}
current := NewIntervalMetrics(intv)
i.intervals = append(i.intervals, current)
if n > 0 {
close(i.intervals[n-1].done)
}
n++
// Prune old intervals if the count exceeds the max.
if n >= i.maxIntervals {
copy(i.intervals[0:], i.intervals[n-i.maxIntervals:])
i.intervals = i.intervals[:i.maxIntervals]
}
return current
}
// Flattens the key for formatting, removes spaces
func (i *InmemSink) flattenKey(parts []string) string {
buf := &bytes.Buffer{}
joined := strings.Join(parts, ".")
spaceReplacer.WriteString(buf, joined)
return buf.String()
}
// Flattens the key for formatting along with its labels, removes spaces
func (i *InmemSink) flattenKeyLabels(parts []string, labels []Label) (string, string) {
key := i.flattenKey(parts)
buf := bytes.NewBufferString(key)
for _, label := range labels {
spaceReplacer.WriteString(buf, fmt.Sprintf(";%s=%s", label.Name, label.Value))
}
return buf.String(), key
}
================================================
FILE: vendor/github.com/armon/go-metrics/inmem_endpoint.go
================================================
package metrics
import (
"context"
"fmt"
"net/http"
"sort"
"time"
)
// MetricsSummary holds a roll-up of metrics info for a given interval
type MetricsSummary struct {
Timestamp string
Gauges []GaugeValue
Points []PointValue
Counters []SampledValue
Samples []SampledValue
}
type GaugeValue struct {
Name string
Hash string `json:"-"`
Value float32
Labels []Label `json:"-"`
DisplayLabels map[string]string `json:"Labels"`
}
type PointValue struct {
Name string
Points []float32
}
type SampledValue struct {
Name string
Hash string `json:"-"`
*AggregateSample
Mean float64
Stddev float64
Labels []Label `json:"-"`
DisplayLabels map[string]string `json:"Labels"`
}
// deepCopy allocates a new instance of AggregateSample
func (source *SampledValue) deepCopy() SampledValue {
dest := *source
if source.AggregateSample != nil {
dest.AggregateSample = &AggregateSample{}
*dest.AggregateSample = *source.AggregateSample
}
return dest
}
// DisplayMetrics returns a summary of the metrics from the most recent finished interval.
func (i *InmemSink) DisplayMetrics(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
data := i.Data()
var interval *IntervalMetrics
n := len(data)
switch {
case n == 0:
return nil, fmt.Errorf("no metric intervals have been initialized yet")
case n == 1:
// Show the current interval if it's all we have
interval = data[0]
default:
// Show the most recent finished interval if we have one
interval = data[n-2]
}
return newMetricSummaryFromInterval(interval), nil
}
func newMetricSummaryFromInterval(interval *IntervalMetrics) MetricsSummary {
interval.RLock()
defer interval.RUnlock()
summary := MetricsSummary{
Timestamp: interval.Interval.Round(time.Second).UTC().String(),
Gauges: make([]GaugeValue, 0, len(interval.Gauges)),
Points: make([]PointValue, 0, len(interval.Points)),
}
// Format and sort the output of each metric type, so it gets displayed in a
// deterministic order.
for name, points := range interval.Points {
summary.Points = append(summary.Points, PointValue{name, points})
}
sort.Slice(summary.Points, func(i, j int) bool {
return summary.Points[i].Name < summary.Points[j].Name
})
for hash, value := range interval.Gauges {
value.Hash = hash
value.DisplayLabels = make(map[string]string)
for _, label := range value.Labels {
value.DisplayLabels[label.Name] = label.Value
}
value.Labels = nil
summary.Gauges = append(summary.Gauges, value)
}
sort.Slice(summary.Gauges, func(i, j int) bool {
return summary.Gauges[i].Hash < summary.Gauges[j].Hash
})
summary.Counters = formatSamples(interval.Counters)
summary.Samples = formatSamples(interval.Samples)
return summary
}
func formatSamples(source map[string]SampledValue) []SampledValue {
output := make([]SampledValue, 0, len(source))
for hash, sample := range source {
displayLabels := make(map[string]string)
for _, label := range sample.Labels {
displayLabels[label.Name] = label.Value
}
output = append(output, SampledValue{
Name: sample.Name,
Hash: hash,
AggregateSample: sample.AggregateSample,
Mean: sample.AggregateSample.Mean(),
Stddev: sample.AggregateSample.Stddev(),
DisplayLabels: displayLabels,
})
}
sort.Slice(output, func(i, j int) bool {
return output[i].Hash < output[j].Hash
})
return output
}
type Encoder interface {
Encode(interface{}) error
}
// Stream writes metrics using encoder.Encode each time an interval ends. Runs
// until the request context is cancelled, or the encoder returns an error.
// The caller is responsible for logging any errors from encoder.
func (i *InmemSink) Stream(ctx context.Context, encoder Encoder) {
interval := i.getInterval()
for {
select {
case <-interval.done:
summary := newMetricSummaryFromInterval(interval)
if err := encoder.Encode(summary); err != nil {
return
}
// update interval to the next one
interval = i.getInterval()
case <-ctx.Done():
return
}
}
}
================================================
FILE: vendor/github.com/armon/go-metrics/inmem_signal.go
================================================
package metrics
import (
"bytes"
"fmt"
"io"
"os"
"os/signal"
"strings"
"sync"
"syscall"
)
// InmemSignal is used to listen for a given signal, and when received,
// to dump the current metrics from the InmemSink to an io.Writer
type InmemSignal struct {
signal syscall.Signal
inm *InmemSink
w io.Writer
sigCh chan os.Signal
stop bool
stopCh chan struct{}
stopLock sync.Mutex
}
// NewInmemSignal creates a new InmemSignal which listens for a given signal,
// and dumps the current metrics out to a writer
func NewInmemSignal(inmem *InmemSink, sig syscall.Signal, w io.Writer) *InmemSignal {
i := &InmemSignal{
signal: sig,
inm: inmem,
w: w,
sigCh: make(chan os.Signal, 1),
stopCh: make(chan struct{}),
}
signal.Notify(i.sigCh, sig)
go i.run()
return i
}
// DefaultInmemSignal returns a new InmemSignal that responds to SIGUSR1
// and writes output to stderr. Windows uses SIGBREAK
func DefaultInmemSignal(inmem *InmemSink) *InmemSignal {
return NewInmemSignal(inmem, DefaultSignal, os.Stderr)
}
// Stop is used to stop the InmemSignal from listening
func (i *InmemSignal) Stop() {
i.stopLock.Lock()
defer i.stopLock.Unlock()
if i.stop {
return
}
i.stop = true
close(i.stopCh)
signal.Stop(i.sigCh)
}
// run is a long running routine that handles signals
func (i *InmemSignal) run() {
for {
select {
case <-i.sigCh:
i.dumpStats()
case <-i.stopCh:
return
}
}
}
// dumpStats is used to dump the data to output writer
func (i *InmemSignal) dumpStats() {
buf := bytes.NewBuffer(nil)
data := i.inm.Data()
// Skip the last period which is still being aggregated
for j := 0; j < len(data)-1; j++ {
intv := data[j]
intv.RLock()
for _, val := range intv.Gauges {
name := i.flattenLabels(val.Name, val.Labels)
fmt.Fprintf(buf, "[%v][G] '%s': %0.3f\n", intv.Interval, name, val.Value)
}
for name, vals := range intv.Points {
for _, val := range vals {
fmt.Fprintf(buf, "[%v][P] '%s': %0.3f\n", intv.Interval, name, val)
}
}
for _, agg := range intv.Counters {
name := i.flattenLabels(agg.Name, agg.Labels)
fmt.Fprintf(buf, "[%v][C] '%s': %s\n", intv.Interval, name, agg.AggregateSample)
}
for _, agg := range intv.Samples {
name := i.flattenLabels(agg.Name, agg.Labels)
fmt.Fprintf(buf, "[%v][S] '%s': %s\n", intv.Interval, name, agg.AggregateSample)
}
intv.RUnlock()
}
// Write out the bytes
i.w.Write(buf.Bytes())
}
// Flattens the key for formatting along with its labels, removes spaces
func (i *InmemSignal) flattenLabels(name string, labels []Label) string {
buf := bytes.NewBufferString(name)
replacer := strings.NewReplacer(" ", "_", ":", "_")
for _, label := range labels {
replacer.WriteString(buf, ".")
replacer.WriteString(buf, label.Value)
}
return buf.String()
}
================================================
FILE: vendor/github.com/armon/go-metrics/metrics.go
================================================
package metrics
import (
"runtime"
"strings"
"time"
"github.com/hashicorp/go-immutable-radix"
)
type Label struct {
Name string
Value string
}
func (m *Metrics) SetGauge(key []string, val float32) {
m.SetGaugeWithLabels(key, val, nil)
}
func (m *Metrics) SetGaugeWithLabels(key []string, val float32, labels []Label) {
if m.HostName != "" {
if m.EnableHostnameLabel {
labels = append(labels, Label{"host", m.HostName})
} else if m.EnableHostname {
key = insert(0, m.HostName, key)
}
}
if m.EnableTypePrefix {
key = insert(0, "gauge", key)
}
if m.ServiceName != "" {
if m.EnableServiceLabel {
labels = append(labels, Label{"service", m.ServiceName})
} else {
key = insert(0, m.ServiceName, key)
}
}
allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return
}
m.sink.SetGaugeWithLabels(key, val, labelsFiltered)
}
func (m *Metrics) EmitKey(key []string, val float32) {
if m.EnableTypePrefix {
key = insert(0, "kv", key)
}
if m.ServiceName != "" {
key = insert(0, m.ServiceName, key)
}
allowed, _ := m.allowMetric(key, nil)
if !allowed {
return
}
m.sink.EmitKey(key, val)
}
func (m *Metrics) IncrCounter(key []string, val float32) {
m.IncrCounterWithLabels(key, val, nil)
}
func (m *Metrics) IncrCounterWithLabels(key []string, val float32, labels []Label) {
if m.HostName != "" && m.EnableHostnameLabel {
labels = append(labels, Label{"host", m.HostName})
}
if m.EnableTypePrefix {
key = insert(0, "counter", key)
}
if m.ServiceName != "" {
if m.EnableServiceLabel {
labels = append(labels, Label{"service", m.ServiceName})
} else {
key = insert(0, m.ServiceName, key)
}
}
allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return
}
m.sink.IncrCounterWithLabels(key, val, labelsFiltered)
}
func (m *Metrics) AddSample(key []string, val float32) {
m.AddSampleWithLabels(key, val, nil)
}
func (m *Metrics) AddSampleWithLabels(key []string, val float32, labels []Label) {
if m.HostName != "" && m.EnableHostnameLabel {
labels = append(labels, Label{"host", m.HostName})
}
if m.EnableTypePrefix {
key = insert(0, "sample", key)
}
if m.ServiceName != "" {
if m.EnableServiceLabel {
labels = append(labels, Label{"service", m.ServiceName})
} else {
key = insert(0, m.ServiceName, key)
}
}
allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return
}
m.sink.AddSampleWithLabels(key, val, labelsFiltered)
}
func (m *Metrics) MeasureSince(key []string, start time.Time) {
m.MeasureSinceWithLabels(key, start, nil)
}
func (m *Metrics) MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
if m.HostName != "" && m.EnableHostnameLabel {
labels = append(labels, Label{"host", m.HostName})
}
if m.EnableTypePrefix {
key = insert(0, "timer", key)
}
if m.ServiceName != "" {
if m.EnableServiceLabel {
labels = append(labels, Label{"service", m.ServiceName})
} else {
key = insert(0, m.ServiceName, key)
}
}
allowed, labelsFiltered := m.allowMetric(key, labels)
if !allowed {
return
}
now := time.Now()
elapsed := now.Sub(start)
msec := float32(elapsed.Nanoseconds()) / float32(m.TimerGranularity)
m.sink.AddSampleWithLabels(key, msec, labelsFiltered)
}
// UpdateFilter overwrites the existing filter with the given rules.
func (m *Metrics) UpdateFilter(allow, block []string) {
m.UpdateFilterAndLabels(allow, block, m.AllowedLabels, m.BlockedLabels)
}
// UpdateFilterAndLabels overwrites the existing filter with the given rules.
func (m *Metrics) UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) {
m.filterLock.Lock()
defer m.filterLock.Unlock()
m.AllowedPrefixes = allow
m.BlockedPrefixes = block
if allowedLabels == nil {
// Having a white list means we take only elements from it
m.allowedLabels = nil
} else {
m.allowedLabels = make(map[string]bool)
for _, v := range allowedLabels {
m.allowedLabels[v] = true
}
}
m.blockedLabels = make(map[string]bool)
for _, v := range blockedLabels {
m.blockedLabels[v] = true
}
m.AllowedLabels = allowedLabels
m.BlockedLabels = blockedLabels
m.filter = iradix.New()
for _, prefix := range m.AllowedPrefixes {
m.filter, _, _ = m.filter.Insert([]byte(prefix), true)
}
for _, prefix := range m.BlockedPrefixes {
m.filter, _, _ = m.filter.Insert([]byte(prefix), false)
}
}
// labelIsAllowed return true if a should be included in metric
// the caller should lock m.filterLock while calling this method
func (m *Metrics) labelIsAllowed(label *Label) bool {
labelName := (*label).Name
if m.blockedLabels != nil {
_, ok := m.blockedLabels[labelName]
if ok {
// If present, let's remove this label
return false
}
}
if m.allowedLabels != nil {
_, ok := m.allowedLabels[labelName]
return ok
}
// Allow by default
return true
}
// filterLabels return only allowed labels
// the caller should lock m.filterLock while calling this method
func (m *Metrics) filterLabels(labels []Label) []Label {
if labels == nil {
return nil
}
toReturn := []Label{}
for _, label := range labels {
if m.labelIsAllowed(&label) {
toReturn = append(toReturn, label)
}
}
return toReturn
}
// Returns whether the metric should be allowed based on configured prefix filters
// Also return the applicable labels
func (m *Metrics) allowMetric(key []string, labels []Label) (bool, []Label) {
m.filterLock.RLock()
defer m.filterLock.RUnlock()
if m.filter == nil || m.filter.Len() == 0 {
return m.Config.FilterDefault, m.filterLabels(labels)
}
_, allowed, ok := m.filter.Root().LongestPrefix([]byte(strings.Join(key, ".")))
if !ok {
return m.Config.FilterDefault, m.filterLabels(labels)
}
return allowed.(bool), m.filterLabels(labels)
}
// Periodically collects runtime stats to publish
func (m *Metrics) collectStats() {
for {
time.Sleep(m.ProfileInterval)
m.EmitRuntimeStats()
}
}
// Emits various runtime statsitics
func (m *Metrics) EmitRuntimeStats() {
// Export number of Goroutines
numRoutines := runtime.NumGoroutine()
m.SetGauge([]string{"runtime", "num_goroutines"}, float32(numRoutines))
// Export memory stats
var stats runtime.MemStats
runtime.ReadMemStats(&stats)
m.SetGauge([]string{"runtime", "alloc_bytes"}, float32(stats.Alloc))
m.SetGauge([]string{"runtime", "sys_bytes"}, float32(stats.Sys))
m.SetGauge([]string{"runtime", "malloc_count"}, float32(stats.Mallocs))
m.SetGauge([]string{"runtime", "free_count"}, float32(stats.Frees))
m.SetGauge([]string{"runtime", "heap_objects"}, float32(stats.HeapObjects))
m.SetGauge([]string{"runtime", "total_gc_pause_ns"}, float32(stats.PauseTotalNs))
m.SetGauge([]string{"runtime", "total_gc_runs"}, float32(stats.NumGC))
// Export info about the last few GC runs
num := stats.NumGC
// Handle wrap around
if num < m.lastNumGC {
m.lastNumGC = 0
}
// Ensure we don't scan more than 256
if num-m.lastNumGC >= 256 {
m.lastNumGC = num - 255
}
for i := m.lastNumGC; i < num; i++ {
pause := stats.PauseNs[i%256]
m.AddSample([]string{"runtime", "gc_pause_ns"}, float32(pause))
}
m.lastNumGC = num
}
// Creates a new slice with the provided string value as the first element
// and the provided slice values as the remaining values.
// Ordering of the values in the provided input slice is kept in tact in the output slice.
func insert(i int, v string, s []string) []string {
// Allocate new slice to avoid modifying the input slice
newS := make([]string, len(s)+1)
// Copy s[0, i-1] into newS
for j := 0; j < i; j++ {
newS[j] = s[j]
}
// Insert provided element at index i
newS[i] = v
// Copy s[i, len(s)-1] into newS starting at newS[i+1]
for j := i; j < len(s); j++ {
newS[j+1] = s[j]
}
return newS
}
================================================
FILE: vendor/github.com/armon/go-metrics/sink.go
================================================
package metrics
import (
"fmt"
"net/url"
)
// The MetricSink interface is used to transmit metrics information
// to an external system
type MetricSink interface {
// A Gauge should retain the last value it is set to
SetGauge(key []string, val float32)
SetGaugeWithLabels(key []string, val float32, labels []Label)
// Should emit a Key/Value pair for each call
EmitKey(key []string, val float32)
// Counters should accumulate values
IncrCounter(key []string, val float32)
IncrCounterWithLabels(key []string, val float32, labels []Label)
// Samples are for timing information, where quantiles are used
AddSample(key []string, val float32)
AddSampleWithLabels(key []string, val float32, labels []Label)
}
// BlackholeSink is used to just blackhole messages
type BlackholeSink struct{}
func (*BlackholeSink) SetGauge(key []string, val float32) {}
func (*BlackholeSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {}
func (*BlackholeSink) EmitKey(key []string, val float32) {}
func (*BlackholeSink) IncrCounter(key []string, val float32) {}
func (*BlackholeSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {}
func (*BlackholeSink) AddSample(key []string, val float32) {}
func (*BlackholeSink) AddSampleWithLabels(key []string, val float32, labels []Label) {}
// FanoutSink is used to sink to fanout values to multiple sinks
type FanoutSink []MetricSink
func (fh FanoutSink) SetGauge(key []string, val float32) {
fh.SetGaugeWithLabels(key, val, nil)
}
func (fh FanoutSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
for _, s := range fh {
s.SetGaugeWithLabels(key, val, labels)
}
}
func (fh FanoutSink) EmitKey(key []string, val float32) {
for _, s := range fh {
s.EmitKey(key, val)
}
}
func (fh FanoutSink) IncrCounter(key []string, val float32) {
fh.IncrCounterWithLabels(key, val, nil)
}
func (fh FanoutSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
for _, s := range fh {
s.IncrCounterWithLabels(key, val, labels)
}
}
func (fh FanoutSink) AddSample(key []string, val float32) {
fh.AddSampleWithLabels(key, val, nil)
}
func (fh FanoutSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
for _, s := range fh {
s.AddSampleWithLabels(key, val, labels)
}
}
// sinkURLFactoryFunc is an generic interface around the *SinkFromURL() function provided
// by each sink type
type sinkURLFactoryFunc func(*url.URL) (MetricSink, error)
// sinkRegistry supports the generic NewMetricSink function by mapping URL
// schemes to metric sink factory functions
var sinkRegistry = map[string]sinkURLFactoryFunc{
"statsd": NewStatsdSinkFromURL,
"statsite": NewStatsiteSinkFromURL,
"inmem": NewInmemSinkFromURL,
}
// NewMetricSinkFromURL allows a generic URL input to configure any of the
// supported sinks. The scheme of the URL identifies the type of the sink, the
// and query parameters are used to set options.
//
// "statsd://" - Initializes a StatsdSink. The host and port are passed through
// as the "addr" of the sink
//
// "statsite://" - Initializes a StatsiteSink. The host and port become the
// "addr" of the sink
//
// "inmem://" - Initializes an InmemSink. The host and port are ignored. The
// "interval" and "duration" query parameters must be specified with valid
// durations, see NewInmemSink for details.
func NewMetricSinkFromURL(urlStr string) (MetricSink, error) {
u, err := url.Parse(urlStr)
if err != nil {
return nil, err
}
sinkURLFactoryFunc := sinkRegistry[u.Scheme]
if sinkURLFactoryFunc == nil {
return nil, fmt.Errorf(
"cannot create metric sink, unrecognized sink name: %q", u.Scheme)
}
return sinkURLFactoryFunc(u)
}
================================================
FILE: vendor/github.com/armon/go-metrics/start.go
================================================
package metrics
import (
"os"
"sync"
"sync/atomic"
"time"
iradix "github.com/hashicorp/go-immutable-radix"
)
// Config is used to configure metrics settings
type Config struct {
ServiceName string // Prefixed with keys to separate services
HostName string // Hostname to use. If not provided and EnableHostname, it will be os.Hostname
EnableHostname bool // Enable prefixing gauge values with hostname
EnableHostnameLabel bool // Enable adding hostname to labels
EnableServiceLabel bool // Enable adding service to labels
EnableRuntimeMetrics bool // Enables profiling of runtime metrics (GC, Goroutines, Memory)
EnableTypePrefix bool // Prefixes key with a type ("counter", "gauge", "timer")
TimerGranularity time.Duration // Granularity of timers.
ProfileInterval time.Duration // Interval to profile runtime metrics
AllowedPrefixes []string // A list of metric prefixes to allow, with '.' as the separator
BlockedPrefixes []string // A list of metric prefixes to block, with '.' as the separator
AllowedLabels []string // A list of metric labels to allow, with '.' as the separator
BlockedLabels []string // A list of metric labels to block, with '.' as the separator
FilterDefault bool // Whether to allow metrics by default
}
// Metrics represents an instance of a metrics sink that can
// be used to emit
type Metrics struct {
Config
lastNumGC uint32
sink MetricSink
filter *iradix.Tree
allowedLabels map[string]bool
blockedLabels map[string]bool
filterLock sync.RWMutex // Lock filters and allowedLabels/blockedLabels access
}
// Shared global metrics instance
var globalMetrics atomic.Value // *Metrics
func init() {
// Initialize to a blackhole sink to avoid errors
globalMetrics.Store(&Metrics{sink: &BlackholeSink{}})
}
// Default returns the shared global metrics instance.
func Default() *Metrics {
return globalMetrics.Load().(*Metrics)
}
// DefaultConfig provides a sane default configuration
func DefaultConfig(serviceName string) *Config {
c := &Config{
ServiceName: serviceName, // Use client provided service
HostName: "",
EnableHostname: true, // Enable hostname prefix
EnableRuntimeMetrics: true, // Enable runtime profiling
EnableTypePrefix: false, // Disable type prefix
TimerGranularity: time.Millisecond, // Timers are in milliseconds
ProfileInterval: time.Second, // Poll runtime every second
FilterDefault: true, // Don't filter metrics by default
}
// Try to get the hostname
name, _ := os.Hostname()
c.HostName = name
return c
}
// New is used to create a new instance of Metrics
func New(conf *Config, sink MetricSink) (*Metrics, error) {
met := &Metrics{}
met.Config = *conf
met.sink = sink
met.UpdateFilterAndLabels(conf.AllowedPrefixes, conf.BlockedPrefixes, conf.AllowedLabels, conf.BlockedLabels)
// Start the runtime collector
if conf.EnableRuntimeMetrics {
go met.collectStats()
}
return met, nil
}
// NewGlobal is the same as New, but it assigns the metrics object to be
// used globally as well as returning it.
func NewGlobal(conf *Config, sink MetricSink) (*Metrics, error) {
metrics, err := New(conf, sink)
if err == nil {
globalMetrics.Store(metrics)
}
return metrics, err
}
// Proxy all the methods to the globalMetrics instance
func SetGauge(key []string, val float32) {
globalMetrics.Load().(*Metrics).SetGauge(key, val)
}
func SetGaugeWithLabels(key []string, val float32, labels []Label) {
globalMetrics.Load().(*Metrics).SetGaugeWithLabels(key, val, labels)
}
func EmitKey(key []string, val float32) {
globalMetrics.Load().(*Metrics).EmitKey(key, val)
}
func IncrCounter(key []string, val float32) {
globalMetrics.Load().(*Metrics).IncrCounter(key, val)
}
func IncrCounterWithLabels(key []string, val float32, labels []Label) {
globalMetrics.Load().(*Metrics).IncrCounterWithLabels(key, val, labels)
}
func AddSample(key []string, val float32) {
globalMetrics.Load().(*Metrics).AddSample(key, val)
}
func AddSampleWithLabels(key []string, val float32, labels []Label) {
globalMetrics.Load().(*Metrics).AddSampleWithLabels(key, val, labels)
}
func MeasureSince(key []string, start time.Time) {
globalMetrics.Load().(*Metrics).MeasureSince(key, start)
}
func MeasureSinceWithLabels(key []string, start time.Time, labels []Label) {
globalMetrics.Load().(*Metrics).MeasureSinceWithLabels(key, start, labels)
}
func UpdateFilter(allow, block []string) {
globalMetrics.Load().(*Metrics).UpdateFilter(allow, block)
}
// UpdateFilterAndLabels set allow/block prefixes of metrics while allowedLabels
// and blockedLabels - when not nil - allow filtering of labels in order to
// block/allow globally labels (especially useful when having large number of
// values for a given label). See README.md for more information about usage.
func UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels []string) {
globalMetrics.Load().(*Metrics).UpdateFilterAndLabels(allow, block, allowedLabels, blockedLabels)
}
================================================
FILE: vendor/github.com/armon/go-metrics/statsd.go
================================================
package metrics
import (
"bytes"
"fmt"
"log"
"net"
"net/url"
"strings"
"time"
)
const (
// statsdMaxLen is the maximum size of a packet
// to send to statsd
statsdMaxLen = 1400
)
// StatsdSink provides a MetricSink that can be used
// with a statsite or statsd metrics server. It uses
// only UDP packets, while StatsiteSink uses TCP.
type StatsdSink struct {
addr string
metricQueue chan string
}
// NewStatsdSinkFromURL creates an StatsdSink from a URL. It is used
// (and tested) from NewMetricSinkFromURL.
func NewStatsdSinkFromURL(u *url.URL) (MetricSink, error) {
return NewStatsdSink(u.Host)
}
// NewStatsdSink is used to create a new StatsdSink
func NewStatsdSink(addr string) (*StatsdSink, error) {
s := &StatsdSink{
addr: addr,
metricQueue: make(chan string, 4096),
}
go s.flushMetrics()
return s, nil
}
// Close is used to stop flushing to statsd
func (s *StatsdSink) Shutdown() {
close(s.metricQueue)
}
func (s *StatsdSink) SetGauge(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
}
func (s *StatsdSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
}
func (s *StatsdSink) EmitKey(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|kv\n", flatKey, val))
}
func (s *StatsdSink) IncrCounter(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
}
func (s *StatsdSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
}
func (s *StatsdSink) AddSample(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
}
func (s *StatsdSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
}
// Flattens the key for formatting, removes spaces
func (s *StatsdSink) flattenKey(parts []string) string {
joined := strings.Join(parts, ".")
return strings.Map(func(r rune) rune {
switch r {
case ':':
fallthrough
case ' ':
return '_'
default:
return r
}
}, joined)
}
// Flattens the key along with labels for formatting, removes spaces
func (s *StatsdSink) flattenKeyLabels(parts []string, labels []Label) string {
for _, label := range labels {
parts = append(parts, label.Value)
}
return s.flattenKey(parts)
}
// Does a non-blocking push to the metrics queue
func (s *StatsdSink) pushMetric(m string) {
select {
case s.metricQueue <- m:
default:
}
}
// Flushes metrics
func (s *StatsdSink) flushMetrics() {
var sock net.Conn
var err error
var wait <-chan time.Time
ticker := time.NewTicker(flushInterval)
defer ticker.Stop()
CONNECT:
// Create a buffer
buf := bytes.NewBuffer(nil)
// Attempt to connect
sock, err = net.Dial("udp", s.addr)
if err != nil {
log.Printf("[ERR] Error connecting to statsd! Err: %s", err)
goto WAIT
}
for {
select {
case metric, ok := <-s.metricQueue:
// Get a metric from the queue
if !ok {
goto QUIT
}
// Check if this would overflow the packet size
if len(metric)+buf.Len() > statsdMaxLen {
_, err := sock.Write(buf.Bytes())
buf.Reset()
if err != nil {
log.Printf("[ERR] Error writing to statsd! Err: %s", err)
goto WAIT
}
}
// Append to the buffer
buf.WriteString(metric)
case <-ticker.C:
if buf.Len() == 0 {
continue
}
_, err := sock.Write(buf.Bytes())
buf.Reset()
if err != nil {
log.Printf("[ERR] Error flushing to statsd! Err: %s", err)
goto WAIT
}
}
}
WAIT:
// Wait for a while
wait = time.After(time.Duration(5) * time.Second)
for {
select {
// Dequeue the messages to avoid backlog
case _, ok := <-s.metricQueue:
if !ok {
goto QUIT
}
case <-wait:
goto CONNECT
}
}
QUIT:
s.metricQueue = nil
}
================================================
FILE: vendor/github.com/armon/go-metrics/statsite.go
================================================
package metrics
import (
"bufio"
"fmt"
"log"
"net"
"net/url"
"strings"
"time"
)
const (
// We force flush the statsite metrics after this period of
// inactivity. Prevents stats from getting stuck in a buffer
// forever.
flushInterval = 100 * time.Millisecond
)
// NewStatsiteSinkFromURL creates an StatsiteSink from a URL. It is used
// (and tested) from NewMetricSinkFromURL.
func NewStatsiteSinkFromURL(u *url.URL) (MetricSink, error) {
return NewStatsiteSink(u.Host)
}
// StatsiteSink provides a MetricSink that can be used with a
// statsite metrics server
type StatsiteSink struct {
addr string
metricQueue chan string
}
// NewStatsiteSink is used to create a new StatsiteSink
func NewStatsiteSink(addr string) (*StatsiteSink, error) {
s := &StatsiteSink{
addr: addr,
metricQueue: make(chan string, 4096),
}
go s.flushMetrics()
return s, nil
}
// Close is used to stop flushing to statsite
func (s *StatsiteSink) Shutdown() {
close(s.metricQueue)
}
func (s *StatsiteSink) SetGauge(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
}
func (s *StatsiteSink) SetGaugeWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|g\n", flatKey, val))
}
func (s *StatsiteSink) EmitKey(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|kv\n", flatKey, val))
}
func (s *StatsiteSink) IncrCounter(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
}
func (s *StatsiteSink) IncrCounterWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|c\n", flatKey, val))
}
func (s *StatsiteSink) AddSample(key []string, val float32) {
flatKey := s.flattenKey(key)
s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
}
func (s *StatsiteSink) AddSampleWithLabels(key []string, val float32, labels []Label) {
flatKey := s.flattenKeyLabels(key, labels)
s.pushMetric(fmt.Sprintf("%s:%f|ms\n", flatKey, val))
}
// Flattens the key for formatting, removes spaces
func (s *StatsiteSink) flattenKey(parts []string) string {
joined := strings.Join(parts, ".")
return strings.Map(func(r rune) rune {
switch r {
case ':':
fallthrough
case ' ':
return '_'
default:
return r
}
}, joined)
}
// Flattens the key along with labels for formatting, removes spaces
func (s *StatsiteSink) flattenKeyLabels(parts []string, labels []Label) string {
for _, label := range labels {
parts = append(parts, label.Value)
}
return s.flattenKey(parts)
}
// Does a non-blocking push to the metrics queue
func (s *StatsiteSink) pushMetric(m string) {
select {
case s.metricQueue <- m:
default:
}
}
// Flushes metrics
func (s *StatsiteSink) flushMetrics() {
var sock net.Conn
var err error
var wait <-chan time.Time
var buffered *bufio.Writer
ticker := time.NewTicker(flushInterval)
defer ticker.Stop()
CONNECT:
// Attempt to connect
sock, err = net.Dial("tcp", s.addr)
if err != nil {
log.Printf("[ERR] Error connecting to statsite! Err: %s", err)
goto WAIT
}
// Create a buffered writer
buffered = bufio.NewWriter(sock)
for {
select {
case metric, ok := <-s.metricQueue:
// Get a metric from the queue
if !ok {
goto QUIT
}
// Try to send to statsite
_, err := buffered.Write([]byte(metric))
if err != nil {
log.Printf("[ERR] Error writing to statsite! Err: %s", err)
goto WAIT
}
case <-ticker.C:
if err := buffered.Flush(); err != nil {
log.Printf("[ERR] Error flushing to statsite! Err: %s", err)
goto WAIT
}
}
}
WAIT:
// Wait for a while
wait = time.After(time.Duration(5) * time.Second)
for {
select {
// Dequeue the messages to avoid backlog
case _, ok := <-s.metricQueue:
if !ok {
goto QUIT
}
case <-wait:
goto CONNECT
}
}
QUIT:
s.metricQueue = nil
}
================================================
FILE: vendor/github.com/armon/go-radix/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
================================================
FILE: vendor/github.com/armon/go-radix/.travis.yml
================================================
language: go
go:
- tip
================================================
FILE: vendor/github.com/armon/go-radix/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Armon Dadgar
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/armon/go-radix/README.md
================================================
go-radix [](https://travis-ci.org/armon/go-radix)
=========
Provides the `radix` package that implements a [radix tree](http://en.wikipedia.org/wiki/Radix_tree).
The package only provides a single `Tree` implementation, optimized for sparse nodes.
As a radix tree, it provides the following:
* O(k) operations. In many cases, this can be faster than a hash table since
the hash function is an O(k) operation, and hash tables have very poor cache locality.
* Minimum / Maximum value lookups
* Ordered iteration
For an immutable variant, see [go-immutable-radix](https://github.com/hashicorp/go-immutable-radix).
Documentation
=============
The full documentation is available on [Godoc](http://godoc.org/github.com/armon/go-radix).
Example
=======
Below is a simple example of usage
```go
// Create a tree
r := radix.New()
r.Insert("foo", 1)
r.Insert("bar", 2)
r.Insert("foobar", 2)
// Find the longest prefix match
m, _, _ := r.LongestPrefix("foozip")
if m != "foo" {
panic("should be foo")
}
```
================================================
FILE: vendor/github.com/armon/go-radix/radix.go
================================================
package radix
import (
"sort"
"strings"
)
// WalkFn is used when walking the tree. Takes a
// key and value, returning if iteration should
// be terminated.
type WalkFn func(s string, v interface{}) bool
// leafNode is used to represent a value
type leafNode struct {
key string
val interface{}
}
// edge is used to represent an edge node
type edge struct {
label byte
node *node
}
type node struct {
// leaf is used to store possible leaf
leaf *leafNode
// prefix is the common prefix we ignore
prefix string
// Edges should be stored in-order for iteration.
// We avoid a fully materialized slice to save memory,
// since in most cases we expect to be sparse
edges edges
}
func (n *node) isLeaf() bool {
return n.leaf != nil
}
func (n *node) addEdge(e edge) {
n.edges = append(n.edges, e)
n.edges.Sort()
}
func (n *node) updateEdge(label byte, node *node) {
num := len(n.edges)
idx := sort.Search(num, func(i int) bool {
return n.edges[i].label >= label
})
if idx < num && n.edges[idx].label == label {
n.edges[idx].node = node
return
}
panic("replacing missing edge")
}
func (n *node) getEdge(label byte) *node {
num := len(n.edges)
idx := sort.Search(num, func(i int) bool {
return n.edges[i].label >= label
})
if idx < num && n.edges[idx].label == label {
return n.edges[idx].node
}
return nil
}
func (n *node) delEdge(label byte) {
num := len(n.edges)
idx := sort.Search(num, func(i int) bool {
return n.edges[i].label >= label
})
if idx < num && n.edges[idx].label == label {
copy(n.edges[idx:], n.edges[idx+1:])
n.edges[len(n.edges)-1] = edge{}
n.edges = n.edges[:len(n.edges)-1]
}
}
type edges []edge
func (e edges) Len() int {
return len(e)
}
func (e edges) Less(i, j int) bool {
return e[i].label < e[j].label
}
func (e edges) Swap(i, j int) {
e[i], e[j] = e[j], e[i]
}
func (e edges) Sort() {
sort.Sort(e)
}
// Tree implements a radix tree. This can be treated as a
// Dictionary abstract data type. The main advantage over
// a standard hash map is prefix-based lookups and
// ordered iteration,
type Tree struct {
root *node
size int
}
// New returns an empty Tree
func New() *Tree {
return NewFromMap(nil)
}
// NewFromMap returns a new tree containing the keys
// from an existing map
func NewFromMap(m map[string]interface{}) *Tree {
t := &Tree{root: &node{}}
for k, v := range m {
t.Insert(k, v)
}
return t
}
// Len is used to return the number of elements in the tree
func (t *Tree) Len() int {
return t.size
}
// longestPrefix finds the length of the shared prefix
// of two strings
func longestPrefix(k1, k2 string) int {
max := len(k1)
if l := len(k2); l < max {
max = l
}
var i int
for i = 0; i < max; i++ {
if k1[i] != k2[i] {
break
}
}
return i
}
// Insert is used to add a newentry or update
// an existing entry. Returns if updated.
func (t *Tree) Insert(s string, v interface{}) (interface{}, bool) {
var parent *node
n := t.root
search := s
for {
// Handle key exhaution
if len(search) == 0 {
if n.isLeaf() {
old := n.leaf.val
n.leaf.val = v
return old, true
}
n.leaf = &leafNode{
key: s,
val: v,
}
t.size++
return nil, false
}
// Look for the edge
parent = n
n = n.getEdge(search[0])
// No edge, create one
if n == nil {
e := edge{
label: search[0],
node: &node{
leaf: &leafNode{
key: s,
val: v,
},
prefix: search,
},
}
parent.addEdge(e)
t.size++
return nil, false
}
// Determine longest prefix of the search key on match
commonPrefix := longestPrefix(search, n.prefix)
if commonPrefix == len(n.prefix) {
search = search[commonPrefix:]
continue
}
// Split the node
t.size++
child := &node{
prefix: search[:commonPrefix],
}
parent.updateEdge(search[0], child)
// Restore the existing node
child.addEdge(edge{
label: n.prefix[commonPrefix],
node: n,
})
n.prefix = n.prefix[commonPrefix:]
// Create a new leaf node
leaf := &leafNode{
key: s,
val: v,
}
// If the new key is a subset, add to to this node
search = search[commonPrefix:]
if len(search) == 0 {
child.leaf = leaf
return nil, false
}
// Create a new edge for the node
child.addEdge(edge{
label: search[0],
node: &node{
leaf: leaf,
prefix: search,
},
})
return nil, false
}
}
// Delete is used to delete a key, returning the previous
// value and if it was deleted
func (t *Tree) Delete(s string) (interface{}, bool) {
var parent *node
var label byte
n := t.root
search := s
for {
// Check for key exhaution
if len(search) == 0 {
if !n.isLeaf() {
break
}
goto DELETE
}
// Look for an edge
parent = n
label = search[0]
n = n.getEdge(label)
if n == nil {
break
}
// Consume the search prefix
if strings.HasPrefix(search, n.prefix) {
search = search[len(n.prefix):]
} else {
break
}
}
return nil, false
DELETE:
// Delete the leaf
leaf := n.leaf
n.leaf = nil
t.size--
// Check if we should delete this node from the parent
if parent != nil && len(n.edges) == 0 {
parent.delEdge(label)
}
// Check if we should merge this node
if n != t.root && len(n.edges) == 1 {
n.mergeChild()
}
// Check if we should merge the parent's other child
if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() {
parent.mergeChild()
}
return leaf.val, true
}
// DeletePrefix is used to delete the subtree under a prefix
// Returns how many nodes were deleted
// Use this to delete large subtrees efficiently
func (t *Tree) DeletePrefix(s string) int {
return t.deletePrefix(nil, t.root, s)
}
// delete does a recursive deletion
func (t *Tree) deletePrefix(parent, n *node, prefix string) int {
// Check for key exhaustion
if len(prefix) == 0 {
// Remove the leaf node
subTreeSize := 0
//recursively walk from all edges of the node to be deleted
recursiveWalk(n, func(s string, v interface{}) bool {
subTreeSize++
return false
})
if n.isLeaf() {
n.leaf = nil
}
n.edges = nil // deletes the entire subtree
// Check if we should merge the parent's other child
if parent != nil && parent != t.root && len(parent.edges) == 1 && !parent.isLeaf() {
parent.mergeChild()
}
t.size -= subTreeSize
return subTreeSize
}
// Look for an edge
label := prefix[0]
child := n.getEdge(label)
if child == nil || (!strings.HasPrefix(child.prefix, prefix) && !strings.HasPrefix(prefix, child.prefix)) {
return 0
}
// Consume the search prefix
if len(child.prefix) > len(prefix) {
prefix = prefix[len(prefix):]
} else {
prefix = prefix[len(child.prefix):]
}
return t.deletePrefix(n, child, prefix)
}
func (n *node) mergeChild() {
e := n.edges[0]
child := e.node
n.prefix = n.prefix + child.prefix
n.leaf = child.leaf
n.edges = child.edges
}
// Get is used to lookup a specific key, returning
// the value and if it was found
func (t *Tree) Get(s string) (interface{}, bool) {
n := t.root
search := s
for {
// Check for key exhaution
if len(search) == 0 {
if n.isLeaf() {
return n.leaf.val, true
}
break
}
// Look for an edge
n = n.getEdge(search[0])
if n == nil {
break
}
// Consume the search prefix
if strings.HasPrefix(search, n.prefix) {
search = search[len(n.prefix):]
} else {
break
}
}
return nil, false
}
// LongestPrefix is like Get, but instead of an
// exact match, it will return the longest prefix match.
func (t *Tree) LongestPrefix(s string) (string, interface{}, bool) {
var last *leafNode
n := t.root
search := s
for {
// Look for a leaf node
if n.isLeaf() {
last = n.leaf
}
// Check for key exhaution
if len(search) == 0 {
break
}
// Look for an edge
n = n.getEdge(search[0])
if n == nil {
break
}
// Consume the search prefix
if strings.HasPrefix(search, n.prefix) {
search = search[len(n.prefix):]
} else {
break
}
}
if last != nil {
return last.key, last.val, true
}
return "", nil, false
}
// Minimum is used to return the minimum value in the tree
func (t *Tree) Minimum() (string, interface{}, bool) {
n := t.root
for {
if n.isLeaf() {
return n.leaf.key, n.leaf.val, true
}
if len(n.edges) > 0 {
n = n.edges[0].node
} else {
break
}
}
return "", nil, false
}
// Maximum is used to return the maximum value in the tree
func (t *Tree) Maximum() (string, interface{}, bool) {
n := t.root
for {
if num := len(n.edges); num > 0 {
n = n.edges[num-1].node
continue
}
if n.isLeaf() {
return n.leaf.key, n.leaf.val, true
}
break
}
return "", nil, false
}
// Walk is used to walk the tree
func (t *Tree) Walk(fn WalkFn) {
recursiveWalk(t.root, fn)
}
// WalkPrefix is used to walk the tree under a prefix
func (t *Tree) WalkPrefix(prefix string, fn WalkFn) {
n := t.root
search := prefix
for {
// Check for key exhaution
if len(search) == 0 {
recursiveWalk(n, fn)
return
}
// Look for an edge
n = n.getEdge(search[0])
if n == nil {
break
}
// Consume the search prefix
if strings.HasPrefix(search, n.prefix) {
search = search[len(n.prefix):]
} else if strings.HasPrefix(n.prefix, search) {
// Child may be under our search prefix
recursiveWalk(n, fn)
return
} else {
break
}
}
}
// WalkPath is used to walk the tree, but only visiting nodes
// from the root down to a given leaf. Where WalkPrefix walks
// all the entries *under* the given prefix, this walks the
// entries *above* the given prefix.
func (t *Tree) WalkPath(path string, fn WalkFn) {
n := t.root
search := path
for {
// Visit the leaf values if any
if n.leaf != nil && fn(n.leaf.key, n.leaf.val) {
return
}
// Check for key exhaution
if len(search) == 0 {
return
}
// Look for an edge
n = n.getEdge(search[0])
if n == nil {
return
}
// Consume the search prefix
if strings.HasPrefix(search, n.prefix) {
search = search[len(n.prefix):]
} else {
break
}
}
}
// recursiveWalk is used to do a pre-order walk of a node
// recursively. Returns true if the walk should be aborted
func recursiveWalk(n *node, fn WalkFn) bool {
// Visit the leaf values if any
if n.leaf != nil && fn(n.leaf.key, n.leaf.val) {
return true
}
// Recurse on the children
for _, e := range n.edges {
if recursiveWalk(e.node, fn) {
return true
}
}
return false
}
// ToMap is used to walk the tree and convert it into a map
func (t *Tree) ToMap() map[string]interface{} {
out := make(map[string]interface{}, t.size)
t.Walk(func(k string, v interface{}) bool {
out[k] = v
return false
})
return out
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/LICENSE.txt
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: vendor/github.com/aws/aws-sdk-go/NOTICE.txt
================================================
AWS SDK for Go
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
Copyright 2014-2015 Stripe, Inc.
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awserr/error.go
================================================
// Package awserr represents API error interface accessors for the SDK.
package awserr
// An Error wraps lower level errors with code, message and an original error.
// The underlying concrete error type may also satisfy other interfaces which
// can be to used to obtain more specific information about the error.
//
// Calling Error() or String() will always include the full information about
// an error based on its underlying type.
//
// Example:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if awsErr, ok := err.(awserr.Error); ok {
// // Get error details
// log.Println("Error:", awsErr.Code(), awsErr.Message())
//
// // Prints out full error message, including original error if there was one.
// log.Println("Error:", awsErr.Error())
//
// // Get original error
// if origErr := awsErr.OrigErr(); origErr != nil {
// // operate on original error.
// }
// } else {
// fmt.Println(err.Error())
// }
// }
//
type Error interface {
// Satisfy the generic error interface.
error
// Returns the short phrase depicting the classification of the error.
Code() string
// Returns the error details message.
Message() string
// Returns the original error if one was set. Nil is returned if not set.
OrigErr() error
}
// BatchError is a batch of errors which also wraps lower level errors with
// code, message, and original errors. Calling Error() will include all errors
// that occurred in the batch.
//
// Deprecated: Replaced with BatchedErrors. Only defined for backwards
// compatibility.
type BatchError interface {
// Satisfy the generic error interface.
error
// Returns the short phrase depicting the classification of the error.
Code() string
// Returns the error details message.
Message() string
// Returns the original error if one was set. Nil is returned if not set.
OrigErrs() []error
}
// BatchedErrors is a batch of errors which also wraps lower level errors with
// code, message, and original errors. Calling Error() will include all errors
// that occurred in the batch.
//
// Replaces BatchError
type BatchedErrors interface {
// Satisfy the base Error interface.
Error
// Returns the original error if one was set. Nil is returned if not set.
OrigErrs() []error
}
// New returns an Error object described by the code, message, and origErr.
//
// If origErr satisfies the Error interface it will not be wrapped within a new
// Error object and will instead be returned.
func New(code, message string, origErr error) Error {
var errs []error
if origErr != nil {
errs = append(errs, origErr)
}
return newBaseError(code, message, errs)
}
// NewBatchError returns an BatchedErrors with a collection of errors as an
// array of errors.
func NewBatchError(code, message string, errs []error) BatchedErrors {
return newBaseError(code, message, errs)
}
// A RequestFailure is an interface to extract request failure information from
// an Error such as the request ID of the failed request returned by a service.
// RequestFailures may not always have a requestID value if the request failed
// prior to reaching the service such as a connection error.
//
// Example:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if reqerr, ok := err.(RequestFailure); ok {
// log.Println("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
// } else {
// log.Println("Error:", err.Error())
// }
// }
//
// Combined with awserr.Error:
//
// output, err := s3manage.Upload(svc, input, opts)
// if err != nil {
// if awsErr, ok := err.(awserr.Error); ok {
// // Generic AWS Error with Code, Message, and original error (if any)
// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
//
// if reqErr, ok := err.(awserr.RequestFailure); ok {
// // A service error occurred
// fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
// }
// } else {
// fmt.Println(err.Error())
// }
// }
//
type RequestFailure interface {
Error
// The status code of the HTTP response.
StatusCode() int
// The request ID returned by the service for a request failure. This will
// be empty if no request ID is available such as the request failed due
// to a connection error.
RequestID() string
}
// NewRequestFailure returns a wrapped error with additional information for
// request status code, and service requestID.
//
// Should be used to wrap all request which involve service requests. Even if
// the request failed without a service response, but had an HTTP status code
// that may be meaningful.
func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure {
return newRequestError(err, statusCode, reqID)
}
// UnmarshalError provides the interface for the SDK failing to unmarshal data.
type UnmarshalError interface {
awsError
Bytes() []byte
}
// NewUnmarshalError returns an initialized UnmarshalError error wrapper adding
// the bytes that fail to unmarshal to the error.
func NewUnmarshalError(err error, msg string, bytes []byte) UnmarshalError {
return &unmarshalError{
awsError: New("UnmarshalError", msg, err),
bytes: bytes,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awserr/types.go
================================================
package awserr
import (
"encoding/hex"
"fmt"
)
// SprintError returns a string of the formatted error code.
//
// Both extra and origErr are optional. If they are included their lines
// will be added, but if they are not included their lines will be ignored.
func SprintError(code, message, extra string, origErr error) string {
msg := fmt.Sprintf("%s: %s", code, message)
if extra != "" {
msg = fmt.Sprintf("%s\n\t%s", msg, extra)
}
if origErr != nil {
msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error())
}
return msg
}
// A baseError wraps the code and message which defines an error. It also
// can be used to wrap an original error object.
//
// Should be used as the root for errors satisfying the awserr.Error. Also
// for any error which does not fit into a specific error wrapper type.
type baseError struct {
// Classification of error
code string
// Detailed information about error
message string
// Optional original error this error is based off of. Allows building
// chained errors.
errs []error
}
// newBaseError returns an error object for the code, message, and errors.
//
// code is a short no whitespace phrase depicting the classification of
// the error that is being created.
//
// message is the free flow string containing detailed information about the
// error.
//
// origErrs is the error objects which will be nested under the new errors to
// be returned.
func newBaseError(code, message string, origErrs []error) *baseError {
b := &baseError{
code: code,
message: message,
errs: origErrs,
}
return b
}
// Error returns the string representation of the error.
//
// See ErrorWithExtra for formatting.
//
// Satisfies the error interface.
func (b baseError) Error() string {
size := len(b.errs)
if size > 0 {
return SprintError(b.code, b.message, "", errorList(b.errs))
}
return SprintError(b.code, b.message, "", nil)
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (b baseError) String() string {
return b.Error()
}
// Code returns the short phrase depicting the classification of the error.
func (b baseError) Code() string {
return b.code
}
// Message returns the error details message.
func (b baseError) Message() string {
return b.message
}
// OrigErr returns the original error if one was set. Nil is returned if no
// error was set. This only returns the first element in the list. If the full
// list is needed, use BatchedErrors.
func (b baseError) OrigErr() error {
switch len(b.errs) {
case 0:
return nil
case 1:
return b.errs[0]
default:
if err, ok := b.errs[0].(Error); ok {
return NewBatchError(err.Code(), err.Message(), b.errs[1:])
}
return NewBatchError("BatchedErrors",
"multiple errors occurred", b.errs)
}
}
// OrigErrs returns the original errors if one was set. An empty slice is
// returned if no error was set.
func (b baseError) OrigErrs() []error {
return b.errs
}
// So that the Error interface type can be included as an anonymous field
// in the requestError struct and not conflict with the error.Error() method.
type awsError Error
// A requestError wraps a request or service error.
//
// Composed of baseError for code, message, and original error.
type requestError struct {
awsError
statusCode int
requestID string
bytes []byte
}
// newRequestError returns a wrapped error with additional information for
// request status code, and service requestID.
//
// Should be used to wrap all request which involve service requests. Even if
// the request failed without a service response, but had an HTTP status code
// that may be meaningful.
//
// Also wraps original errors via the baseError.
func newRequestError(err Error, statusCode int, requestID string) *requestError {
return &requestError{
awsError: err,
statusCode: statusCode,
requestID: requestID,
}
}
// Error returns the string representation of the error.
// Satisfies the error interface.
func (r requestError) Error() string {
extra := fmt.Sprintf("status code: %d, request id: %s",
r.statusCode, r.requestID)
return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (r requestError) String() string {
return r.Error()
}
// StatusCode returns the wrapped status code for the error
func (r requestError) StatusCode() int {
return r.statusCode
}
// RequestID returns the wrapped requestID
func (r requestError) RequestID() string {
return r.requestID
}
// OrigErrs returns the original errors if one was set. An empty slice is
// returned if no error was set.
func (r requestError) OrigErrs() []error {
if b, ok := r.awsError.(BatchedErrors); ok {
return b.OrigErrs()
}
return []error{r.OrigErr()}
}
type unmarshalError struct {
awsError
bytes []byte
}
// Error returns the string representation of the error.
// Satisfies the error interface.
func (e unmarshalError) Error() string {
extra := hex.Dump(e.bytes)
return SprintError(e.Code(), e.Message(), extra, e.OrigErr())
}
// String returns the string representation of the error.
// Alias for Error to satisfy the stringer interface.
func (e unmarshalError) String() string {
return e.Error()
}
// Bytes returns the bytes that failed to unmarshal.
func (e unmarshalError) Bytes() []byte {
return e.bytes
}
// An error list that satisfies the golang interface
type errorList []error
// Error returns the string representation of the error.
//
// Satisfies the error interface.
func (e errorList) Error() string {
msg := ""
// How do we want to handle the array size being zero
if size := len(e); size > 0 {
for i := 0; i < size; i++ {
msg += e[i].Error()
// We check the next index to see if it is within the slice.
// If it is, then we append a newline. We do this, because unit tests
// could be broken with the additional '\n'
if i+1 < size {
msg += "\n"
}
}
}
return msg
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
================================================
package awsutil
import (
"io"
"reflect"
"time"
)
// Copy deeply copies a src structure to dst. Useful for copying request and
// response structures.
//
// Can copy between structs of different type, but will only copy fields which
// are assignable, and exist in both structs. Fields which are not assignable,
// or do not exist in both structs are ignored.
func Copy(dst, src interface{}) {
dstval := reflect.ValueOf(dst)
if !dstval.IsValid() {
panic("Copy dst cannot be nil")
}
rcopy(dstval, reflect.ValueOf(src), true)
}
// CopyOf returns a copy of src while also allocating the memory for dst.
// src must be a pointer type or this operation will fail.
func CopyOf(src interface{}) (dst interface{}) {
dsti := reflect.New(reflect.TypeOf(src).Elem())
dst = dsti.Interface()
rcopy(dsti, reflect.ValueOf(src), true)
return
}
// rcopy performs a recursive copy of values from the source to destination.
//
// root is used to skip certain aspects of the copy which are not valid
// for the root node of a object.
func rcopy(dst, src reflect.Value, root bool) {
if !src.IsValid() {
return
}
switch src.Kind() {
case reflect.Ptr:
if _, ok := src.Interface().(io.Reader); ok {
if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() {
dst.Elem().Set(src)
} else if dst.CanSet() {
dst.Set(src)
}
} else {
e := src.Type().Elem()
if dst.CanSet() && !src.IsNil() {
if _, ok := src.Interface().(*time.Time); !ok {
dst.Set(reflect.New(e))
} else {
tempValue := reflect.New(e)
tempValue.Elem().Set(src.Elem())
// Sets time.Time's unexported values
dst.Set(tempValue)
}
}
if src.Elem().IsValid() {
// Keep the current root state since the depth hasn't changed
rcopy(dst.Elem(), src.Elem(), root)
}
}
case reflect.Struct:
t := dst.Type()
for i := 0; i < t.NumField(); i++ {
name := t.Field(i).Name
srcVal := src.FieldByName(name)
dstVal := dst.FieldByName(name)
if srcVal.IsValid() && dstVal.CanSet() {
rcopy(dstVal, srcVal, false)
}
}
case reflect.Slice:
if src.IsNil() {
break
}
s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
dst.Set(s)
for i := 0; i < src.Len(); i++ {
rcopy(dst.Index(i), src.Index(i), false)
}
case reflect.Map:
if src.IsNil() {
break
}
s := reflect.MakeMap(src.Type())
dst.Set(s)
for _, k := range src.MapKeys() {
v := src.MapIndex(k)
v2 := reflect.New(v.Type()).Elem()
rcopy(v2, v, false)
dst.SetMapIndex(k, v2)
}
default:
// Assign the value if possible. If its not assignable, the value would
// need to be converted and the impact of that may be unexpected, or is
// not compatible with the dst type.
if src.Type().AssignableTo(dst.Type()) {
dst.Set(src)
}
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
================================================
package awsutil
import (
"reflect"
)
// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual.
// In addition to this, this method will also dereference the input values if
// possible so the DeepEqual performed will not fail if one parameter is a
// pointer and the other is not.
//
// DeepEqual will not perform indirection of nested values of the input parameters.
func DeepEqual(a, b interface{}) bool {
ra := reflect.Indirect(reflect.ValueOf(a))
rb := reflect.Indirect(reflect.ValueOf(b))
if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid {
// If the elements are both nil, and of the same type they are equal
// If they are of different types they are not equal
return reflect.TypeOf(a) == reflect.TypeOf(b)
} else if raValid != rbValid {
// Both values must be valid to be equal
return false
}
return reflect.DeepEqual(ra.Interface(), rb.Interface())
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
================================================
package awsutil
import (
"reflect"
"regexp"
"strconv"
"strings"
"github.com/jmespath/go-jmespath"
)
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
// rValuesAtPath returns a slice of values found in value v. The values
// in v are explored recursively so all nested values are collected.
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
pathparts := strings.Split(path, "||")
if len(pathparts) > 1 {
for _, pathpart := range pathparts {
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
if len(vals) > 0 {
return vals
}
}
return nil
}
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
components := strings.Split(path, ".")
for len(values) > 0 && len(components) > 0 {
var index *int64
var indexStar bool
c := strings.TrimSpace(components[0])
if c == "" { // no actual component, illegal syntax
return nil
} else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
// TODO normalize case for user
return nil // don't support unexported fields
}
// parse this component
if m := indexRe.FindStringSubmatch(c); m != nil {
c = m[1]
if m[2] == "" {
index = nil
indexStar = true
} else {
i, _ := strconv.ParseInt(m[2], 10, 32)
index = &i
indexStar = false
}
}
nextvals := []reflect.Value{}
for _, value := range values {
// pull component name out of struct member
if value.Kind() != reflect.Struct {
continue
}
if c == "*" { // pull all members
for i := 0; i < value.NumField(); i++ {
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
nextvals = append(nextvals, f)
}
}
continue
}
value = value.FieldByNameFunc(func(name string) bool {
if c == name {
return true
} else if !caseSensitive && strings.EqualFold(name, c) {
return true
}
return false
})
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
if !value.IsNil() {
value.Set(reflect.Zero(value.Type()))
}
return []reflect.Value{value}
}
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
// TODO if the value is the terminus it should not be created
// if the value to be set to its position is nil.
value.Set(reflect.New(value.Type().Elem()))
value = value.Elem()
} else {
value = reflect.Indirect(value)
}
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
if !createPath && value.IsNil() {
value = reflect.ValueOf(nil)
}
}
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
if indexStar || index != nil {
nextvals = []reflect.Value{}
for _, valItem := range values {
value := reflect.Indirect(valItem)
if value.Kind() != reflect.Slice {
continue
}
if indexStar { // grab all indices
for i := 0; i < value.Len(); i++ {
idx := reflect.Indirect(value.Index(i))
if idx.IsValid() {
nextvals = append(nextvals, idx)
}
}
continue
}
// pull out index
i := int(*index)
if i >= value.Len() { // check out of bounds
if createPath {
// TODO resize slice
} else {
continue
}
} else if i < 0 { // support negative indexing
i = value.Len() + i
}
value = reflect.Indirect(value.Index(i))
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
if !createPath && value.IsNil() {
value = reflect.ValueOf(nil)
}
}
if value.IsValid() {
nextvals = append(nextvals, value)
}
}
values = nextvals
}
components = components[1:]
}
return values
}
// ValuesAtPath returns a list of values at the case insensitive lexical
// path inside of a structure.
func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
result, err := jmespath.Search(path, i)
if err != nil {
return nil, err
}
v := reflect.ValueOf(result)
if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
return nil, nil
}
if s, ok := result.([]interface{}); ok {
return s, err
}
if v.Kind() == reflect.Map && v.Len() == 0 {
return nil, nil
}
if v.Kind() == reflect.Slice {
out := make([]interface{}, v.Len())
for i := 0; i < v.Len(); i++ {
out[i] = v.Index(i).Interface()
}
return out, nil
}
return []interface{}{result}, nil
}
// SetValueAtPath sets a value at the case insensitive lexical path inside
// of a structure.
func SetValueAtPath(i interface{}, path string, v interface{}) {
rvals := rValuesAtPath(i, path, true, false, v == nil)
for _, rval := range rvals {
if rval.Kind() == reflect.Ptr && rval.IsNil() {
continue
}
setValue(rval, v)
}
}
func setValue(dstVal reflect.Value, src interface{}) {
if dstVal.Kind() == reflect.Ptr {
dstVal = reflect.Indirect(dstVal)
}
srcVal := reflect.ValueOf(src)
if !srcVal.IsValid() { // src is literal nil
if dstVal.CanAddr() {
// Convert to pointer so that pointer's value can be nil'ed
// dstVal = dstVal.Addr()
}
dstVal.Set(reflect.Zero(dstVal.Type()))
} else if srcVal.Kind() == reflect.Ptr {
if srcVal.IsNil() {
srcVal = reflect.Zero(dstVal.Type())
} else {
srcVal = reflect.ValueOf(src).Elem()
}
dstVal.Set(srcVal)
} else {
dstVal.Set(srcVal)
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
================================================
package awsutil
import (
"bytes"
"fmt"
"io"
"reflect"
"strings"
)
// Prettify returns the string representation of a value.
func Prettify(i interface{}) string {
var buf bytes.Buffer
prettify(reflect.ValueOf(i), 0, &buf)
return buf.String()
}
// prettify will recursively walk value v to build a textual
// representation of the value.
func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
strtype := v.Type().String()
if strtype == "time.Time" {
fmt.Fprintf(buf, "%s", v.Interface())
break
} else if strings.HasPrefix(strtype, "io.") {
buf.WriteString("")
break
}
buf.WriteString("{\n")
names := []string{}
for i := 0; i < v.Type().NumField(); i++ {
name := v.Type().Field(i).Name
f := v.Field(i)
if name[0:1] == strings.ToLower(name[0:1]) {
continue // ignore unexported fields
}
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
continue // ignore unset fields
}
names = append(names, name)
}
for i, n := range names {
val := v.FieldByName(n)
ft, ok := v.Type().FieldByName(n)
if !ok {
panic(fmt.Sprintf("expected to find field %v on type %v, but was not found", n, v.Type()))
}
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(n + ": ")
if tag := ft.Tag.Get("sensitive"); tag == "true" {
buf.WriteString("")
} else {
prettify(val, indent+2, buf)
}
if i < len(names)-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
case reflect.Slice:
strtype := v.Type().String()
if strtype == "[]uint8" {
fmt.Fprintf(buf, " len %d", v.Len())
break
}
nl, id, id2 := "", "", ""
if v.Len() > 3 {
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
}
buf.WriteString("[" + nl)
for i := 0; i < v.Len(); i++ {
buf.WriteString(id2)
prettify(v.Index(i), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString("," + nl)
}
}
buf.WriteString(nl + id + "]")
case reflect.Map:
buf.WriteString("{\n")
for i, k := range v.MapKeys() {
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(k.String() + ": ")
prettify(v.MapIndex(k), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
default:
if !v.IsValid() {
fmt.Fprint(buf, "")
return
}
format := "%v"
switch v.Interface().(type) {
case string:
format = "%q"
case io.ReadSeeker, io.Reader:
format = "buffer(%p)"
}
fmt.Fprintf(buf, format, v.Interface())
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
================================================
package awsutil
import (
"bytes"
"fmt"
"reflect"
"strings"
)
// StringValue returns the string representation of a value.
//
// Deprecated: Use Prettify instead.
func StringValue(i interface{}) string {
var buf bytes.Buffer
stringValue(reflect.ValueOf(i), 0, &buf)
return buf.String()
}
func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
switch v.Kind() {
case reflect.Struct:
buf.WriteString("{\n")
for i := 0; i < v.Type().NumField(); i++ {
ft := v.Type().Field(i)
fv := v.Field(i)
if ft.Name[0:1] == strings.ToLower(ft.Name[0:1]) {
continue // ignore unexported fields
}
if (fv.Kind() == reflect.Ptr || fv.Kind() == reflect.Slice) && fv.IsNil() {
continue // ignore unset fields
}
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(ft.Name + ": ")
if tag := ft.Tag.Get("sensitive"); tag == "true" {
buf.WriteString("")
} else {
stringValue(fv, indent+2, buf)
}
buf.WriteString(",\n")
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
case reflect.Slice:
nl, id, id2 := "", "", ""
if v.Len() > 3 {
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
}
buf.WriteString("[" + nl)
for i := 0; i < v.Len(); i++ {
buf.WriteString(id2)
stringValue(v.Index(i), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString("," + nl)
}
}
buf.WriteString(nl + id + "]")
case reflect.Map:
buf.WriteString("{\n")
for i, k := range v.MapKeys() {
buf.WriteString(strings.Repeat(" ", indent+2))
buf.WriteString(k.String() + ": ")
stringValue(v.MapIndex(k), indent+2, buf)
if i < v.Len()-1 {
buf.WriteString(",\n")
}
}
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
default:
format := "%v"
switch v.Interface().(type) {
case string:
format = "%q"
}
fmt.Fprintf(buf, format, v.Interface())
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/client/client.go
================================================
package client
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
)
// A Config provides configuration to a service client instance.
type Config struct {
Config *aws.Config
Handlers request.Handlers
PartitionID string
Endpoint string
SigningRegion string
SigningName string
ResolvedRegion string
// States that the signing name did not come from a modeled source but
// was derived based on other data. Used by service client constructors
// to determine if the signin name can be overridden based on metadata the
// service has.
SigningNameDerived bool
}
// ConfigProvider provides a generic way for a service client to receive
// the ClientConfig without circular dependencies.
type ConfigProvider interface {
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
}
// ConfigNoResolveEndpointProvider same as ConfigProvider except it will not
// resolve the endpoint automatically. The service client's endpoint must be
// provided via the aws.Config.Endpoint field.
type ConfigNoResolveEndpointProvider interface {
ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) Config
}
// A Client implements the base client request and response handling
// used by all service clients.
type Client struct {
request.Retryer
metadata.ClientInfo
Config aws.Config
Handlers request.Handlers
}
// New will return a pointer to a new initialized service client.
func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
svc := &Client{
Config: cfg,
ClientInfo: info,
Handlers: handlers.Copy(),
}
switch retryer, ok := cfg.Retryer.(request.Retryer); {
case ok:
svc.Retryer = retryer
case cfg.Retryer != nil && cfg.Logger != nil:
s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
cfg.Logger.Log(s)
fallthrough
default:
maxRetries := aws.IntValue(cfg.MaxRetries)
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
maxRetries = DefaultRetryerMaxNumRetries
}
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
}
svc.AddDebugHandlers()
for _, option := range options {
option(svc)
}
return svc
}
// NewRequest returns a new Request pointer for the service API
// operation and parameters.
func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
}
// AddDebugHandlers injects debug logging handlers into the service to log request
// debug information.
func (c *Client) AddDebugHandlers() {
c.Handlers.Send.PushFrontNamed(LogHTTPRequestHandler)
c.Handlers.Send.PushBackNamed(LogHTTPResponseHandler)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
================================================
package client
import (
"math"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkrand"
)
// DefaultRetryer implements basic retry logic using exponential backoff for
// most services. If you want to implement custom retry logic, you can implement the
// request.Retryer interface.
//
type DefaultRetryer struct {
// Num max Retries is the number of max retries that will be performed.
// By default, this is zero.
NumMaxRetries int
// MinRetryDelay is the minimum retry delay after which retry will be performed.
// If not set, the value is 0ns.
MinRetryDelay time.Duration
// MinThrottleRetryDelay is the minimum retry delay when throttled.
// If not set, the value is 0ns.
MinThrottleDelay time.Duration
// MaxRetryDelay is the maximum retry delay before which retry must be performed.
// If not set, the value is 0ns.
MaxRetryDelay time.Duration
// MaxThrottleDelay is the maximum retry delay when throttled.
// If not set, the value is 0ns.
MaxThrottleDelay time.Duration
}
const (
// DefaultRetryerMaxNumRetries sets maximum number of retries
DefaultRetryerMaxNumRetries = 3
// DefaultRetryerMinRetryDelay sets minimum retry delay
DefaultRetryerMinRetryDelay = 30 * time.Millisecond
// DefaultRetryerMinThrottleDelay sets minimum delay when throttled
DefaultRetryerMinThrottleDelay = 500 * time.Millisecond
// DefaultRetryerMaxRetryDelay sets maximum retry delay
DefaultRetryerMaxRetryDelay = 300 * time.Second
// DefaultRetryerMaxThrottleDelay sets maximum delay when throttled
DefaultRetryerMaxThrottleDelay = 300 * time.Second
)
// MaxRetries returns the number of maximum returns the service will use to make
// an individual API request.
func (d DefaultRetryer) MaxRetries() int {
return d.NumMaxRetries
}
// setRetryerDefaults sets the default values of the retryer if not set
func (d *DefaultRetryer) setRetryerDefaults() {
if d.MinRetryDelay == 0 {
d.MinRetryDelay = DefaultRetryerMinRetryDelay
}
if d.MaxRetryDelay == 0 {
d.MaxRetryDelay = DefaultRetryerMaxRetryDelay
}
if d.MinThrottleDelay == 0 {
d.MinThrottleDelay = DefaultRetryerMinThrottleDelay
}
if d.MaxThrottleDelay == 0 {
d.MaxThrottleDelay = DefaultRetryerMaxThrottleDelay
}
}
// RetryRules returns the delay duration before retrying this request again
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
// if number of max retries is zero, no retries will be performed.
if d.NumMaxRetries == 0 {
return 0
}
// Sets default value for retryer members
d.setRetryerDefaults()
// minDelay is the minimum retryer delay
minDelay := d.MinRetryDelay
var initialDelay time.Duration
isThrottle := r.IsErrorThrottle()
if isThrottle {
if delay, ok := getRetryAfterDelay(r); ok {
initialDelay = delay
}
minDelay = d.MinThrottleDelay
}
retryCount := r.RetryCount
// maxDelay the maximum retryer delay
maxDelay := d.MaxRetryDelay
if isThrottle {
maxDelay = d.MaxThrottleDelay
}
var delay time.Duration
// Logic to cap the retry count based on the minDelay provided
actualRetryCount := int(math.Log2(float64(minDelay))) + 1
if actualRetryCount < 63-retryCount {
delay = time.Duration(1< maxDelay {
delay = getJitterDelay(maxDelay / 2)
}
} else {
delay = getJitterDelay(maxDelay / 2)
}
return delay + initialDelay
}
// getJitterDelay returns a jittered delay for retry
func getJitterDelay(duration time.Duration) time.Duration {
return time.Duration(sdkrand.SeededRand.Int63n(int64(duration)) + int64(duration))
}
// ShouldRetry returns true if the request should be retried.
func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
// ShouldRetry returns false if number of max retries is 0.
if d.NumMaxRetries == 0 {
return false
}
// If one of the other handlers already set the retry state
// we don't want to override it based on the service's state
if r.Retryable != nil {
return *r.Retryable
}
return r.IsErrorRetryable() || r.IsErrorThrottle()
}
// This will look in the Retry-After header, RFC 7231, for how long
// it will wait before attempting another request
func getRetryAfterDelay(r *request.Request) (time.Duration, bool) {
if !canUseRetryAfterHeader(r) {
return 0, false
}
delayStr := r.HTTPResponse.Header.Get("Retry-After")
if len(delayStr) == 0 {
return 0, false
}
delay, err := strconv.Atoi(delayStr)
if err != nil {
return 0, false
}
return time.Duration(delay) * time.Second, true
}
// Will look at the status code to see if the retry header pertains to
// the status code.
func canUseRetryAfterHeader(r *request.Request) bool {
switch r.HTTPResponse.StatusCode {
case 429:
case 503:
default:
return false
}
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/client/logger.go
================================================
package client
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http/httputil"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
)
const logReqMsg = `DEBUG: Request %s/%s Details:
---[ REQUEST POST-SIGN ]-----------------------------
%s
-----------------------------------------------------`
const logReqErrMsg = `DEBUG ERROR: Request %s/%s:
---[ REQUEST DUMP ERROR ]-----------------------------
%s
------------------------------------------------------`
type logWriter struct {
// Logger is what we will use to log the payload of a response.
Logger aws.Logger
// buf stores the contents of what has been read
buf *bytes.Buffer
}
func (logger *logWriter) Write(b []byte) (int, error) {
return logger.buf.Write(b)
}
type teeReaderCloser struct {
// io.Reader will be a tee reader that is used during logging.
// This structure will read from a body and write the contents to a logger.
io.Reader
// Source is used just to close when we are done reading.
Source io.ReadCloser
}
func (reader *teeReaderCloser) Close() error {
return reader.Source.Close()
}
// LogHTTPRequestHandler is a SDK request handler to log the HTTP request sent
// to a service. Will include the HTTP request body if the LogLevel of the
// request matches LogDebugWithHTTPBody.
var LogHTTPRequestHandler = request.NamedHandler{
Name: "awssdk.client.LogRequest",
Fn: logRequest,
}
func logRequest(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
bodySeekable := aws.IsReaderSeekable(r.Body)
b, err := httputil.DumpRequestOut(r.HTTPRequest, logBody)
if err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, err))
return
}
if logBody {
if !bodySeekable {
r.SetReaderBody(aws.ReadSeekCloser(r.HTTPRequest.Body))
}
// Reset the request body because dumpRequest will re-wrap the
// r.HTTPRequest's Body as a NoOpCloser and will not be reset after
// read by the HTTP client reader.
if err := r.Error; err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, err))
return
}
}
r.Config.Logger.Log(fmt.Sprintf(logReqMsg,
r.ClientInfo.ServiceName, r.Operation.Name, string(b)))
}
// LogHTTPRequestHeaderHandler is a SDK request handler to log the HTTP request sent
// to a service. Will only log the HTTP request's headers. The request payload
// will not be read.
var LogHTTPRequestHeaderHandler = request.NamedHandler{
Name: "awssdk.client.LogRequestHeader",
Fn: logRequestHeader,
}
func logRequestHeader(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
b, err := httputil.DumpRequestOut(r.HTTPRequest, false)
if err != nil {
r.Config.Logger.Log(fmt.Sprintf(logReqErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, err))
return
}
r.Config.Logger.Log(fmt.Sprintf(logReqMsg,
r.ClientInfo.ServiceName, r.Operation.Name, string(b)))
}
const logRespMsg = `DEBUG: Response %s/%s Details:
---[ RESPONSE ]--------------------------------------
%s
-----------------------------------------------------`
const logRespErrMsg = `DEBUG ERROR: Response %s/%s:
---[ RESPONSE DUMP ERROR ]-----------------------------
%s
-----------------------------------------------------`
// LogHTTPResponseHandler is a SDK request handler to log the HTTP response
// received from a service. Will include the HTTP response body if the LogLevel
// of the request matches LogDebugWithHTTPBody.
var LogHTTPResponseHandler = request.NamedHandler{
Name: "awssdk.client.LogResponse",
Fn: logResponse,
}
func logResponse(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
lw := &logWriter{r.Config.Logger, bytes.NewBuffer(nil)}
if r.HTTPResponse == nil {
lw.Logger.Log(fmt.Sprintf(logRespErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, "request's HTTPResponse is nil"))
return
}
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
if logBody {
r.HTTPResponse.Body = &teeReaderCloser{
Reader: io.TeeReader(r.HTTPResponse.Body, lw),
Source: r.HTTPResponse.Body,
}
}
handlerFn := func(req *request.Request) {
b, err := httputil.DumpResponse(req.HTTPResponse, false)
if err != nil {
lw.Logger.Log(fmt.Sprintf(logRespErrMsg,
req.ClientInfo.ServiceName, req.Operation.Name, err))
return
}
lw.Logger.Log(fmt.Sprintf(logRespMsg,
req.ClientInfo.ServiceName, req.Operation.Name, string(b)))
if logBody {
b, err := ioutil.ReadAll(lw.buf)
if err != nil {
lw.Logger.Log(fmt.Sprintf(logRespErrMsg,
req.ClientInfo.ServiceName, req.Operation.Name, err))
return
}
lw.Logger.Log(string(b))
}
}
const handlerName = "awsdk.client.LogResponse.ResponseBody"
r.Handlers.Unmarshal.SetBackNamed(request.NamedHandler{
Name: handlerName, Fn: handlerFn,
})
r.Handlers.UnmarshalError.SetBackNamed(request.NamedHandler{
Name: handlerName, Fn: handlerFn,
})
}
// LogHTTPResponseHeaderHandler is a SDK request handler to log the HTTP
// response received from a service. Will only log the HTTP response's headers.
// The response payload will not be read.
var LogHTTPResponseHeaderHandler = request.NamedHandler{
Name: "awssdk.client.LogResponseHeader",
Fn: logResponseHeader,
}
func logResponseHeader(r *request.Request) {
if !r.Config.LogLevel.AtLeast(aws.LogDebug) || r.Config.Logger == nil {
return
}
b, err := httputil.DumpResponse(r.HTTPResponse, false)
if err != nil {
r.Config.Logger.Log(fmt.Sprintf(logRespErrMsg,
r.ClientInfo.ServiceName, r.Operation.Name, err))
return
}
r.Config.Logger.Log(fmt.Sprintf(logRespMsg,
r.ClientInfo.ServiceName, r.Operation.Name, string(b)))
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
================================================
package metadata
// ClientInfo wraps immutable data from the client.Client structure.
type ClientInfo struct {
ServiceName string
ServiceID string
APIVersion string
PartitionID string
Endpoint string
SigningName string
SigningRegion string
JSONVersion string
TargetPrefix string
ResolvedRegion string
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/client/no_op_retryer.go
================================================
package client
import (
"time"
"github.com/aws/aws-sdk-go/aws/request"
)
// NoOpRetryer provides a retryer that performs no retries.
// It should be used when we do not want retries to be performed.
type NoOpRetryer struct{}
// MaxRetries returns the number of maximum returns the service will use to make
// an individual API; For NoOpRetryer the MaxRetries will always be zero.
func (d NoOpRetryer) MaxRetries() int {
return 0
}
// ShouldRetry will always return false for NoOpRetryer, as it should never retry.
func (d NoOpRetryer) ShouldRetry(_ *request.Request) bool {
return false
}
// RetryRules returns the delay duration before retrying this request again;
// since NoOpRetryer does not retry, RetryRules always returns 0.
func (d NoOpRetryer) RetryRules(_ *request.Request) time.Duration {
return 0
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/config.go
================================================
package aws
import (
"net/http"
"time"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/endpoints"
)
// UseServiceDefaultRetries instructs the config to use the service's own
// default number of retries. This will be the default action if
// Config.MaxRetries is nil also.
const UseServiceDefaultRetries = -1
// RequestRetryer is an alias for a type that implements the request.Retryer
// interface.
type RequestRetryer interface{}
// A Config provides service configuration for service clients. By default,
// all clients will use the defaults.DefaultConfig structure.
//
// // Create Session with MaxRetries configuration to be shared by multiple
// // service clients.
// sess := session.Must(session.NewSession(&aws.Config{
// MaxRetries: aws.Int(3),
// }))
//
// // Create S3 service client with a specific Region.
// svc := s3.New(sess, &aws.Config{
// Region: aws.String("us-west-2"),
// })
type Config struct {
// Enables verbose error printing of all credential chain errors.
// Should be used when wanting to see all errors while attempting to
// retrieve credentials.
CredentialsChainVerboseErrors *bool
// The credentials object to use when signing requests. Defaults to a
// chain of credential providers to search for credentials in environment
// variables, shared credential file, and EC2 Instance Roles.
Credentials *credentials.Credentials
// An optional endpoint URL (hostname only or fully qualified URI)
// that overrides the default generated endpoint for a client. Set this
// to `nil` or the value to `""` to use the default generated endpoint.
//
// Note: You must still provide a `Region` value when specifying an
// endpoint for a client.
Endpoint *string
// The resolver to use for looking up endpoints for AWS service clients
// to use based on region.
EndpointResolver endpoints.Resolver
// EnforceShouldRetryCheck is used in the AfterRetryHandler to always call
// ShouldRetry regardless of whether or not if request.Retryable is set.
// This will utilize ShouldRetry method of custom retryers. If EnforceShouldRetryCheck
// is not set, then ShouldRetry will only be called if request.Retryable is nil.
// Proper handling of the request.Retryable field is important when setting this field.
EnforceShouldRetryCheck *bool
// The region to send requests to. This parameter is required and must
// be configured globally or on a per-client basis unless otherwise
// noted. A full list of regions is found in the "Regions and Endpoints"
// document.
//
// See http://docs.aws.amazon.com/general/latest/gr/rande.html for AWS
// Regions and Endpoints.
Region *string
// Set this to `true` to disable SSL when sending requests. Defaults
// to `false`.
DisableSSL *bool
// The HTTP client to use when sending requests. Defaults to
// `http.DefaultClient`.
HTTPClient *http.Client
// An integer value representing the logging level. The default log level
// is zero (LogOff), which represents no logging. To enable logging set
// to a LogLevel Value.
LogLevel *LogLevelType
// The logger writer interface to write logging messages to. Defaults to
// standard out.
Logger Logger
// The maximum number of times that a request will be retried for failures.
// Defaults to -1, which defers the max retry setting to the service
// specific configuration.
MaxRetries *int
// Retryer guides how HTTP requests should be retried in case of
// recoverable failures.
//
// When nil or the value does not implement the request.Retryer interface,
// the client.DefaultRetryer will be used.
//
// When both Retryer and MaxRetries are non-nil, the former is used and
// the latter ignored.
//
// To set the Retryer field in a type-safe manner and with chaining, use
// the request.WithRetryer helper function:
//
// cfg := request.WithRetryer(aws.NewConfig(), myRetryer)
//
Retryer RequestRetryer
// Disables semantic parameter validation, which validates input for
// missing required fields and/or other semantic request input errors.
DisableParamValidation *bool
// Disables the computation of request and response checksums, e.g.,
// CRC32 checksums in Amazon DynamoDB.
DisableComputeChecksums *bool
// Set this to `true` to force the request to use path-style addressing,
// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client
// will use virtual hosted bucket addressing when possible
// (`http://BUCKET.s3.amazonaws.com/KEY`).
//
// Note: This configuration option is specific to the Amazon S3 service.
//
// See http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html
// for Amazon S3: Virtual Hosting of Buckets
S3ForcePathStyle *bool
// Set this to `true` to disable the SDK adding the `Expect: 100-Continue`
// header to PUT requests over 2MB of content. 100-Continue instructs the
// HTTP client not to send the body until the service responds with a
// `continue` status. This is useful to prevent sending the request body
// until after the request is authenticated, and validated.
//
// http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
//
// 100-Continue is only enabled for Go 1.6 and above. See `http.Transport`'s
// `ExpectContinueTimeout` for information on adjusting the continue wait
// timeout. https://golang.org/pkg/net/http/#Transport
//
// You should use this flag to disable 100-Continue if you experience issues
// with proxies or third party S3 compatible services.
S3Disable100Continue *bool
// Set this to `true` to enable S3 Accelerate feature. For all operations
// compatible with S3 Accelerate will use the accelerate endpoint for
// requests. Requests not compatible will fall back to normal S3 requests.
//
// The bucket must be enable for accelerate to be used with S3 client with
// accelerate enabled. If the bucket is not enabled for accelerate an error
// will be returned. The bucket name must be DNS compatible to also work
// with accelerate.
S3UseAccelerate *bool
// S3DisableContentMD5Validation config option is temporarily disabled,
// For S3 GetObject API calls, #1837.
//
// Set this to `true` to disable the S3 service client from automatically
// adding the ContentMD5 to S3 Object Put and Upload API calls. This option
// will also disable the SDK from performing object ContentMD5 validation
// on GetObject API calls.
S3DisableContentMD5Validation *bool
// Set this to `true` to have the S3 service client to use the region specified
// in the ARN, when an ARN is provided as an argument to a bucket parameter.
S3UseARNRegion *bool
// Set this to `true` to enable the SDK to unmarshal API response header maps to
// normalized lower case map keys.
//
// For example S3's X-Amz-Meta prefixed header will be unmarshaled to lower case
// Metadata member's map keys. The value of the header in the map is unaffected.
//
// The AWS SDK for Go v2, uses lower case header maps by default. The v1
// SDK provides this opt-in for this option, for backwards compatibility.
LowerCaseHeaderMaps *bool
// Set this to `true` to disable the EC2Metadata client from overriding the
// default http.Client's Timeout. This is helpful if you do not want the
// EC2Metadata client to create a new http.Client. This options is only
// meaningful if you're not already using a custom HTTP client with the
// SDK. Enabled by default.
//
// Must be set and provided to the session.NewSession() in order to disable
// the EC2Metadata overriding the timeout for default credentials chain.
//
// Example:
// sess := session.Must(session.NewSession(aws.NewConfig()
// .WithEC2MetadataDisableTimeoutOverride(true)))
//
// svc := s3.New(sess)
//
EC2MetadataDisableTimeoutOverride *bool
// Instructs the endpoint to be generated for a service client to
// be the dual stack endpoint. The dual stack endpoint will support
// both IPv4 and IPv6 addressing.
//
// Setting this for a service which does not support dual stack will fail
// to make requests. It is not recommended to set this value on the session
// as it will apply to all service clients created with the session. Even
// services which don't support dual stack endpoints.
//
// If the Endpoint config value is also provided the UseDualStack flag
// will be ignored.
//
// Only supported with.
//
// sess := session.Must(session.NewSession())
//
// svc := s3.New(sess, &aws.Config{
// UseDualStack: aws.Bool(true),
// })
//
// Deprecated: This option will continue to function for S3 and S3 Control for backwards compatibility.
// UseDualStackEndpoint should be used to enable usage of a service's dual-stack endpoint for all service clients
// moving forward. For S3 and S3 Control, when UseDualStackEndpoint is set to a non-zero value it takes higher
// precedence then this option.
UseDualStack *bool
// Sets the resolver to resolve a dual-stack endpoint for the service.
UseDualStackEndpoint endpoints.DualStackEndpointState
// UseFIPSEndpoint specifies the resolver must resolve a FIPS endpoint.
UseFIPSEndpoint endpoints.FIPSEndpointState
// SleepDelay is an override for the func the SDK will call when sleeping
// during the lifecycle of a request. Specifically this will be used for
// request delays. This value should only be used for testing. To adjust
// the delay of a request see the aws/client.DefaultRetryer and
// aws/request.Retryer.
//
// SleepDelay will prevent any Context from being used for canceling retry
// delay of an API operation. It is recommended to not use SleepDelay at all
// and specify a Retryer instead.
SleepDelay func(time.Duration)
// DisableRestProtocolURICleaning will not clean the URL path when making rest protocol requests.
// Will default to false. This would only be used for empty directory names in s3 requests.
//
// Example:
// sess := session.Must(session.NewSession(&aws.Config{
// DisableRestProtocolURICleaning: aws.Bool(true),
// }))
//
// svc := s3.New(sess)
// out, err := svc.GetObject(&s3.GetObjectInput {
// Bucket: aws.String("bucketname"),
// Key: aws.String("//foo//bar//moo"),
// })
DisableRestProtocolURICleaning *bool
// EnableEndpointDiscovery will allow for endpoint discovery on operations that
// have the definition in its model. By default, endpoint discovery is off.
// To use EndpointDiscovery, Endpoint should be unset or set to an empty string.
//
// Example:
// sess := session.Must(session.NewSession(&aws.Config{
// EnableEndpointDiscovery: aws.Bool(true),
// }))
//
// svc := s3.New(sess)
// out, err := svc.GetObject(&s3.GetObjectInput {
// Bucket: aws.String("bucketname"),
// Key: aws.String("/foo/bar/moo"),
// })
EnableEndpointDiscovery *bool
// DisableEndpointHostPrefix will disable the SDK's behavior of prefixing
// request endpoint hosts with modeled information.
//
// Disabling this feature is useful when you want to use local endpoints
// for testing that do not support the modeled host prefix pattern.
DisableEndpointHostPrefix *bool
// STSRegionalEndpoint will enable regional or legacy endpoint resolving
STSRegionalEndpoint endpoints.STSRegionalEndpoint
// S3UsEast1RegionalEndpoint will enable regional or legacy endpoint resolving
S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint
}
// NewConfig returns a new Config pointer that can be chained with builder
// methods to set multiple configuration values inline without using pointers.
//
// // Create Session with MaxRetries configuration to be shared by multiple
// // service clients.
// sess := session.Must(session.NewSession(aws.NewConfig().
// WithMaxRetries(3),
// ))
//
// // Create S3 service client with a specific Region.
// svc := s3.New(sess, aws.NewConfig().
// WithRegion("us-west-2"),
// )
func NewConfig() *Config {
return &Config{}
}
// WithCredentialsChainVerboseErrors sets a config verbose errors boolean and returning
// a Config pointer.
func (c *Config) WithCredentialsChainVerboseErrors(verboseErrs bool) *Config {
c.CredentialsChainVerboseErrors = &verboseErrs
return c
}
// WithCredentials sets a config Credentials value returning a Config pointer
// for chaining.
func (c *Config) WithCredentials(creds *credentials.Credentials) *Config {
c.Credentials = creds
return c
}
// WithEndpoint sets a config Endpoint value returning a Config pointer for
// chaining.
func (c *Config) WithEndpoint(endpoint string) *Config {
c.Endpoint = &endpoint
return c
}
// WithEndpointResolver sets a config EndpointResolver value returning a
// Config pointer for chaining.
func (c *Config) WithEndpointResolver(resolver endpoints.Resolver) *Config {
c.EndpointResolver = resolver
return c
}
// WithRegion sets a config Region value returning a Config pointer for
// chaining.
func (c *Config) WithRegion(region string) *Config {
c.Region = ®ion
return c
}
// WithDisableSSL sets a config DisableSSL value returning a Config pointer
// for chaining.
func (c *Config) WithDisableSSL(disable bool) *Config {
c.DisableSSL = &disable
return c
}
// WithHTTPClient sets a config HTTPClient value returning a Config pointer
// for chaining.
func (c *Config) WithHTTPClient(client *http.Client) *Config {
c.HTTPClient = client
return c
}
// WithMaxRetries sets a config MaxRetries value returning a Config pointer
// for chaining.
func (c *Config) WithMaxRetries(max int) *Config {
c.MaxRetries = &max
return c
}
// WithDisableParamValidation sets a config DisableParamValidation value
// returning a Config pointer for chaining.
func (c *Config) WithDisableParamValidation(disable bool) *Config {
c.DisableParamValidation = &disable
return c
}
// WithDisableComputeChecksums sets a config DisableComputeChecksums value
// returning a Config pointer for chaining.
func (c *Config) WithDisableComputeChecksums(disable bool) *Config {
c.DisableComputeChecksums = &disable
return c
}
// WithLogLevel sets a config LogLevel value returning a Config pointer for
// chaining.
func (c *Config) WithLogLevel(level LogLevelType) *Config {
c.LogLevel = &level
return c
}
// WithLogger sets a config Logger value returning a Config pointer for
// chaining.
func (c *Config) WithLogger(logger Logger) *Config {
c.Logger = logger
return c
}
// WithS3ForcePathStyle sets a config S3ForcePathStyle value returning a Config
// pointer for chaining.
func (c *Config) WithS3ForcePathStyle(force bool) *Config {
c.S3ForcePathStyle = &force
return c
}
// WithS3Disable100Continue sets a config S3Disable100Continue value returning
// a Config pointer for chaining.
func (c *Config) WithS3Disable100Continue(disable bool) *Config {
c.S3Disable100Continue = &disable
return c
}
// WithS3UseAccelerate sets a config S3UseAccelerate value returning a Config
// pointer for chaining.
func (c *Config) WithS3UseAccelerate(enable bool) *Config {
c.S3UseAccelerate = &enable
return c
}
// WithS3DisableContentMD5Validation sets a config
// S3DisableContentMD5Validation value returning a Config pointer for chaining.
func (c *Config) WithS3DisableContentMD5Validation(enable bool) *Config {
c.S3DisableContentMD5Validation = &enable
return c
}
// WithS3UseARNRegion sets a config S3UseARNRegion value and
// returning a Config pointer for chaining
func (c *Config) WithS3UseARNRegion(enable bool) *Config {
c.S3UseARNRegion = &enable
return c
}
// WithUseDualStack sets a config UseDualStack value returning a Config
// pointer for chaining.
func (c *Config) WithUseDualStack(enable bool) *Config {
c.UseDualStack = &enable
return c
}
// WithEC2MetadataDisableTimeoutOverride sets a config EC2MetadataDisableTimeoutOverride value
// returning a Config pointer for chaining.
func (c *Config) WithEC2MetadataDisableTimeoutOverride(enable bool) *Config {
c.EC2MetadataDisableTimeoutOverride = &enable
return c
}
// WithSleepDelay overrides the function used to sleep while waiting for the
// next retry. Defaults to time.Sleep.
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
c.SleepDelay = fn
return c
}
// WithEndpointDiscovery will set whether or not to use endpoint discovery.
func (c *Config) WithEndpointDiscovery(t bool) *Config {
c.EnableEndpointDiscovery = &t
return c
}
// WithDisableEndpointHostPrefix will set whether or not to use modeled host prefix
// when making requests.
func (c *Config) WithDisableEndpointHostPrefix(t bool) *Config {
c.DisableEndpointHostPrefix = &t
return c
}
// WithSTSRegionalEndpoint will set whether or not to use regional endpoint flag
// when resolving the endpoint for a service
func (c *Config) WithSTSRegionalEndpoint(sre endpoints.STSRegionalEndpoint) *Config {
c.STSRegionalEndpoint = sre
return c
}
// WithS3UsEast1RegionalEndpoint will set whether or not to use regional endpoint flag
// when resolving the endpoint for a service
func (c *Config) WithS3UsEast1RegionalEndpoint(sre endpoints.S3UsEast1RegionalEndpoint) *Config {
c.S3UsEast1RegionalEndpoint = sre
return c
}
// WithLowerCaseHeaderMaps sets a config LowerCaseHeaderMaps value
// returning a Config pointer for chaining.
func (c *Config) WithLowerCaseHeaderMaps(t bool) *Config {
c.LowerCaseHeaderMaps = &t
return c
}
// WithDisableRestProtocolURICleaning sets a config DisableRestProtocolURICleaning value
// returning a Config pointer for chaining.
func (c *Config) WithDisableRestProtocolURICleaning(t bool) *Config {
c.DisableRestProtocolURICleaning = &t
return c
}
// MergeIn merges the passed in configs into the existing config object.
func (c *Config) MergeIn(cfgs ...*Config) {
for _, other := range cfgs {
mergeInConfig(c, other)
}
}
func mergeInConfig(dst *Config, other *Config) {
if other == nil {
return
}
if other.CredentialsChainVerboseErrors != nil {
dst.CredentialsChainVerboseErrors = other.CredentialsChainVerboseErrors
}
if other.Credentials != nil {
dst.Credentials = other.Credentials
}
if other.Endpoint != nil {
dst.Endpoint = other.Endpoint
}
if other.EndpointResolver != nil {
dst.EndpointResolver = other.EndpointResolver
}
if other.Region != nil {
dst.Region = other.Region
}
if other.DisableSSL != nil {
dst.DisableSSL = other.DisableSSL
}
if other.HTTPClient != nil {
dst.HTTPClient = other.HTTPClient
}
if other.LogLevel != nil {
dst.LogLevel = other.LogLevel
}
if other.Logger != nil {
dst.Logger = other.Logger
}
if other.MaxRetries != nil {
dst.MaxRetries = other.MaxRetries
}
if other.Retryer != nil {
dst.Retryer = other.Retryer
}
if other.DisableParamValidation != nil {
dst.DisableParamValidation = other.DisableParamValidation
}
if other.DisableComputeChecksums != nil {
dst.DisableComputeChecksums = other.DisableComputeChecksums
}
if other.S3ForcePathStyle != nil {
dst.S3ForcePathStyle = other.S3ForcePathStyle
}
if other.S3Disable100Continue != nil {
dst.S3Disable100Continue = other.S3Disable100Continue
}
if other.S3UseAccelerate != nil {
dst.S3UseAccelerate = other.S3UseAccelerate
}
if other.S3DisableContentMD5Validation != nil {
dst.S3DisableContentMD5Validation = other.S3DisableContentMD5Validation
}
if other.S3UseARNRegion != nil {
dst.S3UseARNRegion = other.S3UseARNRegion
}
if other.UseDualStack != nil {
dst.UseDualStack = other.UseDualStack
}
if other.UseDualStackEndpoint != endpoints.DualStackEndpointStateUnset {
dst.UseDualStackEndpoint = other.UseDualStackEndpoint
}
if other.EC2MetadataDisableTimeoutOverride != nil {
dst.EC2MetadataDisableTimeoutOverride = other.EC2MetadataDisableTimeoutOverride
}
if other.SleepDelay != nil {
dst.SleepDelay = other.SleepDelay
}
if other.DisableRestProtocolURICleaning != nil {
dst.DisableRestProtocolURICleaning = other.DisableRestProtocolURICleaning
}
if other.EnforceShouldRetryCheck != nil {
dst.EnforceShouldRetryCheck = other.EnforceShouldRetryCheck
}
if other.EnableEndpointDiscovery != nil {
dst.EnableEndpointDiscovery = other.EnableEndpointDiscovery
}
if other.DisableEndpointHostPrefix != nil {
dst.DisableEndpointHostPrefix = other.DisableEndpointHostPrefix
}
if other.STSRegionalEndpoint != endpoints.UnsetSTSEndpoint {
dst.STSRegionalEndpoint = other.STSRegionalEndpoint
}
if other.S3UsEast1RegionalEndpoint != endpoints.UnsetS3UsEast1Endpoint {
dst.S3UsEast1RegionalEndpoint = other.S3UsEast1RegionalEndpoint
}
if other.LowerCaseHeaderMaps != nil {
dst.LowerCaseHeaderMaps = other.LowerCaseHeaderMaps
}
if other.UseDualStackEndpoint != endpoints.DualStackEndpointStateUnset {
dst.UseDualStackEndpoint = other.UseDualStackEndpoint
}
if other.UseFIPSEndpoint != endpoints.FIPSEndpointStateUnset {
dst.UseFIPSEndpoint = other.UseFIPSEndpoint
}
}
// Copy will return a shallow copy of the Config object. If any additional
// configurations are provided they will be merged into the new config returned.
func (c *Config) Copy(cfgs ...*Config) *Config {
dst := &Config{}
dst.MergeIn(c)
for _, cfg := range cfgs {
dst.MergeIn(cfg)
}
return dst
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/context_1_5.go
================================================
//go:build !go1.9
// +build !go1.9
package aws
import "time"
// Context is an copy of the Go v1.7 stdlib's context.Context interface.
// It is represented as a SDK interface to enable you to use the "WithContext"
// API methods with Go v1.6 and a Context type such as golang.org/x/net/context.
//
// See https://golang.org/pkg/context on how to use contexts.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
Value(key interface{}) interface{}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/context_1_9.go
================================================
//go:build go1.9
// +build go1.9
package aws
import "context"
// Context is an alias of the Go stdlib's context.Context interface.
// It can be used within the SDK's API operation "WithContext" methods.
//
// See https://golang.org/pkg/context on how to use contexts.
type Context = context.Context
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/context_background_1_5.go
================================================
//go:build !go1.7
// +build !go1.7
package aws
import (
"github.com/aws/aws-sdk-go/internal/context"
)
// BackgroundContext returns a context that will never be canceled, has no
// values, and no deadline. This context is used by the SDK to provide
// backwards compatibility with non-context API operations and functionality.
//
// Go 1.6 and before:
// This context function is equivalent to context.Background in the Go stdlib.
//
// Go 1.7 and later:
// The context returned will be the value returned by context.Background()
//
// See https://golang.org/pkg/context for more information on Contexts.
func BackgroundContext() Context {
return context.BackgroundCtx
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/context_background_1_7.go
================================================
//go:build go1.7
// +build go1.7
package aws
import "context"
// BackgroundContext returns a context that will never be canceled, has no
// values, and no deadline. This context is used by the SDK to provide
// backwards compatibility with non-context API operations and functionality.
//
// Go 1.6 and before:
// This context function is equivalent to context.Background in the Go stdlib.
//
// Go 1.7 and later:
// The context returned will be the value returned by context.Background()
//
// See https://golang.org/pkg/context for more information on Contexts.
func BackgroundContext() Context {
return context.Background()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/context_sleep.go
================================================
package aws
import (
"time"
)
// SleepWithContext will wait for the timer duration to expire, or the context
// is canceled. Which ever happens first. If the context is canceled the Context's
// error will be returned.
//
// Expects Context to always return a non-nil error if the Done channel is closed.
func SleepWithContext(ctx Context, dur time.Duration) error {
t := time.NewTimer(dur)
defer t.Stop()
select {
case <-t.C:
break
case <-ctx.Done():
return ctx.Err()
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/convert_types.go
================================================
package aws
import "time"
// String returns a pointer to the string value passed in.
func String(v string) *string {
return &v
}
// StringValue returns the value of the string pointer passed in or
// "" if the pointer is nil.
func StringValue(v *string) string {
if v != nil {
return *v
}
return ""
}
// StringSlice converts a slice of string values into a slice of
// string pointers
func StringSlice(src []string) []*string {
dst := make([]*string, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// StringValueSlice converts a slice of string pointers into a slice of
// string values
func StringValueSlice(src []*string) []string {
dst := make([]string, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// StringMap converts a string map of string values into a string
// map of string pointers
func StringMap(src map[string]string) map[string]*string {
dst := make(map[string]*string)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// StringValueMap converts a string map of string pointers into a string
// map of string values
func StringValueMap(src map[string]*string) map[string]string {
dst := make(map[string]string)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Bool returns a pointer to the bool value passed in.
func Bool(v bool) *bool {
return &v
}
// BoolValue returns the value of the bool pointer passed in or
// false if the pointer is nil.
func BoolValue(v *bool) bool {
if v != nil {
return *v
}
return false
}
// BoolSlice converts a slice of bool values into a slice of
// bool pointers
func BoolSlice(src []bool) []*bool {
dst := make([]*bool, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// BoolValueSlice converts a slice of bool pointers into a slice of
// bool values
func BoolValueSlice(src []*bool) []bool {
dst := make([]bool, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// BoolMap converts a string map of bool values into a string
// map of bool pointers
func BoolMap(src map[string]bool) map[string]*bool {
dst := make(map[string]*bool)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// BoolValueMap converts a string map of bool pointers into a string
// map of bool values
func BoolValueMap(src map[string]*bool) map[string]bool {
dst := make(map[string]bool)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Int returns a pointer to the int value passed in.
func Int(v int) *int {
return &v
}
// IntValue returns the value of the int pointer passed in or
// 0 if the pointer is nil.
func IntValue(v *int) int {
if v != nil {
return *v
}
return 0
}
// IntSlice converts a slice of int values into a slice of
// int pointers
func IntSlice(src []int) []*int {
dst := make([]*int, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// IntValueSlice converts a slice of int pointers into a slice of
// int values
func IntValueSlice(src []*int) []int {
dst := make([]int, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// IntMap converts a string map of int values into a string
// map of int pointers
func IntMap(src map[string]int) map[string]*int {
dst := make(map[string]*int)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// IntValueMap converts a string map of int pointers into a string
// map of int values
func IntValueMap(src map[string]*int) map[string]int {
dst := make(map[string]int)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Uint returns a pointer to the uint value passed in.
func Uint(v uint) *uint {
return &v
}
// UintValue returns the value of the uint pointer passed in or
// 0 if the pointer is nil.
func UintValue(v *uint) uint {
if v != nil {
return *v
}
return 0
}
// UintSlice converts a slice of uint values uinto a slice of
// uint pointers
func UintSlice(src []uint) []*uint {
dst := make([]*uint, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// UintValueSlice converts a slice of uint pointers uinto a slice of
// uint values
func UintValueSlice(src []*uint) []uint {
dst := make([]uint, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// UintMap converts a string map of uint values uinto a string
// map of uint pointers
func UintMap(src map[string]uint) map[string]*uint {
dst := make(map[string]*uint)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// UintValueMap converts a string map of uint pointers uinto a string
// map of uint values
func UintValueMap(src map[string]*uint) map[string]uint {
dst := make(map[string]uint)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Int8 returns a pointer to the int8 value passed in.
func Int8(v int8) *int8 {
return &v
}
// Int8Value returns the value of the int8 pointer passed in or
// 0 if the pointer is nil.
func Int8Value(v *int8) int8 {
if v != nil {
return *v
}
return 0
}
// Int8Slice converts a slice of int8 values into a slice of
// int8 pointers
func Int8Slice(src []int8) []*int8 {
dst := make([]*int8, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Int8ValueSlice converts a slice of int8 pointers into a slice of
// int8 values
func Int8ValueSlice(src []*int8) []int8 {
dst := make([]int8, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Int8Map converts a string map of int8 values into a string
// map of int8 pointers
func Int8Map(src map[string]int8) map[string]*int8 {
dst := make(map[string]*int8)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Int8ValueMap converts a string map of int8 pointers into a string
// map of int8 values
func Int8ValueMap(src map[string]*int8) map[string]int8 {
dst := make(map[string]int8)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Int16 returns a pointer to the int16 value passed in.
func Int16(v int16) *int16 {
return &v
}
// Int16Value returns the value of the int16 pointer passed in or
// 0 if the pointer is nil.
func Int16Value(v *int16) int16 {
if v != nil {
return *v
}
return 0
}
// Int16Slice converts a slice of int16 values into a slice of
// int16 pointers
func Int16Slice(src []int16) []*int16 {
dst := make([]*int16, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Int16ValueSlice converts a slice of int16 pointers into a slice of
// int16 values
func Int16ValueSlice(src []*int16) []int16 {
dst := make([]int16, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Int16Map converts a string map of int16 values into a string
// map of int16 pointers
func Int16Map(src map[string]int16) map[string]*int16 {
dst := make(map[string]*int16)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Int16ValueMap converts a string map of int16 pointers into a string
// map of int16 values
func Int16ValueMap(src map[string]*int16) map[string]int16 {
dst := make(map[string]int16)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Int32 returns a pointer to the int32 value passed in.
func Int32(v int32) *int32 {
return &v
}
// Int32Value returns the value of the int32 pointer passed in or
// 0 if the pointer is nil.
func Int32Value(v *int32) int32 {
if v != nil {
return *v
}
return 0
}
// Int32Slice converts a slice of int32 values into a slice of
// int32 pointers
func Int32Slice(src []int32) []*int32 {
dst := make([]*int32, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Int32ValueSlice converts a slice of int32 pointers into a slice of
// int32 values
func Int32ValueSlice(src []*int32) []int32 {
dst := make([]int32, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Int32Map converts a string map of int32 values into a string
// map of int32 pointers
func Int32Map(src map[string]int32) map[string]*int32 {
dst := make(map[string]*int32)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Int32ValueMap converts a string map of int32 pointers into a string
// map of int32 values
func Int32ValueMap(src map[string]*int32) map[string]int32 {
dst := make(map[string]int32)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Int64 returns a pointer to the int64 value passed in.
func Int64(v int64) *int64 {
return &v
}
// Int64Value returns the value of the int64 pointer passed in or
// 0 if the pointer is nil.
func Int64Value(v *int64) int64 {
if v != nil {
return *v
}
return 0
}
// Int64Slice converts a slice of int64 values into a slice of
// int64 pointers
func Int64Slice(src []int64) []*int64 {
dst := make([]*int64, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Int64ValueSlice converts a slice of int64 pointers into a slice of
// int64 values
func Int64ValueSlice(src []*int64) []int64 {
dst := make([]int64, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Int64Map converts a string map of int64 values into a string
// map of int64 pointers
func Int64Map(src map[string]int64) map[string]*int64 {
dst := make(map[string]*int64)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Int64ValueMap converts a string map of int64 pointers into a string
// map of int64 values
func Int64ValueMap(src map[string]*int64) map[string]int64 {
dst := make(map[string]int64)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Uint8 returns a pointer to the uint8 value passed in.
func Uint8(v uint8) *uint8 {
return &v
}
// Uint8Value returns the value of the uint8 pointer passed in or
// 0 if the pointer is nil.
func Uint8Value(v *uint8) uint8 {
if v != nil {
return *v
}
return 0
}
// Uint8Slice converts a slice of uint8 values into a slice of
// uint8 pointers
func Uint8Slice(src []uint8) []*uint8 {
dst := make([]*uint8, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Uint8ValueSlice converts a slice of uint8 pointers into a slice of
// uint8 values
func Uint8ValueSlice(src []*uint8) []uint8 {
dst := make([]uint8, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Uint8Map converts a string map of uint8 values into a string
// map of uint8 pointers
func Uint8Map(src map[string]uint8) map[string]*uint8 {
dst := make(map[string]*uint8)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Uint8ValueMap converts a string map of uint8 pointers into a string
// map of uint8 values
func Uint8ValueMap(src map[string]*uint8) map[string]uint8 {
dst := make(map[string]uint8)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Uint16 returns a pointer to the uint16 value passed in.
func Uint16(v uint16) *uint16 {
return &v
}
// Uint16Value returns the value of the uint16 pointer passed in or
// 0 if the pointer is nil.
func Uint16Value(v *uint16) uint16 {
if v != nil {
return *v
}
return 0
}
// Uint16Slice converts a slice of uint16 values into a slice of
// uint16 pointers
func Uint16Slice(src []uint16) []*uint16 {
dst := make([]*uint16, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Uint16ValueSlice converts a slice of uint16 pointers into a slice of
// uint16 values
func Uint16ValueSlice(src []*uint16) []uint16 {
dst := make([]uint16, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Uint16Map converts a string map of uint16 values into a string
// map of uint16 pointers
func Uint16Map(src map[string]uint16) map[string]*uint16 {
dst := make(map[string]*uint16)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Uint16ValueMap converts a string map of uint16 pointers into a string
// map of uint16 values
func Uint16ValueMap(src map[string]*uint16) map[string]uint16 {
dst := make(map[string]uint16)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Uint32 returns a pointer to the uint32 value passed in.
func Uint32(v uint32) *uint32 {
return &v
}
// Uint32Value returns the value of the uint32 pointer passed in or
// 0 if the pointer is nil.
func Uint32Value(v *uint32) uint32 {
if v != nil {
return *v
}
return 0
}
// Uint32Slice converts a slice of uint32 values into a slice of
// uint32 pointers
func Uint32Slice(src []uint32) []*uint32 {
dst := make([]*uint32, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Uint32ValueSlice converts a slice of uint32 pointers into a slice of
// uint32 values
func Uint32ValueSlice(src []*uint32) []uint32 {
dst := make([]uint32, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Uint32Map converts a string map of uint32 values into a string
// map of uint32 pointers
func Uint32Map(src map[string]uint32) map[string]*uint32 {
dst := make(map[string]*uint32)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Uint32ValueMap converts a string map of uint32 pointers into a string
// map of uint32 values
func Uint32ValueMap(src map[string]*uint32) map[string]uint32 {
dst := make(map[string]uint32)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Uint64 returns a pointer to the uint64 value passed in.
func Uint64(v uint64) *uint64 {
return &v
}
// Uint64Value returns the value of the uint64 pointer passed in or
// 0 if the pointer is nil.
func Uint64Value(v *uint64) uint64 {
if v != nil {
return *v
}
return 0
}
// Uint64Slice converts a slice of uint64 values into a slice of
// uint64 pointers
func Uint64Slice(src []uint64) []*uint64 {
dst := make([]*uint64, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Uint64ValueSlice converts a slice of uint64 pointers into a slice of
// uint64 values
func Uint64ValueSlice(src []*uint64) []uint64 {
dst := make([]uint64, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Uint64Map converts a string map of uint64 values into a string
// map of uint64 pointers
func Uint64Map(src map[string]uint64) map[string]*uint64 {
dst := make(map[string]*uint64)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Uint64ValueMap converts a string map of uint64 pointers into a string
// map of uint64 values
func Uint64ValueMap(src map[string]*uint64) map[string]uint64 {
dst := make(map[string]uint64)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Float32 returns a pointer to the float32 value passed in.
func Float32(v float32) *float32 {
return &v
}
// Float32Value returns the value of the float32 pointer passed in or
// 0 if the pointer is nil.
func Float32Value(v *float32) float32 {
if v != nil {
return *v
}
return 0
}
// Float32Slice converts a slice of float32 values into a slice of
// float32 pointers
func Float32Slice(src []float32) []*float32 {
dst := make([]*float32, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Float32ValueSlice converts a slice of float32 pointers into a slice of
// float32 values
func Float32ValueSlice(src []*float32) []float32 {
dst := make([]float32, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Float32Map converts a string map of float32 values into a string
// map of float32 pointers
func Float32Map(src map[string]float32) map[string]*float32 {
dst := make(map[string]*float32)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Float32ValueMap converts a string map of float32 pointers into a string
// map of float32 values
func Float32ValueMap(src map[string]*float32) map[string]float32 {
dst := make(map[string]float32)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Float64 returns a pointer to the float64 value passed in.
func Float64(v float64) *float64 {
return &v
}
// Float64Value returns the value of the float64 pointer passed in or
// 0 if the pointer is nil.
func Float64Value(v *float64) float64 {
if v != nil {
return *v
}
return 0
}
// Float64Slice converts a slice of float64 values into a slice of
// float64 pointers
func Float64Slice(src []float64) []*float64 {
dst := make([]*float64, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// Float64ValueSlice converts a slice of float64 pointers into a slice of
// float64 values
func Float64ValueSlice(src []*float64) []float64 {
dst := make([]float64, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// Float64Map converts a string map of float64 values into a string
// map of float64 pointers
func Float64Map(src map[string]float64) map[string]*float64 {
dst := make(map[string]*float64)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// Float64ValueMap converts a string map of float64 pointers into a string
// map of float64 values
func Float64ValueMap(src map[string]*float64) map[string]float64 {
dst := make(map[string]float64)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
// Time returns a pointer to the time.Time value passed in.
func Time(v time.Time) *time.Time {
return &v
}
// TimeValue returns the value of the time.Time pointer passed in or
// time.Time{} if the pointer is nil.
func TimeValue(v *time.Time) time.Time {
if v != nil {
return *v
}
return time.Time{}
}
// SecondsTimeValue converts an int64 pointer to a time.Time value
// representing seconds since Epoch or time.Time{} if the pointer is nil.
func SecondsTimeValue(v *int64) time.Time {
if v != nil {
return time.Unix((*v / 1000), 0)
}
return time.Time{}
}
// MillisecondsTimeValue converts an int64 pointer to a time.Time value
// representing milliseconds sinch Epoch or time.Time{} if the pointer is nil.
func MillisecondsTimeValue(v *int64) time.Time {
if v != nil {
return time.Unix(0, (*v * 1000000))
}
return time.Time{}
}
// TimeUnixMilli returns a Unix timestamp in milliseconds from "January 1, 1970 UTC".
// The result is undefined if the Unix time cannot be represented by an int64.
// Which includes calling TimeUnixMilli on a zero Time is undefined.
//
// This utility is useful for service API's such as CloudWatch Logs which require
// their unix time values to be in milliseconds.
//
// See Go stdlib https://golang.org/pkg/time/#Time.UnixNano for more information.
func TimeUnixMilli(t time.Time) int64 {
return t.UnixNano() / int64(time.Millisecond/time.Nanosecond)
}
// TimeSlice converts a slice of time.Time values into a slice of
// time.Time pointers
func TimeSlice(src []time.Time) []*time.Time {
dst := make([]*time.Time, len(src))
for i := 0; i < len(src); i++ {
dst[i] = &(src[i])
}
return dst
}
// TimeValueSlice converts a slice of time.Time pointers into a slice of
// time.Time values
func TimeValueSlice(src []*time.Time) []time.Time {
dst := make([]time.Time, len(src))
for i := 0; i < len(src); i++ {
if src[i] != nil {
dst[i] = *(src[i])
}
}
return dst
}
// TimeMap converts a string map of time.Time values into a string
// map of time.Time pointers
func TimeMap(src map[string]time.Time) map[string]*time.Time {
dst := make(map[string]*time.Time)
for k, val := range src {
v := val
dst[k] = &v
}
return dst
}
// TimeValueMap converts a string map of time.Time pointers into a string
// map of time.Time values
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
dst := make(map[string]time.Time)
for k, val := range src {
if val != nil {
dst[k] = *val
}
}
return dst
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/corehandlers/handlers.go
================================================
package corehandlers
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
)
// Interface for matching types which also have a Len method.
type lener interface {
Len() int
}
// BuildContentLengthHandler builds the content length of a request based on the body,
// or will use the HTTPRequest.Header's "Content-Length" if defined. If unable
// to determine request body length and no "Content-Length" was specified it will panic.
//
// The Content-Length will only be added to the request if the length of the body
// is greater than 0. If the body is empty or the current `Content-Length`
// header is <= 0, the header will also be stripped.
var BuildContentLengthHandler = request.NamedHandler{Name: "core.BuildContentLengthHandler", Fn: func(r *request.Request) {
var length int64
if slength := r.HTTPRequest.Header.Get("Content-Length"); slength != "" {
length, _ = strconv.ParseInt(slength, 10, 64)
} else {
if r.Body != nil {
var err error
length, err = aws.SeekerLen(r.Body)
if err != nil {
r.Error = awserr.New(request.ErrCodeSerialization, "failed to get request body's length", err)
return
}
}
}
if length > 0 {
r.HTTPRequest.ContentLength = length
r.HTTPRequest.Header.Set("Content-Length", fmt.Sprintf("%d", length))
} else {
r.HTTPRequest.ContentLength = 0
r.HTTPRequest.Header.Del("Content-Length")
}
}}
var reStatusCode = regexp.MustCompile(`^(\d{3})`)
// ValidateReqSigHandler is a request handler to ensure that the request's
// signature doesn't expire before it is sent. This can happen when a request
// is built and signed significantly before it is sent. Or significant delays
// occur when retrying requests that would cause the signature to expire.
var ValidateReqSigHandler = request.NamedHandler{
Name: "core.ValidateReqSigHandler",
Fn: func(r *request.Request) {
// Unsigned requests are not signed
if r.Config.Credentials == credentials.AnonymousCredentials {
return
}
signedTime := r.Time
if !r.LastSignedAt.IsZero() {
signedTime = r.LastSignedAt
}
// 5 minutes to allow for some clock skew/delays in transmission.
// Would be improved with aws/aws-sdk-go#423
if signedTime.Add(5 * time.Minute).After(time.Now()) {
return
}
fmt.Println("request expired, resigning")
r.Sign()
},
}
// SendHandler is a request handler to send service request using HTTP client.
var SendHandler = request.NamedHandler{
Name: "core.SendHandler",
Fn: func(r *request.Request) {
sender := sendFollowRedirects
if r.DisableFollowRedirects {
sender = sendWithoutFollowRedirects
}
if request.NoBody == r.HTTPRequest.Body {
// Strip off the request body if the NoBody reader was used as a
// place holder for a request body. This prevents the SDK from
// making requests with a request body when it would be invalid
// to do so.
//
// Use a shallow copy of the http.Request to ensure the race condition
// of transport on Body will not trigger
reqOrig, reqCopy := r.HTTPRequest, *r.HTTPRequest
reqCopy.Body = nil
r.HTTPRequest = &reqCopy
defer func() {
r.HTTPRequest = reqOrig
}()
}
var err error
r.HTTPResponse, err = sender(r)
if err != nil {
handleSendError(r, err)
}
},
}
func sendFollowRedirects(r *request.Request) (*http.Response, error) {
return r.Config.HTTPClient.Do(r.HTTPRequest)
}
func sendWithoutFollowRedirects(r *request.Request) (*http.Response, error) {
transport := r.Config.HTTPClient.Transport
if transport == nil {
transport = http.DefaultTransport
}
return transport.RoundTrip(r.HTTPRequest)
}
func handleSendError(r *request.Request, err error) {
// Prevent leaking if an HTTPResponse was returned. Clean up
// the body.
if r.HTTPResponse != nil {
r.HTTPResponse.Body.Close()
}
// Capture the case where url.Error is returned for error processing
// response. e.g. 301 without location header comes back as string
// error and r.HTTPResponse is nil. Other URL redirect errors will
// comeback in a similar method.
if e, ok := err.(*url.Error); ok && e.Err != nil {
if s := reStatusCode.FindStringSubmatch(e.Err.Error()); s != nil {
code, _ := strconv.ParseInt(s[1], 10, 64)
r.HTTPResponse = &http.Response{
StatusCode: int(code),
Status: http.StatusText(int(code)),
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
}
return
}
}
if r.HTTPResponse == nil {
// Add a dummy request response object to ensure the HTTPResponse
// value is consistent.
r.HTTPResponse = &http.Response{
StatusCode: int(0),
Status: http.StatusText(int(0)),
Body: ioutil.NopCloser(bytes.NewReader([]byte{})),
}
}
// Catch all request errors, and let the default retrier determine
// if the error is retryable.
r.Error = awserr.New(request.ErrCodeRequestError, "send request failed", err)
// Override the error with a context canceled error, if that was canceled.
ctx := r.Context()
select {
case <-ctx.Done():
r.Error = awserr.New(request.CanceledErrorCode,
"request context canceled", ctx.Err())
r.Retryable = aws.Bool(false)
default:
}
}
// ValidateResponseHandler is a request handler to validate service response.
var ValidateResponseHandler = request.NamedHandler{Name: "core.ValidateResponseHandler", Fn: func(r *request.Request) {
if r.HTTPResponse.StatusCode == 0 || r.HTTPResponse.StatusCode >= 300 {
// this may be replaced by an UnmarshalError handler
r.Error = awserr.New("UnknownError", "unknown error", r.Error)
}
}}
// AfterRetryHandler performs final checks to determine if the request should
// be retried and how long to delay.
var AfterRetryHandler = request.NamedHandler{
Name: "core.AfterRetryHandler",
Fn: func(r *request.Request) {
// If one of the other handlers already set the retry state
// we don't want to override it based on the service's state
if r.Retryable == nil || aws.BoolValue(r.Config.EnforceShouldRetryCheck) {
r.Retryable = aws.Bool(r.ShouldRetry(r))
}
if r.WillRetry() {
r.RetryDelay = r.RetryRules(r)
if sleepFn := r.Config.SleepDelay; sleepFn != nil {
// Support SleepDelay for backwards compatibility and testing
sleepFn(r.RetryDelay)
} else if err := aws.SleepWithContext(r.Context(), r.RetryDelay); err != nil {
r.Error = awserr.New(request.CanceledErrorCode,
"request context canceled", err)
r.Retryable = aws.Bool(false)
return
}
// when the expired token exception occurs the credentials
// need to be expired locally so that the next request to
// get credentials will trigger a credentials refresh.
if r.IsErrorExpired() {
r.Config.Credentials.Expire()
}
r.RetryCount++
r.Error = nil
}
}}
// ValidateEndpointHandler is a request handler to validate a request had the
// appropriate Region and Endpoint set. Will set r.Error if the endpoint or
// region is not valid.
var ValidateEndpointHandler = request.NamedHandler{Name: "core.ValidateEndpointHandler", Fn: func(r *request.Request) {
if r.ClientInfo.SigningRegion == "" && aws.StringValue(r.Config.Region) == "" {
r.Error = aws.ErrMissingRegion
} else if r.ClientInfo.Endpoint == "" {
// Was any endpoint provided by the user, or one was derived by the
// SDK's endpoint resolver?
r.Error = aws.ErrMissingEndpoint
}
}}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/corehandlers/param_validator.go
================================================
package corehandlers
import "github.com/aws/aws-sdk-go/aws/request"
// ValidateParametersHandler is a request handler to validate the input parameters.
// Validating parameters only has meaning if done prior to the request being sent.
var ValidateParametersHandler = request.NamedHandler{Name: "core.ValidateParametersHandler", Fn: func(r *request.Request) {
if !r.ParamsFilled() {
return
}
if v, ok := r.Params.(request.Validator); ok {
if err := v.Validate(); err != nil {
r.Error = err
}
}
}}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/corehandlers/user_agent.go
================================================
package corehandlers
import (
"os"
"runtime"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
)
// SDKVersionUserAgentHandler is a request handler for adding the SDK Version
// to the user agent.
var SDKVersionUserAgentHandler = request.NamedHandler{
Name: "core.SDKVersionUserAgentHandler",
Fn: request.MakeAddToUserAgentHandler(aws.SDKName, aws.SDKVersion,
runtime.Version(), runtime.GOOS, runtime.GOARCH),
}
const execEnvVar = `AWS_EXECUTION_ENV`
const execEnvUAKey = `exec-env`
// AddHostExecEnvUserAgentHander is a request handler appending the SDK's
// execution environment to the user agent.
//
// If the environment variable AWS_EXECUTION_ENV is set, its value will be
// appended to the user agent string.
var AddHostExecEnvUserAgentHander = request.NamedHandler{
Name: "core.AddHostExecEnvUserAgentHander",
Fn: func(r *request.Request) {
v := os.Getenv(execEnvVar)
if len(v) == 0 {
return
}
request.AddToUserAgent(r, execEnvUAKey+"/"+v)
},
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/chain_provider.go
================================================
package credentials
import (
"github.com/aws/aws-sdk-go/aws/awserr"
)
var (
// ErrNoValidProvidersFoundInChain Is returned when there are no valid
// providers in the ChainProvider.
//
// This has been deprecated. For verbose error messaging set
// aws.Config.CredentialsChainVerboseErrors to true.
ErrNoValidProvidersFoundInChain = awserr.New("NoCredentialProviders",
`no valid providers in chain. Deprecated.
For verbose messaging see aws.Config.CredentialsChainVerboseErrors`,
nil)
)
// A ChainProvider will search for a provider which returns credentials
// and cache that provider until Retrieve is called again.
//
// The ChainProvider provides a way of chaining multiple providers together
// which will pick the first available using priority order of the Providers
// in the list.
//
// If none of the Providers retrieve valid credentials Value, ChainProvider's
// Retrieve() will return the error ErrNoValidProvidersFoundInChain.
//
// If a Provider is found which returns valid credentials Value ChainProvider
// will cache that Provider for all calls to IsExpired(), until Retrieve is
// called again.
//
// Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
// In this example EnvProvider will first check if any credentials are available
// via the environment variables. If there are none ChainProvider will check
// the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
// does not return any credentials ChainProvider will return the error
// ErrNoValidProvidersFoundInChain
//
// creds := credentials.NewChainCredentials(
// []credentials.Provider{
// &credentials.EnvProvider{},
// &ec2rolecreds.EC2RoleProvider{
// Client: ec2metadata.New(sess),
// },
// })
//
// // Usage of ChainCredentials with aws.Config
// svc := ec2.New(session.Must(session.NewSession(&aws.Config{
// Credentials: creds,
// })))
//
type ChainProvider struct {
Providers []Provider
curr Provider
VerboseErrors bool
}
// NewChainCredentials returns a pointer to a new Credentials object
// wrapping a chain of providers.
func NewChainCredentials(providers []Provider) *Credentials {
return NewCredentials(&ChainProvider{
Providers: append([]Provider{}, providers...),
})
}
// Retrieve returns the credentials value or error if no provider returned
// without error.
//
// If a provider is found it will be cached and any calls to IsExpired()
// will return the expired state of the cached provider.
func (c *ChainProvider) Retrieve() (Value, error) {
var errs []error
for _, p := range c.Providers {
creds, err := p.Retrieve()
if err == nil {
c.curr = p
return creds, nil
}
errs = append(errs, err)
}
c.curr = nil
var err error
err = ErrNoValidProvidersFoundInChain
if c.VerboseErrors {
err = awserr.NewBatchError("NoCredentialProviders", "no valid providers in chain", errs)
}
return Value{}, err
}
// IsExpired will returned the expired state of the currently cached provider
// if there is one. If there is no current provider, true will be returned.
func (c *ChainProvider) IsExpired() bool {
if c.curr != nil {
return c.curr.IsExpired()
}
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/context_background_go1.5.go
================================================
//go:build !go1.7
// +build !go1.7
package credentials
import (
"github.com/aws/aws-sdk-go/internal/context"
)
// backgroundContext returns a context that will never be canceled, has no
// values, and no deadline. This context is used by the SDK to provide
// backwards compatibility with non-context API operations and functionality.
//
// Go 1.6 and before:
// This context function is equivalent to context.Background in the Go stdlib.
//
// Go 1.7 and later:
// The context returned will be the value returned by context.Background()
//
// See https://golang.org/pkg/context for more information on Contexts.
func backgroundContext() Context {
return context.BackgroundCtx
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/context_background_go1.7.go
================================================
//go:build go1.7
// +build go1.7
package credentials
import "context"
// backgroundContext returns a context that will never be canceled, has no
// values, and no deadline. This context is used by the SDK to provide
// backwards compatibility with non-context API operations and functionality.
//
// Go 1.6 and before:
// This context function is equivalent to context.Background in the Go stdlib.
//
// Go 1.7 and later:
// The context returned will be the value returned by context.Background()
//
// See https://golang.org/pkg/context for more information on Contexts.
func backgroundContext() Context {
return context.Background()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/context_go1.5.go
================================================
//go:build !go1.9
// +build !go1.9
package credentials
import "time"
// Context is an copy of the Go v1.7 stdlib's context.Context interface.
// It is represented as a SDK interface to enable you to use the "WithContext"
// API methods with Go v1.6 and a Context type such as golang.org/x/net/context.
//
// This type, aws.Context, and context.Context are equivalent.
//
// See https://golang.org/pkg/context on how to use contexts.
type Context interface {
// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
Deadline() (deadline time.Time, ok bool)
// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
Done() <-chan struct{}
// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
Err() error
// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
//
// Use context values only for request-scoped data that transits
// processes and API boundaries, not for passing optional parameters to
// functions.
Value(key interface{}) interface{}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/context_go1.9.go
================================================
//go:build go1.9
// +build go1.9
package credentials
import "context"
// Context is an alias of the Go stdlib's context.Context interface.
// It can be used within the SDK's API operation "WithContext" methods.
//
// This type, aws.Context, and context.Context are equivalent.
//
// See https://golang.org/pkg/context on how to use contexts.
type Context = context.Context
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
================================================
// Package credentials provides credential retrieval and management
//
// The Credentials is the primary method of getting access to and managing
// credentials Values. Using dependency injection retrieval of the credential
// values is handled by a object which satisfies the Provider interface.
//
// By default the Credentials.Get() will cache the successful result of a
// Provider's Retrieve() until Provider.IsExpired() returns true. At which
// point Credentials will call Provider's Retrieve() to get new credential Value.
//
// The Provider is responsible for determining when credentials Value have expired.
// It is also important to note that Credentials will always call Retrieve the
// first time Credentials.Get() is called.
//
// Example of using the environment variable credentials.
//
// creds := credentials.NewEnvCredentials()
//
// // Retrieve the credentials value
// credValue, err := creds.Get()
// if err != nil {
// // handle error
// }
//
// Example of forcing credentials to expire and be refreshed on the next Get().
// This may be helpful to proactively expire credentials and refresh them sooner
// than they would naturally expire on their own.
//
// creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{})
// creds.Expire()
// credsValue, err := creds.Get()
// // New credentials will be retrieved instead of from cache.
//
//
// Custom Provider
//
// Each Provider built into this package also provides a helper method to generate
// a Credentials pointer setup with the provider. To use a custom Provider just
// create a type which satisfies the Provider interface and pass it to the
// NewCredentials method.
//
// type MyProvider struct{}
// func (m *MyProvider) Retrieve() (Value, error) {...}
// func (m *MyProvider) IsExpired() bool {...}
//
// creds := credentials.NewCredentials(&MyProvider{})
// credValue, err := creds.Get()
//
package credentials
import (
"fmt"
"sync"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/internal/sync/singleflight"
)
// AnonymousCredentials is an empty Credential object that can be used as
// dummy placeholder credentials for requests that do not need signed.
//
// This Credentials can be used to configure a service to not sign requests
// when making service API calls. For example, when accessing public
// s3 buckets.
//
// svc := s3.New(session.Must(session.NewSession(&aws.Config{
// Credentials: credentials.AnonymousCredentials,
// })))
// // Access public S3 buckets.
var AnonymousCredentials = NewStaticCredentials("", "", "")
// A Value is the AWS credentials value for individual credential fields.
type Value struct {
// AWS Access key ID
AccessKeyID string
// AWS Secret Access Key
SecretAccessKey string
// AWS Session Token
SessionToken string
// Provider used to get credentials
ProviderName string
}
// HasKeys returns if the credentials Value has both AccessKeyID and
// SecretAccessKey value set.
func (v Value) HasKeys() bool {
return len(v.AccessKeyID) != 0 && len(v.SecretAccessKey) != 0
}
// A Provider is the interface for any component which will provide credentials
// Value. A provider is required to manage its own Expired state, and what to
// be expired means.
//
// The Provider should not need to implement its own mutexes, because
// that will be managed by Credentials.
type Provider interface {
// Retrieve returns nil if it successfully retrieved the value.
// Error is returned if the value were not obtainable, or empty.
Retrieve() (Value, error)
// IsExpired returns if the credentials are no longer valid, and need
// to be retrieved.
IsExpired() bool
}
// ProviderWithContext is a Provider that can retrieve credentials with a Context
type ProviderWithContext interface {
Provider
RetrieveWithContext(Context) (Value, error)
}
// An Expirer is an interface that Providers can implement to expose the expiration
// time, if known. If the Provider cannot accurately provide this info,
// it should not implement this interface.
type Expirer interface {
// The time at which the credentials are no longer valid
ExpiresAt() time.Time
}
// An ErrorProvider is a stub credentials provider that always returns an error
// this is used by the SDK when construction a known provider is not possible
// due to an error.
type ErrorProvider struct {
// The error to be returned from Retrieve
Err error
// The provider name to set on the Retrieved returned Value
ProviderName string
}
// Retrieve will always return the error that the ErrorProvider was created with.
func (p ErrorProvider) Retrieve() (Value, error) {
return Value{ProviderName: p.ProviderName}, p.Err
}
// IsExpired will always return not expired.
func (p ErrorProvider) IsExpired() bool {
return false
}
// A Expiry provides shared expiration logic to be used by credentials
// providers to implement expiry functionality.
//
// The best method to use this struct is as an anonymous field within the
// provider's struct.
//
// Example:
// type EC2RoleProvider struct {
// Expiry
// ...
// }
type Expiry struct {
// The date/time when to expire on
expiration time.Time
// If set will be used by IsExpired to determine the current time.
// Defaults to time.Now if CurrentTime is not set. Available for testing
// to be able to mock out the current time.
CurrentTime func() time.Time
}
// SetExpiration sets the expiration IsExpired will check when called.
//
// If window is greater than 0 the expiration time will be reduced by the
// window value.
//
// Using a window is helpful to trigger credentials to expire sooner than
// the expiration time given to ensure no requests are made with expired
// tokens.
func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
// Passed in expirations should have the monotonic clock values stripped.
// This ensures time comparisons will be based on wall-time.
e.expiration = expiration.Round(0)
if window > 0 {
e.expiration = e.expiration.Add(-window)
}
}
// IsExpired returns if the credentials are expired.
func (e *Expiry) IsExpired() bool {
curTime := e.CurrentTime
if curTime == nil {
curTime = time.Now
}
return e.expiration.Before(curTime())
}
// ExpiresAt returns the expiration time of the credential
func (e *Expiry) ExpiresAt() time.Time {
return e.expiration
}
// A Credentials provides concurrency safe retrieval of AWS credentials Value.
// Credentials will cache the credentials value until they expire. Once the value
// expires the next Get will attempt to retrieve valid credentials.
//
// Credentials is safe to use across multiple goroutines and will manage the
// synchronous state so the Providers do not need to implement their own
// synchronization.
//
// The first Credentials.Get() will always call Provider.Retrieve() to get the
// first instance of the credentials Value. All calls to Get() after that
// will return the cached credentials Value until IsExpired() returns true.
type Credentials struct {
sf singleflight.Group
m sync.RWMutex
creds Value
provider Provider
}
// NewCredentials returns a pointer to a new Credentials with the provider set.
func NewCredentials(provider Provider) *Credentials {
c := &Credentials{
provider: provider,
}
return c
}
// GetWithContext returns the credentials value, or error if the credentials
// Value failed to be retrieved. Will return early if the passed in context is
// canceled.
//
// Will return the cached credentials Value if it has not expired. If the
// credentials Value has expired the Provider's Retrieve() will be called
// to refresh the credentials.
//
// If Credentials.Expire() was called the credentials Value will be force
// expired, and the next call to Get() will cause them to be refreshed.
//
// Passed in Context is equivalent to aws.Context, and context.Context.
func (c *Credentials) GetWithContext(ctx Context) (Value, error) {
// Check if credentials are cached, and not expired.
select {
case curCreds, ok := <-c.asyncIsExpired():
// ok will only be true, of the credentials were not expired. ok will
// be false and have no value if the credentials are expired.
if ok {
return curCreds, nil
}
case <-ctx.Done():
return Value{}, awserr.New("RequestCanceled",
"request context canceled", ctx.Err())
}
// Cannot pass context down to the actual retrieve, because the first
// context would cancel the whole group when there is not direct
// association of items in the group.
resCh := c.sf.DoChan("", func() (interface{}, error) {
return c.singleRetrieve(&suppressedContext{ctx})
})
select {
case res := <-resCh:
return res.Val.(Value), res.Err
case <-ctx.Done():
return Value{}, awserr.New("RequestCanceled",
"request context canceled", ctx.Err())
}
}
func (c *Credentials) singleRetrieve(ctx Context) (interface{}, error) {
c.m.Lock()
defer c.m.Unlock()
if curCreds := c.creds; !c.isExpiredLocked(curCreds) {
return curCreds, nil
}
var creds Value
var err error
if p, ok := c.provider.(ProviderWithContext); ok {
creds, err = p.RetrieveWithContext(ctx)
} else {
creds, err = c.provider.Retrieve()
}
if err == nil {
c.creds = creds
}
return creds, err
}
// Get returns the credentials value, or error if the credentials Value failed
// to be retrieved.
//
// Will return the cached credentials Value if it has not expired. If the
// credentials Value has expired the Provider's Retrieve() will be called
// to refresh the credentials.
//
// If Credentials.Expire() was called the credentials Value will be force
// expired, and the next call to Get() will cause them to be refreshed.
func (c *Credentials) Get() (Value, error) {
return c.GetWithContext(backgroundContext())
}
// Expire expires the credentials and forces them to be retrieved on the
// next call to Get().
//
// This will override the Provider's expired state, and force Credentials
// to call the Provider's Retrieve().
func (c *Credentials) Expire() {
c.m.Lock()
defer c.m.Unlock()
c.creds = Value{}
}
// IsExpired returns if the credentials are no longer valid, and need
// to be retrieved.
//
// If the Credentials were forced to be expired with Expire() this will
// reflect that override.
func (c *Credentials) IsExpired() bool {
c.m.RLock()
defer c.m.RUnlock()
return c.isExpiredLocked(c.creds)
}
// asyncIsExpired returns a channel of credentials Value. If the channel is
// closed the credentials are expired and credentials value are not empty.
func (c *Credentials) asyncIsExpired() <-chan Value {
ch := make(chan Value, 1)
go func() {
c.m.RLock()
defer c.m.RUnlock()
if curCreds := c.creds; !c.isExpiredLocked(curCreds) {
ch <- curCreds
}
close(ch)
}()
return ch
}
// isExpiredLocked helper method wrapping the definition of expired credentials.
func (c *Credentials) isExpiredLocked(creds interface{}) bool {
return creds == nil || creds.(Value) == Value{} || c.provider.IsExpired()
}
// ExpiresAt provides access to the functionality of the Expirer interface of
// the underlying Provider, if it supports that interface. Otherwise, it returns
// an error.
func (c *Credentials) ExpiresAt() (time.Time, error) {
c.m.RLock()
defer c.m.RUnlock()
expirer, ok := c.provider.(Expirer)
if !ok {
return time.Time{}, awserr.New("ProviderNotExpirer",
fmt.Sprintf("provider %s does not support ExpiresAt()",
c.creds.ProviderName),
nil)
}
if c.creds == (Value{}) {
// set expiration time to the distant past
return time.Time{}, nil
}
return expirer.ExpiresAt(), nil
}
type suppressedContext struct {
Context
}
func (s *suppressedContext) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (s *suppressedContext) Done() <-chan struct{} {
return nil
}
func (s *suppressedContext) Err() error {
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds/ec2_role_provider.go
================================================
package ec2rolecreds
import (
"bufio"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkuri"
)
// ProviderName provides a name of EC2Role provider
const ProviderName = "EC2RoleProvider"
// A EC2RoleProvider retrieves credentials from the EC2 service, and keeps track if
// those credentials are expired.
//
// Example how to configure the EC2RoleProvider with custom http Client, Endpoint
// or ExpiryWindow
//
// p := &ec2rolecreds.EC2RoleProvider{
// // Pass in a custom timeout to be used when requesting
// // IAM EC2 Role credentials.
// Client: ec2metadata.New(sess, aws.Config{
// HTTPClient: &http.Client{Timeout: 10 * time.Second},
// }),
//
// // Do not use early expiry of credentials. If a non zero value is
// // specified the credentials will be expired early
// ExpiryWindow: 0,
// }
type EC2RoleProvider struct {
credentials.Expiry
// Required EC2Metadata client to use when connecting to EC2 metadata service.
Client *ec2metadata.EC2Metadata
// ExpiryWindow will allow the credentials to trigger refreshing prior to
// the credentials actually expiring. This is beneficial so race conditions
// with expiring credentials do not cause request to fail unexpectedly
// due to ExpiredTokenException exceptions.
//
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
// 10 seconds before the credentials are actually expired.
//
// If ExpiryWindow is 0 or less it will be ignored.
ExpiryWindow time.Duration
}
// NewCredentials returns a pointer to a new Credentials object wrapping
// the EC2RoleProvider. Takes a ConfigProvider to create a EC2Metadata client.
// The ConfigProvider is satisfied by the session.Session type.
func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials {
p := &EC2RoleProvider{
Client: ec2metadata.New(c),
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
// NewCredentialsWithClient returns a pointer to a new Credentials object wrapping
// the EC2RoleProvider. Takes a EC2Metadata client to use when connecting to EC2
// metadata service.
func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*EC2RoleProvider)) *credentials.Credentials {
p := &EC2RoleProvider{
Client: client,
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
// Retrieve retrieves credentials from the EC2 service.
// Error will be returned if the request fails, or unable to extract
// the desired credentials.
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
return m.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext retrieves credentials from the EC2 service.
// Error will be returned if the request fails, or unable to extract
// the desired credentials.
func (m *EC2RoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
credsList, err := requestCredList(ctx, m.Client)
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
if len(credsList) == 0 {
return credentials.Value{ProviderName: ProviderName}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
}
credsName := credsList[0]
roleCreds, err := requestCred(ctx, m.Client, credsName)
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
return credentials.Value{
AccessKeyID: roleCreds.AccessKeyID,
SecretAccessKey: roleCreds.SecretAccessKey,
SessionToken: roleCreds.Token,
ProviderName: ProviderName,
}, nil
}
// A ec2RoleCredRespBody provides the shape for unmarshaling credential
// request responses.
type ec2RoleCredRespBody struct {
// Success State
Expiration time.Time
AccessKeyID string
SecretAccessKey string
Token string
// Error state
Code string
Message string
}
const iamSecurityCredsPath = "iam/security-credentials/"
// requestCredList requests a list of credentials from the EC2 service.
// If there are no credentials, or there is an error making or receiving the request
func requestCredList(ctx aws.Context, client *ec2metadata.EC2Metadata) ([]string, error) {
resp, err := client.GetMetadataWithContext(ctx, iamSecurityCredsPath)
if err != nil {
return nil, awserr.New("EC2RoleRequestError", "no EC2 instance role found", err)
}
credsList := []string{}
s := bufio.NewScanner(strings.NewReader(resp))
for s.Scan() {
credsList = append(credsList, s.Text())
}
if err := s.Err(); err != nil {
return nil, awserr.New(request.ErrCodeSerialization,
"failed to read EC2 instance role from metadata service", err)
}
return credsList, nil
}
// requestCred requests the credentials for a specific credentials from the EC2 service.
//
// If the credentials cannot be found, or there is an error reading the response
// and error will be returned.
func requestCred(ctx aws.Context, client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
resp, err := client.GetMetadataWithContext(ctx, sdkuri.PathJoin(iamSecurityCredsPath, credsName))
if err != nil {
return ec2RoleCredRespBody{},
awserr.New("EC2RoleRequestError",
fmt.Sprintf("failed to get %s EC2 instance role credentials", credsName),
err)
}
respCreds := ec2RoleCredRespBody{}
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
return ec2RoleCredRespBody{},
awserr.New(request.ErrCodeSerialization,
fmt.Sprintf("failed to decode %s EC2 instance role credentials", credsName),
err)
}
if respCreds.Code != "Success" {
// If an error code was returned something failed requesting the role.
return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil)
}
return respCreds, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/endpointcreds/provider.go
================================================
// Package endpointcreds provides support for retrieving credentials from an
// arbitrary HTTP endpoint.
//
// The credentials endpoint Provider can receive both static and refreshable
// credentials that will expire. Credentials are static when an "Expiration"
// value is not provided in the endpoint's response.
//
// Static credentials will never expire once they have been retrieved. The format
// of the static credentials response:
// {
// "AccessKeyId" : "MUA...",
// "SecretAccessKey" : "/7PC5om....",
// }
//
// Refreshable credentials will expire within the "ExpiryWindow" of the Expiration
// value in the response. The format of the refreshable credentials response:
// {
// "AccessKeyId" : "MUA...",
// "SecretAccessKey" : "/7PC5om....",
// "Token" : "AQoDY....=",
// "Expiration" : "2016-02-25T06:03:31Z"
// }
//
// Errors should be returned in the following format and only returned with 400
// or 500 HTTP status codes.
// {
// "code": "ErrorCode",
// "message": "Helpful error message."
// }
package endpointcreds
import (
"encoding/json"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
)
// ProviderName is the name of the credentials provider.
const ProviderName = `CredentialsEndpointProvider`
// Provider satisfies the credentials.Provider interface, and is a client to
// retrieve credentials from an arbitrary endpoint.
type Provider struct {
staticCreds bool
credentials.Expiry
// Requires a AWS Client to make HTTP requests to the endpoint with.
// the Endpoint the request will be made to is provided by the aws.Config's
// Endpoint value.
Client *client.Client
// ExpiryWindow will allow the credentials to trigger refreshing prior to
// the credentials actually expiring. This is beneficial so race conditions
// with expiring credentials do not cause request to fail unexpectedly
// due to ExpiredTokenException exceptions.
//
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
// 10 seconds before the credentials are actually expired.
//
// If ExpiryWindow is 0 or less it will be ignored.
ExpiryWindow time.Duration
// Optional authorization token value if set will be used as the value of
// the Authorization header of the endpoint credential request.
AuthorizationToken string
}
// NewProviderClient returns a credentials Provider for retrieving AWS credentials
// from arbitrary endpoint.
func NewProviderClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) credentials.Provider {
p := &Provider{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: "CredentialsEndpoint",
Endpoint: endpoint,
},
handlers,
),
}
p.Client.Handlers.Unmarshal.PushBack(unmarshalHandler)
p.Client.Handlers.UnmarshalError.PushBack(unmarshalError)
p.Client.Handlers.Validate.Clear()
p.Client.Handlers.Validate.PushBack(validateEndpointHandler)
for _, option := range options {
option(p)
}
return p
}
// NewCredentialsClient returns a pointer to a new Credentials object
// wrapping the endpoint credentials Provider.
func NewCredentialsClient(cfg aws.Config, handlers request.Handlers, endpoint string, options ...func(*Provider)) *credentials.Credentials {
return credentials.NewCredentials(NewProviderClient(cfg, handlers, endpoint, options...))
}
// IsExpired returns true if the credentials retrieved are expired, or not yet
// retrieved.
func (p *Provider) IsExpired() bool {
if p.staticCreds {
return false
}
return p.Expiry.IsExpired()
}
// Retrieve will attempt to request the credentials from the endpoint the Provider
// was configured for. And error will be returned if the retrieval fails.
func (p *Provider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext will attempt to request the credentials from the endpoint the Provider
// was configured for. And error will be returned if the retrieval fails.
func (p *Provider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
resp, err := p.getCredentials(ctx)
if err != nil {
return credentials.Value{ProviderName: ProviderName},
awserr.New("CredentialsEndpointError", "failed to load credentials", err)
}
if resp.Expiration != nil {
p.SetExpiration(*resp.Expiration, p.ExpiryWindow)
} else {
p.staticCreds = true
}
return credentials.Value{
AccessKeyID: resp.AccessKeyID,
SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.Token,
ProviderName: ProviderName,
}, nil
}
type getCredentialsOutput struct {
Expiration *time.Time
AccessKeyID string
SecretAccessKey string
Token string
}
type errorOutput struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (p *Provider) getCredentials(ctx aws.Context) (*getCredentialsOutput, error) {
op := &request.Operation{
Name: "GetCredentials",
HTTPMethod: "GET",
}
out := &getCredentialsOutput{}
req := p.Client.NewRequest(op, nil, out)
req.SetContext(ctx)
req.HTTPRequest.Header.Set("Accept", "application/json")
if authToken := p.AuthorizationToken; len(authToken) != 0 {
req.HTTPRequest.Header.Set("Authorization", authToken)
}
return out, req.Send()
}
func validateEndpointHandler(r *request.Request) {
if len(r.ClientInfo.Endpoint) == 0 {
r.Error = aws.ErrMissingEndpoint
}
}
func unmarshalHandler(r *request.Request) {
defer r.HTTPResponse.Body.Close()
out := r.Data.(*getCredentialsOutput)
if err := json.NewDecoder(r.HTTPResponse.Body).Decode(&out); err != nil {
r.Error = awserr.New(request.ErrCodeSerialization,
"failed to decode endpoint credentials",
err,
)
}
}
func unmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var errOut errorOutput
err := jsonutil.UnmarshalJSONError(&errOut, r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to decode error message", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
// Response body format is not consistent between metadata endpoints.
// Grab the error message as a string and include that as the source error
r.Error = awserr.New(errOut.Code, errOut.Message, nil)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/env_provider.go
================================================
package credentials
import (
"os"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// EnvProviderName provides a name of Env provider
const EnvProviderName = "EnvProvider"
var (
// ErrAccessKeyIDNotFound is returned when the AWS Access Key ID can't be
// found in the process's environment.
ErrAccessKeyIDNotFound = awserr.New("EnvAccessKeyNotFound", "AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY not found in environment", nil)
// ErrSecretAccessKeyNotFound is returned when the AWS Secret Access Key
// can't be found in the process's environment.
ErrSecretAccessKeyNotFound = awserr.New("EnvSecretNotFound", "AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY not found in environment", nil)
)
// A EnvProvider retrieves credentials from the environment variables of the
// running process. Environment credentials never expire.
//
// Environment variables used:
//
// * Access Key ID: AWS_ACCESS_KEY_ID or AWS_ACCESS_KEY
//
// * Secret Access Key: AWS_SECRET_ACCESS_KEY or AWS_SECRET_KEY
type EnvProvider struct {
retrieved bool
}
// NewEnvCredentials returns a pointer to a new Credentials object
// wrapping the environment variable provider.
func NewEnvCredentials() *Credentials {
return NewCredentials(&EnvProvider{})
}
// Retrieve retrieves the keys from the environment.
func (e *EnvProvider) Retrieve() (Value, error) {
e.retrieved = false
id := os.Getenv("AWS_ACCESS_KEY_ID")
if id == "" {
id = os.Getenv("AWS_ACCESS_KEY")
}
secret := os.Getenv("AWS_SECRET_ACCESS_KEY")
if secret == "" {
secret = os.Getenv("AWS_SECRET_KEY")
}
if id == "" {
return Value{ProviderName: EnvProviderName}, ErrAccessKeyIDNotFound
}
if secret == "" {
return Value{ProviderName: EnvProviderName}, ErrSecretAccessKeyNotFound
}
e.retrieved = true
return Value{
AccessKeyID: id,
SecretAccessKey: secret,
SessionToken: os.Getenv("AWS_SESSION_TOKEN"),
ProviderName: EnvProviderName,
}, nil
}
// IsExpired returns if the credentials have been retrieved.
func (e *EnvProvider) IsExpired() bool {
return !e.retrieved
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/example.ini
================================================
[default]
aws_access_key_id = accessKey
aws_secret_access_key = secret
aws_session_token = token
[no_token]
aws_access_key_id = accessKey
aws_secret_access_key = secret
[with_colon]
aws_access_key_id: accessKey
aws_secret_access_key: secret
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/processcreds/provider.go
================================================
/*
Package processcreds is a credential Provider to retrieve `credential_process`
credentials.
WARNING: The following describes a method of sourcing credentials from an external
process. This can potentially be dangerous, so proceed with caution. Other
credential providers should be preferred if at all possible. If using this
option, you should make sure that the config file is as locked down as possible
using security best practices for your operating system.
You can use credentials from a `credential_process` in a variety of ways.
One way is to setup your shared config file, located in the default
location, with the `credential_process` key and the command you want to be
called. You also need to set the AWS_SDK_LOAD_CONFIG environment variable
(e.g., `export AWS_SDK_LOAD_CONFIG=1`) to use the shared config file.
[default]
credential_process = /command/to/call
Creating a new session will use the credential process to retrieve credentials.
NOTE: If there are credentials in the profile you are using, the credential
process will not be used.
// Initialize a session to load credentials.
sess, _ := session.NewSession(&aws.Config{
Region: aws.String("us-east-1")},
)
// Create S3 service client to use the credentials.
svc := s3.New(sess)
Another way to use the `credential_process` method is by using
`credentials.NewCredentials()` and providing a command to be executed to
retrieve credentials:
// Create credentials using the ProcessProvider.
creds := processcreds.NewCredentials("/path/to/command")
// Create service client value configured for credentials.
svc := s3.New(sess, &aws.Config{Credentials: creds})
You can set a non-default timeout for the `credential_process` with another
constructor, `credentials.NewCredentialsTimeout()`, providing the timeout. To
set a one minute timeout:
// Create credentials using the ProcessProvider.
creds := processcreds.NewCredentialsTimeout(
"/path/to/command",
time.Duration(500) * time.Millisecond)
If you need more control, you can set any configurable options in the
credentials using one or more option functions. For example, you can set a two
minute timeout, a credential duration of 60 minutes, and a maximum stdout
buffer size of 2k.
creds := processcreds.NewCredentials(
"/path/to/command",
func(opt *ProcessProvider) {
opt.Timeout = time.Duration(2) * time.Minute
opt.Duration = time.Duration(60) * time.Minute
opt.MaxBufSize = 2048
})
You can also use your own `exec.Cmd`:
// Create an exec.Cmd
myCommand := exec.Command("/path/to/command")
// Create credentials using your exec.Cmd and custom timeout
creds := processcreds.NewCredentialsCommand(
myCommand,
func(opt *processcreds.ProcessProvider) {
opt.Timeout = time.Duration(1) * time.Second
})
*/
package processcreds
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"runtime"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/internal/sdkio"
)
const (
// ProviderName is the name this credentials provider will label any
// returned credentials Value with.
ProviderName = `ProcessProvider`
// ErrCodeProcessProviderParse error parsing process output
ErrCodeProcessProviderParse = "ProcessProviderParseError"
// ErrCodeProcessProviderVersion version error in output
ErrCodeProcessProviderVersion = "ProcessProviderVersionError"
// ErrCodeProcessProviderRequired required attribute missing in output
ErrCodeProcessProviderRequired = "ProcessProviderRequiredError"
// ErrCodeProcessProviderExecution execution of command failed
ErrCodeProcessProviderExecution = "ProcessProviderExecutionError"
// errMsgProcessProviderTimeout process took longer than allowed
errMsgProcessProviderTimeout = "credential process timed out"
// errMsgProcessProviderProcess process error
errMsgProcessProviderProcess = "error in credential_process"
// errMsgProcessProviderParse problem parsing output
errMsgProcessProviderParse = "parse failed of credential_process output"
// errMsgProcessProviderVersion version error in output
errMsgProcessProviderVersion = "wrong version in process output (not 1)"
// errMsgProcessProviderMissKey missing access key id in output
errMsgProcessProviderMissKey = "missing AccessKeyId in process output"
// errMsgProcessProviderMissSecret missing secret acess key in output
errMsgProcessProviderMissSecret = "missing SecretAccessKey in process output"
// errMsgProcessProviderPrepareCmd prepare of command failed
errMsgProcessProviderPrepareCmd = "failed to prepare command"
// errMsgProcessProviderEmptyCmd command must not be empty
errMsgProcessProviderEmptyCmd = "command must not be empty"
// errMsgProcessProviderPipe failed to initialize pipe
errMsgProcessProviderPipe = "failed to initialize pipe"
// DefaultDuration is the default amount of time in minutes that the
// credentials will be valid for.
DefaultDuration = time.Duration(15) * time.Minute
// DefaultBufSize limits buffer size from growing to an enormous
// amount due to a faulty process.
DefaultBufSize = int(8 * sdkio.KibiByte)
// DefaultTimeout default limit on time a process can run.
DefaultTimeout = time.Duration(1) * time.Minute
)
// ProcessProvider satisfies the credentials.Provider interface, and is a
// client to retrieve credentials from a process.
type ProcessProvider struct {
staticCreds bool
credentials.Expiry
originalCommand []string
// Expiry duration of the credentials. Defaults to 15 minutes if not set.
Duration time.Duration
// ExpiryWindow will allow the credentials to trigger refreshing prior to
// the credentials actually expiring. This is beneficial so race conditions
// with expiring credentials do not cause request to fail unexpectedly
// due to ExpiredTokenException exceptions.
//
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
// 10 seconds before the credentials are actually expired.
//
// If ExpiryWindow is 0 or less it will be ignored.
ExpiryWindow time.Duration
// A string representing an os command that should return a JSON with
// credential information.
command *exec.Cmd
// MaxBufSize limits memory usage from growing to an enormous
// amount due to a faulty process.
MaxBufSize int
// Timeout limits the time a process can run.
Timeout time.Duration
}
// NewCredentials returns a pointer to a new Credentials object wrapping the
// ProcessProvider. The credentials will expire every 15 minutes by default.
func NewCredentials(command string, options ...func(*ProcessProvider)) *credentials.Credentials {
p := &ProcessProvider{
command: exec.Command(command),
Duration: DefaultDuration,
Timeout: DefaultTimeout,
MaxBufSize: DefaultBufSize,
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
// NewCredentialsTimeout returns a pointer to a new Credentials object with
// the specified command and timeout, and default duration and max buffer size.
func NewCredentialsTimeout(command string, timeout time.Duration) *credentials.Credentials {
p := NewCredentials(command, func(opt *ProcessProvider) {
opt.Timeout = timeout
})
return p
}
// NewCredentialsCommand returns a pointer to a new Credentials object with
// the specified command, and default timeout, duration and max buffer size.
func NewCredentialsCommand(command *exec.Cmd, options ...func(*ProcessProvider)) *credentials.Credentials {
p := &ProcessProvider{
command: command,
Duration: DefaultDuration,
Timeout: DefaultTimeout,
MaxBufSize: DefaultBufSize,
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
type credentialProcessResponse struct {
Version int
AccessKeyID string `json:"AccessKeyId"`
SecretAccessKey string
SessionToken string
Expiration *time.Time
}
// Retrieve executes the 'credential_process' and returns the credentials.
func (p *ProcessProvider) Retrieve() (credentials.Value, error) {
out, err := p.executeCredentialProcess()
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
// Serialize and validate response
resp := &credentialProcessResponse{}
if err = json.Unmarshal(out, resp); err != nil {
return credentials.Value{ProviderName: ProviderName}, awserr.New(
ErrCodeProcessProviderParse,
fmt.Sprintf("%s: %s", errMsgProcessProviderParse, string(out)),
err)
}
if resp.Version != 1 {
return credentials.Value{ProviderName: ProviderName}, awserr.New(
ErrCodeProcessProviderVersion,
errMsgProcessProviderVersion,
nil)
}
if len(resp.AccessKeyID) == 0 {
return credentials.Value{ProviderName: ProviderName}, awserr.New(
ErrCodeProcessProviderRequired,
errMsgProcessProviderMissKey,
nil)
}
if len(resp.SecretAccessKey) == 0 {
return credentials.Value{ProviderName: ProviderName}, awserr.New(
ErrCodeProcessProviderRequired,
errMsgProcessProviderMissSecret,
nil)
}
// Handle expiration
p.staticCreds = resp.Expiration == nil
if resp.Expiration != nil {
p.SetExpiration(*resp.Expiration, p.ExpiryWindow)
}
return credentials.Value{
ProviderName: ProviderName,
AccessKeyID: resp.AccessKeyID,
SecretAccessKey: resp.SecretAccessKey,
SessionToken: resp.SessionToken,
}, nil
}
// IsExpired returns true if the credentials retrieved are expired, or not yet
// retrieved.
func (p *ProcessProvider) IsExpired() bool {
if p.staticCreds {
return false
}
return p.Expiry.IsExpired()
}
// prepareCommand prepares the command to be executed.
func (p *ProcessProvider) prepareCommand() error {
var cmdArgs []string
if runtime.GOOS == "windows" {
cmdArgs = []string{"cmd.exe", "/C"}
} else {
cmdArgs = []string{"sh", "-c"}
}
if len(p.originalCommand) == 0 {
p.originalCommand = make([]string, len(p.command.Args))
copy(p.originalCommand, p.command.Args)
// check for empty command because it succeeds
if len(strings.TrimSpace(p.originalCommand[0])) < 1 {
return awserr.New(
ErrCodeProcessProviderExecution,
fmt.Sprintf(
"%s: %s",
errMsgProcessProviderPrepareCmd,
errMsgProcessProviderEmptyCmd),
nil)
}
}
cmdArgs = append(cmdArgs, p.originalCommand...)
p.command = exec.Command(cmdArgs[0], cmdArgs[1:]...)
p.command.Env = os.Environ()
return nil
}
// executeCredentialProcess starts the credential process on the OS and
// returns the results or an error.
func (p *ProcessProvider) executeCredentialProcess() ([]byte, error) {
if err := p.prepareCommand(); err != nil {
return nil, err
}
// Setup the pipes
outReadPipe, outWritePipe, err := os.Pipe()
if err != nil {
return nil, awserr.New(
ErrCodeProcessProviderExecution,
errMsgProcessProviderPipe,
err)
}
p.command.Stderr = os.Stderr // display stderr on console for MFA
p.command.Stdout = outWritePipe // get creds json on process's stdout
p.command.Stdin = os.Stdin // enable stdin for MFA
output := bytes.NewBuffer(make([]byte, 0, p.MaxBufSize))
stdoutCh := make(chan error, 1)
go readInput(
io.LimitReader(outReadPipe, int64(p.MaxBufSize)),
output,
stdoutCh)
execCh := make(chan error, 1)
go executeCommand(*p.command, execCh)
finished := false
var errors []error
for !finished {
select {
case readError := <-stdoutCh:
errors = appendError(errors, readError)
finished = true
case execError := <-execCh:
err := outWritePipe.Close()
errors = appendError(errors, err)
errors = appendError(errors, execError)
if errors != nil {
return output.Bytes(), awserr.NewBatchError(
ErrCodeProcessProviderExecution,
errMsgProcessProviderProcess,
errors)
}
case <-time.After(p.Timeout):
finished = true
return output.Bytes(), awserr.NewBatchError(
ErrCodeProcessProviderExecution,
errMsgProcessProviderTimeout,
errors) // errors can be nil
}
}
out := output.Bytes()
if runtime.GOOS == "windows" {
// windows adds slashes to quotes
out = []byte(strings.Replace(string(out), `\"`, `"`, -1))
}
return out, nil
}
// appendError conveniently checks for nil before appending slice
func appendError(errors []error, err error) []error {
if err != nil {
return append(errors, err)
}
return errors
}
func executeCommand(cmd exec.Cmd, exec chan error) {
// Start the command
err := cmd.Start()
if err == nil {
err = cmd.Wait()
}
exec <- err
}
func readInput(r io.Reader, w io.Writer, read chan error) {
tee := io.TeeReader(r, w)
_, err := ioutil.ReadAll(tee)
if err == io.EOF {
err = nil
}
read <- err // will only arrive here when write end of pipe is closed
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/shared_credentials_provider.go
================================================
package credentials
import (
"fmt"
"os"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/internal/ini"
"github.com/aws/aws-sdk-go/internal/shareddefaults"
)
// SharedCredsProviderName provides a name of SharedCreds provider
const SharedCredsProviderName = "SharedCredentialsProvider"
var (
// ErrSharedCredentialsHomeNotFound is emitted when the user directory cannot be found.
ErrSharedCredentialsHomeNotFound = awserr.New("UserHomeNotFound", "user home directory not found.", nil)
)
// A SharedCredentialsProvider retrieves access key pair (access key ID,
// secret access key, and session token if present) credentials from the current
// user's home directory, and keeps track if those credentials are expired.
//
// Profile ini file example: $HOME/.aws/credentials
type SharedCredentialsProvider struct {
// Path to the shared credentials file.
//
// If empty will look for "AWS_SHARED_CREDENTIALS_FILE" env variable. If the
// env value is empty will default to current user's home directory.
// Linux/OSX: "$HOME/.aws/credentials"
// Windows: "%USERPROFILE%\.aws\credentials"
Filename string
// AWS Profile to extract credentials from the shared credentials file. If empty
// will default to environment variable "AWS_PROFILE" or "default" if
// environment variable is also not set.
Profile string
// retrieved states if the credentials have been successfully retrieved.
retrieved bool
}
// NewSharedCredentials returns a pointer to a new Credentials object
// wrapping the Profile file provider.
func NewSharedCredentials(filename, profile string) *Credentials {
return NewCredentials(&SharedCredentialsProvider{
Filename: filename,
Profile: profile,
})
}
// Retrieve reads and extracts the shared credentials from the current
// users home directory.
func (p *SharedCredentialsProvider) Retrieve() (Value, error) {
p.retrieved = false
filename, err := p.filename()
if err != nil {
return Value{ProviderName: SharedCredsProviderName}, err
}
creds, err := loadProfile(filename, p.profile())
if err != nil {
return Value{ProviderName: SharedCredsProviderName}, err
}
p.retrieved = true
return creds, nil
}
// IsExpired returns if the shared credentials have expired.
func (p *SharedCredentialsProvider) IsExpired() bool {
return !p.retrieved
}
// loadProfiles loads from the file pointed to by shared credentials filename for profile.
// The credentials retrieved from the profile will be returned or error. Error will be
// returned if it fails to read from the file, or the data is invalid.
func loadProfile(filename, profile string) (Value, error) {
config, err := ini.OpenFile(filename)
if err != nil {
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to load shared credentials file", err)
}
iniProfile, ok := config.GetSection(profile)
if !ok {
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsLoad", "failed to get profile", nil)
}
id := iniProfile.String("aws_access_key_id")
if len(id) == 0 {
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsAccessKey",
fmt.Sprintf("shared credentials %s in %s did not contain aws_access_key_id", profile, filename),
nil)
}
secret := iniProfile.String("aws_secret_access_key")
if len(secret) == 0 {
return Value{ProviderName: SharedCredsProviderName}, awserr.New("SharedCredsSecret",
fmt.Sprintf("shared credentials %s in %s did not contain aws_secret_access_key", profile, filename),
nil)
}
// Default to empty string if not found
token := iniProfile.String("aws_session_token")
return Value{
AccessKeyID: id,
SecretAccessKey: secret,
SessionToken: token,
ProviderName: SharedCredsProviderName,
}, nil
}
// filename returns the filename to use to read AWS shared credentials.
//
// Will return an error if the user's home directory path cannot be found.
func (p *SharedCredentialsProvider) filename() (string, error) {
if len(p.Filename) != 0 {
return p.Filename, nil
}
if p.Filename = os.Getenv("AWS_SHARED_CREDENTIALS_FILE"); len(p.Filename) != 0 {
return p.Filename, nil
}
if home := shareddefaults.UserHomeDir(); len(home) == 0 {
// Backwards compatibility of home directly not found error being returned.
// This error is too verbose, failure when opening the file would of been
// a better error to return.
return "", ErrSharedCredentialsHomeNotFound
}
p.Filename = shareddefaults.SharedCredentialsFilename()
return p.Filename, nil
}
// profile returns the AWS shared credentials profile. If empty will read
// environment variable "AWS_PROFILE". If that is not set profile will
// return "default".
func (p *SharedCredentialsProvider) profile() string {
if p.Profile == "" {
p.Profile = os.Getenv("AWS_PROFILE")
}
if p.Profile == "" {
p.Profile = "default"
}
return p.Profile
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/ssocreds/doc.go
================================================
// Package ssocreds provides a credential provider for retrieving temporary AWS credentials using an SSO access token.
//
// IMPORTANT: The provider in this package does not initiate or perform the AWS SSO login flow. The SDK provider
// expects that you have already performed the SSO login flow using AWS CLI using the "aws sso login" command, or by
// some other mechanism. The provider must find a valid non-expired access token for the AWS SSO user portal URL in
// ~/.aws/sso/cache. If a cached token is not found, it is expired, or the file is malformed an error will be returned.
//
// Loading AWS SSO credentials with the AWS shared configuration file
//
// You can use configure AWS SSO credentials from the AWS shared configuration file by
// providing the specifying the required keys in the profile:
//
// sso_account_id
// sso_region
// sso_role_name
// sso_start_url
//
// For example, the following defines a profile "devsso" and specifies the AWS SSO parameters that defines the target
// account, role, sign-on portal, and the region where the user portal is located. Note: all SSO arguments must be
// provided, or an error will be returned.
//
// [profile devsso]
// sso_start_url = https://my-sso-portal.awsapps.com/start
// sso_role_name = SSOReadOnlyRole
// sso_region = us-east-1
// sso_account_id = 123456789012
//
// Using the config module, you can load the AWS SDK shared configuration, and specify that this profile be used to
// retrieve credentials. For example:
//
// sess, err := session.NewSessionWithOptions(session.Options{
// SharedConfigState: session.SharedConfigEnable,
// Profile: "devsso",
// })
// if err != nil {
// return err
// }
//
// Programmatically loading AWS SSO credentials directly
//
// You can programmatically construct the AWS SSO Provider in your application, and provide the necessary information
// to load and retrieve temporary credentials using an access token from ~/.aws/sso/cache.
//
// svc := sso.New(sess, &aws.Config{
// Region: aws.String("us-west-2"), // Client Region must correspond to the AWS SSO user portal region
// })
//
// provider := ssocreds.NewCredentialsWithClient(svc, "123456789012", "SSOReadOnlyRole", "https://my-sso-portal.awsapps.com/start")
//
// credentials, err := provider.Get()
// if err != nil {
// return err
// }
//
// Additional Resources
//
// Configuring the AWS CLI to use AWS Single Sign-On: https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html
//
// AWS Single Sign-On User Guide: https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html
package ssocreds
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/ssocreds/os.go
================================================
//go:build !windows
// +build !windows
package ssocreds
import "os"
func getHomeDirectory() string {
return os.Getenv("HOME")
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/ssocreds/os_windows.go
================================================
package ssocreds
import "os"
func getHomeDirectory() string {
return os.Getenv("USERPROFILE")
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/ssocreds/provider.go
================================================
package ssocreds
import (
"crypto/sha1"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/service/sso"
"github.com/aws/aws-sdk-go/service/sso/ssoiface"
)
// ErrCodeSSOProviderInvalidToken is the code type that is returned if loaded token has expired or is otherwise invalid.
// To refresh the SSO session run aws sso login with the corresponding profile.
const ErrCodeSSOProviderInvalidToken = "SSOProviderInvalidToken"
const invalidTokenMessage = "the SSO session has expired or is invalid"
func init() {
nowTime = time.Now
defaultCacheLocation = defaultCacheLocationImpl
}
var nowTime func() time.Time
// ProviderName is the name of the provider used to specify the source of credentials.
const ProviderName = "SSOProvider"
var defaultCacheLocation func() string
func defaultCacheLocationImpl() string {
return filepath.Join(getHomeDirectory(), ".aws", "sso", "cache")
}
// Provider is an AWS credential provider that retrieves temporary AWS credentials by exchanging an SSO login token.
type Provider struct {
credentials.Expiry
// The Client which is configured for the AWS Region where the AWS SSO user portal is located.
Client ssoiface.SSOAPI
// The AWS account that is assigned to the user.
AccountID string
// The role name that is assigned to the user.
RoleName string
// The URL that points to the organization's AWS Single Sign-On (AWS SSO) user portal.
StartURL string
}
// NewCredentials returns a new AWS Single Sign-On (AWS SSO) credential provider. The ConfigProvider is expected to be configured
// for the AWS Region where the AWS SSO user portal is located.
func NewCredentials(configProvider client.ConfigProvider, accountID, roleName, startURL string, optFns ...func(provider *Provider)) *credentials.Credentials {
return NewCredentialsWithClient(sso.New(configProvider), accountID, roleName, startURL, optFns...)
}
// NewCredentialsWithClient returns a new AWS Single Sign-On (AWS SSO) credential provider. The provided client is expected to be configured
// for the AWS Region where the AWS SSO user portal is located.
func NewCredentialsWithClient(client ssoiface.SSOAPI, accountID, roleName, startURL string, optFns ...func(provider *Provider)) *credentials.Credentials {
p := &Provider{
Client: client,
AccountID: accountID,
RoleName: roleName,
StartURL: startURL,
}
for _, fn := range optFns {
fn(p)
}
return credentials.NewCredentials(p)
}
// Retrieve retrieves temporary AWS credentials from the configured Amazon Single Sign-On (AWS SSO) user portal
// by exchanging the accessToken present in ~/.aws/sso/cache.
func (p *Provider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext retrieves temporary AWS credentials from the configured Amazon Single Sign-On (AWS SSO) user portal
// by exchanging the accessToken present in ~/.aws/sso/cache.
func (p *Provider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
tokenFile, err := loadTokenFile(p.StartURL)
if err != nil {
return credentials.Value{}, err
}
output, err := p.Client.GetRoleCredentialsWithContext(ctx, &sso.GetRoleCredentialsInput{
AccessToken: &tokenFile.AccessToken,
AccountId: &p.AccountID,
RoleName: &p.RoleName,
})
if err != nil {
return credentials.Value{}, err
}
expireTime := time.Unix(0, aws.Int64Value(output.RoleCredentials.Expiration)*int64(time.Millisecond)).UTC()
p.SetExpiration(expireTime, 0)
return credentials.Value{
AccessKeyID: aws.StringValue(output.RoleCredentials.AccessKeyId),
SecretAccessKey: aws.StringValue(output.RoleCredentials.SecretAccessKey),
SessionToken: aws.StringValue(output.RoleCredentials.SessionToken),
ProviderName: ProviderName,
}, nil
}
func getCacheFileName(url string) (string, error) {
hash := sha1.New()
_, err := hash.Write([]byte(url))
if err != nil {
return "", err
}
return strings.ToLower(hex.EncodeToString(hash.Sum(nil))) + ".json", nil
}
type rfc3339 time.Time
func (r *rfc3339) UnmarshalJSON(bytes []byte) error {
var value string
if err := json.Unmarshal(bytes, &value); err != nil {
return err
}
parse, err := time.Parse(time.RFC3339, value)
if err != nil {
return fmt.Errorf("expected RFC3339 timestamp: %v", err)
}
*r = rfc3339(parse)
return nil
}
type token struct {
AccessToken string `json:"accessToken"`
ExpiresAt rfc3339 `json:"expiresAt"`
Region string `json:"region,omitempty"`
StartURL string `json:"startUrl,omitempty"`
}
func (t token) Expired() bool {
return nowTime().Round(0).After(time.Time(t.ExpiresAt))
}
func loadTokenFile(startURL string) (t token, err error) {
key, err := getCacheFileName(startURL)
if err != nil {
return token{}, awserr.New(ErrCodeSSOProviderInvalidToken, invalidTokenMessage, err)
}
fileBytes, err := ioutil.ReadFile(filepath.Join(defaultCacheLocation(), key))
if err != nil {
return token{}, awserr.New(ErrCodeSSOProviderInvalidToken, invalidTokenMessage, err)
}
if err := json.Unmarshal(fileBytes, &t); err != nil {
return token{}, awserr.New(ErrCodeSSOProviderInvalidToken, invalidTokenMessage, err)
}
if len(t.AccessToken) == 0 {
return token{}, awserr.New(ErrCodeSSOProviderInvalidToken, invalidTokenMessage, nil)
}
if t.Expired() {
return token{}, awserr.New(ErrCodeSSOProviderInvalidToken, invalidTokenMessage, nil)
}
return t, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/static_provider.go
================================================
package credentials
import (
"github.com/aws/aws-sdk-go/aws/awserr"
)
// StaticProviderName provides a name of Static provider
const StaticProviderName = "StaticProvider"
var (
// ErrStaticCredentialsEmpty is emitted when static credentials are empty.
ErrStaticCredentialsEmpty = awserr.New("EmptyStaticCreds", "static credentials are empty", nil)
)
// A StaticProvider is a set of credentials which are set programmatically,
// and will never expire.
type StaticProvider struct {
Value
}
// NewStaticCredentials returns a pointer to a new Credentials object
// wrapping a static credentials value provider. Token is only required
// for temporary security credentials retrieved via STS, otherwise an empty
// string can be passed for this parameter.
func NewStaticCredentials(id, secret, token string) *Credentials {
return NewCredentials(&StaticProvider{Value: Value{
AccessKeyID: id,
SecretAccessKey: secret,
SessionToken: token,
}})
}
// NewStaticCredentialsFromCreds returns a pointer to a new Credentials object
// wrapping the static credentials value provide. Same as NewStaticCredentials
// but takes the creds Value instead of individual fields
func NewStaticCredentialsFromCreds(creds Value) *Credentials {
return NewCredentials(&StaticProvider{Value: creds})
}
// Retrieve returns the credentials or error if the credentials are invalid.
func (s *StaticProvider) Retrieve() (Value, error) {
if s.AccessKeyID == "" || s.SecretAccessKey == "" {
return Value{ProviderName: StaticProviderName}, ErrStaticCredentialsEmpty
}
if len(s.Value.ProviderName) == 0 {
s.Value.ProviderName = StaticProviderName
}
return s.Value, nil
}
// IsExpired returns if the credentials are expired.
//
// For StaticProvider, the credentials never expired.
func (s *StaticProvider) IsExpired() bool {
return false
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/assume_role_provider.go
================================================
/*
Package stscreds are credential Providers to retrieve STS AWS credentials.
STS provides multiple ways to retrieve credentials which can be used when making
future AWS service API operation calls.
The SDK will ensure that per instance of credentials.Credentials all requests
to refresh the credentials will be synchronized. But, the SDK is unable to
ensure synchronous usage of the AssumeRoleProvider if the value is shared
between multiple Credentials, Sessions or service clients.
Assume Role
To assume an IAM role using STS with the SDK you can create a new Credentials
with the SDKs's stscreds package.
// Initial credentials loaded from SDK's default credential chain. Such as
// the environment, shared credentials (~/.aws/credentials), or EC2 Instance
// Role. These credentials will be used to to make the STS Assume Role API.
sess := session.Must(session.NewSession())
// Create the credentials from AssumeRoleProvider to assume the role
// referenced by the "myRoleARN" ARN.
creds := stscreds.NewCredentials(sess, "myRoleArn")
// Create service client value configured for credentials
// from assumed role.
svc := s3.New(sess, &aws.Config{Credentials: creds})
Assume Role with static MFA Token
To assume an IAM role with a MFA token you can either specify a MFA token code
directly or provide a function to prompt the user each time the credentials
need to refresh the role's credentials. Specifying the TokenCode should be used
for short lived operations that will not need to be refreshed, and when you do
not want to have direct control over the user provides their MFA token.
With TokenCode the AssumeRoleProvider will be not be able to refresh the role's
credentials.
// Create the credentials from AssumeRoleProvider to assume the role
// referenced by the "myRoleARN" ARN using the MFA token code provided.
creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
p.SerialNumber = aws.String("myTokenSerialNumber")
p.TokenCode = aws.String("00000000")
})
// Create service client value configured for credentials
// from assumed role.
svc := s3.New(sess, &aws.Config{Credentials: creds})
Assume Role with MFA Token Provider
To assume an IAM role with MFA for longer running tasks where the credentials
may need to be refreshed setting the TokenProvider field of AssumeRoleProvider
will allow the credential provider to prompt for new MFA token code when the
role's credentials need to be refreshed.
The StdinTokenProvider function is available to prompt on stdin to retrieve
the MFA token code from the user. You can also implement custom prompts by
satisfing the TokenProvider function signature.
Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
have undesirable results as the StdinTokenProvider will not be synchronized. A
single Credentials with an AssumeRoleProvider can be shared safely.
// Create the credentials from AssumeRoleProvider to assume the role
// referenced by the "myRoleARN" ARN. Prompting for MFA token from stdin.
creds := stscreds.NewCredentials(sess, "myRoleArn", func(p *stscreds.AssumeRoleProvider) {
p.SerialNumber = aws.String("myTokenSerialNumber")
p.TokenProvider = stscreds.StdinTokenProvider
})
// Create service client value configured for credentials
// from assumed role.
svc := s3.New(sess, &aws.Config{Credentials: creds})
*/
package stscreds
import (
"fmt"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkrand"
"github.com/aws/aws-sdk-go/service/sts"
)
// StdinTokenProvider will prompt on stderr and read from stdin for a string value.
// An error is returned if reading from stdin fails.
//
// Use this function to read MFA tokens from stdin. The function makes no attempt
// to make atomic prompts from stdin across multiple gorouties.
//
// Using StdinTokenProvider with multiple AssumeRoleProviders, or Credentials will
// have undesirable results as the StdinTokenProvider will not be synchronized. A
// single Credentials with an AssumeRoleProvider can be shared safely
//
// Will wait forever until something is provided on the stdin.
func StdinTokenProvider() (string, error) {
var v string
fmt.Fprintf(os.Stderr, "Assume Role MFA token code: ")
_, err := fmt.Scanln(&v)
return v, err
}
// ProviderName provides a name of AssumeRole provider
const ProviderName = "AssumeRoleProvider"
// AssumeRoler represents the minimal subset of the STS client API used by this provider.
type AssumeRoler interface {
AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
}
type assumeRolerWithContext interface {
AssumeRoleWithContext(aws.Context, *sts.AssumeRoleInput, ...request.Option) (*sts.AssumeRoleOutput, error)
}
// DefaultDuration is the default amount of time in minutes that the credentials
// will be valid for.
var DefaultDuration = time.Duration(15) * time.Minute
// AssumeRoleProvider retrieves temporary credentials from the STS service, and
// keeps track of their expiration time.
//
// This credential provider will be used by the SDKs default credential change
// when shared configuration is enabled, and the shared config or shared credentials
// file configure assume role. See Session docs for how to do this.
//
// AssumeRoleProvider does not provide any synchronization and it is not safe
// to share this value across multiple Credentials, Sessions, or service clients
// without also sharing the same Credentials instance.
type AssumeRoleProvider struct {
credentials.Expiry
// STS client to make assume role request with.
Client AssumeRoler
// Role to be assumed.
RoleARN string
// Session name, if you wish to reuse the credentials elsewhere.
RoleSessionName string
// Optional, you can pass tag key-value pairs to your session. These tags are called session tags.
Tags []*sts.Tag
// A list of keys for session tags that you want to set as transitive.
// If you set a tag key as transitive, the corresponding key and value passes to subsequent sessions in a role chain.
TransitiveTagKeys []*string
// Expiry duration of the STS credentials. Defaults to 15 minutes if not set.
Duration time.Duration
// Optional ExternalID to pass along, defaults to nil if not set.
ExternalID *string
// The policy plain text must be 2048 bytes or shorter. However, an internal
// conversion compresses it into a packed binary format with a separate limit.
// The PackedPolicySize response element indicates by percentage how close to
// the upper size limit the policy is, with 100% equaling the maximum allowed
// size.
Policy *string
// The ARNs of IAM managed policies you want to use as managed session policies.
// The policies must exist in the same account as the role.
//
// This parameter is optional. You can provide up to 10 managed policy ARNs.
// However, the plain text that you use for both inline and managed session
// policies can't exceed 2,048 characters.
//
// An AWS conversion compresses the passed session policies and session tags
// into a packed binary format that has a separate limit. Your request can fail
// for this limit even if your plain text meets the other requirements. The
// PackedPolicySize response element indicates by percentage how close the policies
// and tags for your request are to the upper size limit.
//
// Passing policies to this operation returns new temporary credentials. The
// resulting session's permissions are the intersection of the role's identity-based
// policy and the session policies. You can use the role's temporary credentials
// in subsequent AWS API calls to access resources in the account that owns
// the role. You cannot use session policies to grant more permissions than
// those allowed by the identity-based policy of the role that is being assumed.
// For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
PolicyArns []*sts.PolicyDescriptorType
// The identification number of the MFA device that is associated with the user
// who is making the AssumeRole call. Specify this value if the trust policy
// of the role being assumed includes a condition that requires MFA authentication.
// The value is either the serial number for a hardware device (such as GAHT12345678)
// or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
SerialNumber *string
// The value provided by the MFA device, if the trust policy of the role being
// assumed requires MFA (that is, if the policy includes a condition that tests
// for MFA). If the role being assumed requires MFA and if the TokenCode value
// is missing or expired, the AssumeRole call returns an "access denied" error.
//
// If SerialNumber is set and neither TokenCode nor TokenProvider are also
// set an error will be returned.
TokenCode *string
// Async method of providing MFA token code for assuming an IAM role with MFA.
// The value returned by the function will be used as the TokenCode in the Retrieve
// call. See StdinTokenProvider for a provider that prompts and reads from stdin.
//
// This token provider will be called when ever the assumed role's
// credentials need to be refreshed when SerialNumber is also set and
// TokenCode is not set.
//
// If both TokenCode and TokenProvider is set, TokenProvider will be used and
// TokenCode is ignored.
TokenProvider func() (string, error)
// ExpiryWindow will allow the credentials to trigger refreshing prior to
// the credentials actually expiring. This is beneficial so race conditions
// with expiring credentials do not cause request to fail unexpectedly
// due to ExpiredTokenException exceptions.
//
// So a ExpiryWindow of 10s would cause calls to IsExpired() to return true
// 10 seconds before the credentials are actually expired.
//
// If ExpiryWindow is 0 or less it will be ignored.
ExpiryWindow time.Duration
// MaxJitterFrac reduces the effective Duration of each credential requested
// by a random percentage between 0 and MaxJitterFraction. MaxJitterFrac must
// have a value between 0 and 1. Any other value may lead to expected behavior.
// With a MaxJitterFrac value of 0, default) will no jitter will be used.
//
// For example, with a Duration of 30m and a MaxJitterFrac of 0.1, the
// AssumeRole call will be made with an arbitrary Duration between 27m and
// 30m.
//
// MaxJitterFrac should not be negative.
MaxJitterFrac float64
}
// NewCredentials returns a pointer to a new Credentials value wrapping the
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
// role will be named after a nanosecond timestamp of this operation. The
// Credentials value will attempt to refresh the credentials using the provider
// when Credentials.Get is called, if the cached credentials are expiring.
//
// Takes a Config provider to create the STS client. The ConfigProvider is
// satisfied by the session.Session type.
//
// It is safe to share the returned Credentials with multiple Sessions and
// service clients. All access to the credentials and refreshing them
// will be synchronized.
func NewCredentials(c client.ConfigProvider, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
p := &AssumeRoleProvider{
Client: sts.New(c),
RoleARN: roleARN,
Duration: DefaultDuration,
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
// NewCredentialsWithClient returns a pointer to a new Credentials value wrapping the
// AssumeRoleProvider. The credentials will expire every 15 minutes and the
// role will be named after a nanosecond timestamp of this operation. The
// Credentials value will attempt to refresh the credentials using the provider
// when Credentials.Get is called, if the cached credentials are expiring.
//
// Takes an AssumeRoler which can be satisfied by the STS client.
//
// It is safe to share the returned Credentials with multiple Sessions and
// service clients. All access to the credentials and refreshing them
// will be synchronized.
func NewCredentialsWithClient(svc AssumeRoler, roleARN string, options ...func(*AssumeRoleProvider)) *credentials.Credentials {
p := &AssumeRoleProvider{
Client: svc,
RoleARN: roleARN,
Duration: DefaultDuration,
}
for _, option := range options {
option(p)
}
return credentials.NewCredentials(p)
}
// Retrieve generates a new set of temporary credentials using STS.
func (p *AssumeRoleProvider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext generates a new set of temporary credentials using STS.
func (p *AssumeRoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
// Apply defaults where parameters are not set.
if p.RoleSessionName == "" {
// Try to work out a role name that will hopefully end up unique.
p.RoleSessionName = fmt.Sprintf("%d", time.Now().UTC().UnixNano())
}
if p.Duration == 0 {
// Expire as often as AWS permits.
p.Duration = DefaultDuration
}
jitter := time.Duration(sdkrand.SeededRand.Float64() * p.MaxJitterFrac * float64(p.Duration))
input := &sts.AssumeRoleInput{
DurationSeconds: aws.Int64(int64((p.Duration - jitter) / time.Second)),
RoleArn: aws.String(p.RoleARN),
RoleSessionName: aws.String(p.RoleSessionName),
ExternalId: p.ExternalID,
Tags: p.Tags,
PolicyArns: p.PolicyArns,
TransitiveTagKeys: p.TransitiveTagKeys,
}
if p.Policy != nil {
input.Policy = p.Policy
}
if p.SerialNumber != nil {
if p.TokenCode != nil {
input.SerialNumber = p.SerialNumber
input.TokenCode = p.TokenCode
} else if p.TokenProvider != nil {
input.SerialNumber = p.SerialNumber
code, err := p.TokenProvider()
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
input.TokenCode = aws.String(code)
} else {
return credentials.Value{ProviderName: ProviderName},
awserr.New("AssumeRoleTokenNotAvailable",
"assume role with MFA enabled, but neither TokenCode nor TokenProvider are set", nil)
}
}
var roleOutput *sts.AssumeRoleOutput
var err error
if c, ok := p.Client.(assumeRolerWithContext); ok {
roleOutput, err = c.AssumeRoleWithContext(ctx, input)
} else {
roleOutput, err = p.Client.AssumeRole(input)
}
if err != nil {
return credentials.Value{ProviderName: ProviderName}, err
}
// We will proactively generate new credentials before they expire.
p.SetExpiration(*roleOutput.Credentials.Expiration, p.ExpiryWindow)
return credentials.Value{
AccessKeyID: *roleOutput.Credentials.AccessKeyId,
SecretAccessKey: *roleOutput.Credentials.SecretAccessKey,
SessionToken: *roleOutput.Credentials.SessionToken,
ProviderName: ProviderName,
}, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/credentials/stscreds/web_identity_provider.go
================================================
package stscreds
import (
"fmt"
"io/ioutil"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/aws/aws-sdk-go/service/sts/stsiface"
)
const (
// ErrCodeWebIdentity will be used as an error code when constructing
// a new error to be returned during session creation or retrieval.
ErrCodeWebIdentity = "WebIdentityErr"
// WebIdentityProviderName is the web identity provider name
WebIdentityProviderName = "WebIdentityCredentials"
)
// now is used to return a time.Time object representing
// the current time. This can be used to easily test and
// compare test values.
var now = time.Now
// TokenFetcher should return WebIdentity token bytes or an error
type TokenFetcher interface {
FetchToken(credentials.Context) ([]byte, error)
}
// FetchTokenPath is a path to a WebIdentity token file
type FetchTokenPath string
// FetchToken returns a token by reading from the filesystem
func (f FetchTokenPath) FetchToken(ctx credentials.Context) ([]byte, error) {
data, err := ioutil.ReadFile(string(f))
if err != nil {
errMsg := fmt.Sprintf("unable to read file at %s", f)
return nil, awserr.New(ErrCodeWebIdentity, errMsg, err)
}
return data, nil
}
// WebIdentityRoleProvider is used to retrieve credentials using
// an OIDC token.
type WebIdentityRoleProvider struct {
credentials.Expiry
// The policy ARNs to use with the web identity assumed role.
PolicyArns []*sts.PolicyDescriptorType
// Duration the STS credentials will be valid for. Truncated to seconds.
// If unset, the assumed role will use AssumeRoleWithWebIdentity's default
// expiry duration. See
// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/#STS.AssumeRoleWithWebIdentity
// for more information.
Duration time.Duration
// The amount of time the credentials will be refreshed before they expire.
// This is useful refresh credentials before they expire to reduce risk of
// using credentials as they expire. If unset, will default to no expiry
// window.
ExpiryWindow time.Duration
client stsiface.STSAPI
tokenFetcher TokenFetcher
roleARN string
roleSessionName string
}
// NewWebIdentityCredentials will return a new set of credentials with a given
// configuration, role arn, and token file path.
//
// Deprecated: Use NewWebIdentityRoleProviderWithOptions for flexible
// functional options, and wrap with credentials.NewCredentials helper.
func NewWebIdentityCredentials(c client.ConfigProvider, roleARN, roleSessionName, path string) *credentials.Credentials {
svc := sts.New(c)
p := NewWebIdentityRoleProvider(svc, roleARN, roleSessionName, path)
return credentials.NewCredentials(p)
}
// NewWebIdentityRoleProvider will return a new WebIdentityRoleProvider with the
// provided stsiface.STSAPI
//
// Deprecated: Use NewWebIdentityRoleProviderWithOptions for flexible
// functional options.
func NewWebIdentityRoleProvider(svc stsiface.STSAPI, roleARN, roleSessionName, path string) *WebIdentityRoleProvider {
return NewWebIdentityRoleProviderWithOptions(svc, roleARN, roleSessionName, FetchTokenPath(path))
}
// NewWebIdentityRoleProviderWithToken will return a new WebIdentityRoleProvider with the
// provided stsiface.STSAPI and a TokenFetcher
//
// Deprecated: Use NewWebIdentityRoleProviderWithOptions for flexible
// functional options.
func NewWebIdentityRoleProviderWithToken(svc stsiface.STSAPI, roleARN, roleSessionName string, tokenFetcher TokenFetcher) *WebIdentityRoleProvider {
return NewWebIdentityRoleProviderWithOptions(svc, roleARN, roleSessionName, tokenFetcher)
}
// NewWebIdentityRoleProviderWithOptions will return an initialize
// WebIdentityRoleProvider with the provided stsiface.STSAPI, role ARN, and a
// TokenFetcher. Additional options can be provided as functional options.
//
// TokenFetcher is the implementation that will retrieve the JWT token from to
// assume the role with. Use the provided FetchTokenPath implementation to
// retrieve the JWT token using a file system path.
func NewWebIdentityRoleProviderWithOptions(svc stsiface.STSAPI, roleARN, roleSessionName string, tokenFetcher TokenFetcher, optFns ...func(*WebIdentityRoleProvider)) *WebIdentityRoleProvider {
p := WebIdentityRoleProvider{
client: svc,
tokenFetcher: tokenFetcher,
roleARN: roleARN,
roleSessionName: roleSessionName,
}
for _, fn := range optFns {
fn(&p)
}
return &p
}
// Retrieve will attempt to assume a role from a token which is located at
// 'WebIdentityTokenFilePath' specified destination and if that is empty an
// error will be returned.
func (p *WebIdentityRoleProvider) Retrieve() (credentials.Value, error) {
return p.RetrieveWithContext(aws.BackgroundContext())
}
// RetrieveWithContext will attempt to assume a role from a token which is
// located at 'WebIdentityTokenFilePath' specified destination and if that is
// empty an error will be returned.
func (p *WebIdentityRoleProvider) RetrieveWithContext(ctx credentials.Context) (credentials.Value, error) {
b, err := p.tokenFetcher.FetchToken(ctx)
if err != nil {
return credentials.Value{}, awserr.New(ErrCodeWebIdentity, "failed fetching WebIdentity token: ", err)
}
sessionName := p.roleSessionName
if len(sessionName) == 0 {
// session name is used to uniquely identify a session. This simply
// uses unix time in nanoseconds to uniquely identify sessions.
sessionName = strconv.FormatInt(now().UnixNano(), 10)
}
var duration *int64
if p.Duration != 0 {
duration = aws.Int64(int64(p.Duration / time.Second))
}
req, resp := p.client.AssumeRoleWithWebIdentityRequest(&sts.AssumeRoleWithWebIdentityInput{
PolicyArns: p.PolicyArns,
RoleArn: &p.roleARN,
RoleSessionName: &sessionName,
WebIdentityToken: aws.String(string(b)),
DurationSeconds: duration,
})
req.SetContext(ctx)
// InvalidIdentityToken error is a temporary error that can occur
// when assuming an Role with a JWT web identity token.
req.RetryErrorCodes = append(req.RetryErrorCodes, sts.ErrCodeInvalidIdentityTokenException)
if err := req.Send(); err != nil {
return credentials.Value{}, awserr.New(ErrCodeWebIdentity, "failed to retrieve credentials", err)
}
p.SetExpiration(aws.TimeValue(resp.Credentials.Expiration), p.ExpiryWindow)
value := credentials.Value{
AccessKeyID: aws.StringValue(resp.Credentials.AccessKeyId),
SecretAccessKey: aws.StringValue(resp.Credentials.SecretAccessKey),
SessionToken: aws.StringValue(resp.Credentials.SessionToken),
ProviderName: WebIdentityProviderName,
}
return value, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/doc.go
================================================
// Package csm provides the Client Side Monitoring (CSM) client which enables
// sending metrics via UDP connection to the CSM agent. This package provides
// control options, and configuration for the CSM client. The client can be
// controlled manually, or automatically via the SDK's Session configuration.
//
// Enabling CSM client via SDK's Session configuration
//
// The CSM client can be enabled automatically via SDK's Session configuration.
// The SDK's session configuration enables the CSM client if the AWS_CSM_PORT
// environment variable is set to a non-empty value.
//
// The configuration options for the CSM client via the SDK's session
// configuration are:
//
// * AWS_CSM_PORT=
// The port number the CSM agent will receive metrics on.
//
// * AWS_CSM_HOST=
// The hostname, or IP address the CSM agent will receive metrics on.
// Without port number.
//
// Manually enabling the CSM client
//
// The CSM client can be started, paused, and resumed manually. The Start
// function will enable the CSM client to publish metrics to the CSM agent. It
// is safe to call Start concurrently, but if Start is called additional times
// with different ClientID or address it will panic.
//
// r, err := csm.Start("clientID", ":31000")
// if err != nil {
// panic(fmt.Errorf("failed starting CSM: %v", err))
// }
//
// When controlling the CSM client manually, you must also inject its request
// handlers into the SDK's Session configuration for the SDK's API clients to
// publish metrics.
//
// sess, err := session.NewSession(&aws.Config{})
// if err != nil {
// panic(fmt.Errorf("failed loading session: %v", err))
// }
//
// // Add CSM client's metric publishing request handlers to the SDK's
// // Session Configuration.
// r.InjectHandlers(&sess.Handlers)
//
// Controlling CSM client
//
// Once the CSM client has been enabled the Get function will return a Reporter
// value that you can use to pause and resume the metrics published to the CSM
// agent. If Get function is called before the reporter is enabled with the
// Start function or via SDK's Session configuration nil will be returned.
//
// The Pause method can be called to stop the CSM client publishing metrics to
// the CSM agent. The Continue method will resume metric publishing.
//
// // Get the CSM client Reporter.
// r := csm.Get()
//
// // Will pause monitoring
// r.Pause()
// resp, err = client.GetObject(&s3.GetObjectInput{
// Bucket: aws.String("bucket"),
// Key: aws.String("key"),
// })
//
// // Resume monitoring
// r.Continue()
package csm
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/enable.go
================================================
package csm
import (
"fmt"
"strings"
"sync"
)
var (
lock sync.Mutex
)
const (
// DefaultPort is used when no port is specified.
DefaultPort = "31000"
// DefaultHost is the host that will be used when none is specified.
DefaultHost = "127.0.0.1"
)
// AddressWithDefaults returns a CSM address built from the host and port
// values. If the host or port is not set, default values will be used
// instead. If host is "localhost" it will be replaced with "127.0.0.1".
func AddressWithDefaults(host, port string) string {
if len(host) == 0 || strings.EqualFold(host, "localhost") {
host = DefaultHost
}
if len(port) == 0 {
port = DefaultPort
}
// Only IP6 host can contain a colon
if strings.Contains(host, ":") {
return "[" + host + "]:" + port
}
return host + ":" + port
}
// Start will start a long running go routine to capture
// client side metrics. Calling start multiple time will only
// start the metric listener once and will panic if a different
// client ID or port is passed in.
//
// r, err := csm.Start("clientID", "127.0.0.1:31000")
// if err != nil {
// panic(fmt.Errorf("expected no error, but received %v", err))
// }
// sess := session.NewSession()
// r.InjectHandlers(sess.Handlers)
//
// svc := s3.New(sess)
// out, err := svc.GetObject(&s3.GetObjectInput{
// Bucket: aws.String("bucket"),
// Key: aws.String("key"),
// })
func Start(clientID string, url string) (*Reporter, error) {
lock.Lock()
defer lock.Unlock()
if sender == nil {
sender = newReporter(clientID, url)
} else {
if sender.clientID != clientID {
panic(fmt.Errorf("inconsistent client IDs. %q was expected, but received %q", sender.clientID, clientID))
}
if sender.url != url {
panic(fmt.Errorf("inconsistent URLs. %q was expected, but received %q", sender.url, url))
}
}
if err := connect(url); err != nil {
sender = nil
return nil, err
}
return sender, nil
}
// Get will return a reporter if one exists, if one does not exist, nil will
// be returned.
func Get() *Reporter {
lock.Lock()
defer lock.Unlock()
return sender
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/metric.go
================================================
package csm
import (
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
)
type metricTime time.Time
func (t metricTime) MarshalJSON() ([]byte, error) {
ns := time.Duration(time.Time(t).UnixNano())
return []byte(strconv.FormatInt(int64(ns/time.Millisecond), 10)), nil
}
type metric struct {
ClientID *string `json:"ClientId,omitempty"`
API *string `json:"Api,omitempty"`
Service *string `json:"Service,omitempty"`
Timestamp *metricTime `json:"Timestamp,omitempty"`
Type *string `json:"Type,omitempty"`
Version *int `json:"Version,omitempty"`
AttemptCount *int `json:"AttemptCount,omitempty"`
Latency *int `json:"Latency,omitempty"`
Fqdn *string `json:"Fqdn,omitempty"`
UserAgent *string `json:"UserAgent,omitempty"`
AttemptLatency *int `json:"AttemptLatency,omitempty"`
SessionToken *string `json:"SessionToken,omitempty"`
Region *string `json:"Region,omitempty"`
AccessKey *string `json:"AccessKey,omitempty"`
HTTPStatusCode *int `json:"HttpStatusCode,omitempty"`
XAmzID2 *string `json:"XAmzId2,omitempty"`
XAmzRequestID *string `json:"XAmznRequestId,omitempty"`
AWSException *string `json:"AwsException,omitempty"`
AWSExceptionMessage *string `json:"AwsExceptionMessage,omitempty"`
SDKException *string `json:"SdkException,omitempty"`
SDKExceptionMessage *string `json:"SdkExceptionMessage,omitempty"`
FinalHTTPStatusCode *int `json:"FinalHttpStatusCode,omitempty"`
FinalAWSException *string `json:"FinalAwsException,omitempty"`
FinalAWSExceptionMessage *string `json:"FinalAwsExceptionMessage,omitempty"`
FinalSDKException *string `json:"FinalSdkException,omitempty"`
FinalSDKExceptionMessage *string `json:"FinalSdkExceptionMessage,omitempty"`
DestinationIP *string `json:"DestinationIp,omitempty"`
ConnectionReused *int `json:"ConnectionReused,omitempty"`
AcquireConnectionLatency *int `json:"AcquireConnectionLatency,omitempty"`
ConnectLatency *int `json:"ConnectLatency,omitempty"`
RequestLatency *int `json:"RequestLatency,omitempty"`
DNSLatency *int `json:"DnsLatency,omitempty"`
TCPLatency *int `json:"TcpLatency,omitempty"`
SSLLatency *int `json:"SslLatency,omitempty"`
MaxRetriesExceeded *int `json:"MaxRetriesExceeded,omitempty"`
}
func (m *metric) TruncateFields() {
m.ClientID = truncateString(m.ClientID, 255)
m.UserAgent = truncateString(m.UserAgent, 256)
m.AWSException = truncateString(m.AWSException, 128)
m.AWSExceptionMessage = truncateString(m.AWSExceptionMessage, 512)
m.SDKException = truncateString(m.SDKException, 128)
m.SDKExceptionMessage = truncateString(m.SDKExceptionMessage, 512)
m.FinalAWSException = truncateString(m.FinalAWSException, 128)
m.FinalAWSExceptionMessage = truncateString(m.FinalAWSExceptionMessage, 512)
m.FinalSDKException = truncateString(m.FinalSDKException, 128)
m.FinalSDKExceptionMessage = truncateString(m.FinalSDKExceptionMessage, 512)
}
func truncateString(v *string, l int) *string {
if v != nil && len(*v) > l {
nv := (*v)[:l]
return &nv
}
return v
}
func (m *metric) SetException(e metricException) {
switch te := e.(type) {
case awsException:
m.AWSException = aws.String(te.exception)
m.AWSExceptionMessage = aws.String(te.message)
case sdkException:
m.SDKException = aws.String(te.exception)
m.SDKExceptionMessage = aws.String(te.message)
}
}
func (m *metric) SetFinalException(e metricException) {
switch te := e.(type) {
case awsException:
m.FinalAWSException = aws.String(te.exception)
m.FinalAWSExceptionMessage = aws.String(te.message)
case sdkException:
m.FinalSDKException = aws.String(te.exception)
m.FinalSDKExceptionMessage = aws.String(te.message)
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/metric_chan.go
================================================
package csm
import (
"sync/atomic"
)
const (
runningEnum = iota
pausedEnum
)
var (
// MetricsChannelSize of metrics to hold in the channel
MetricsChannelSize = 100
)
type metricChan struct {
ch chan metric
paused *int64
}
func newMetricChan(size int) metricChan {
return metricChan{
ch: make(chan metric, size),
paused: new(int64),
}
}
func (ch *metricChan) Pause() {
atomic.StoreInt64(ch.paused, pausedEnum)
}
func (ch *metricChan) Continue() {
atomic.StoreInt64(ch.paused, runningEnum)
}
func (ch *metricChan) IsPaused() bool {
v := atomic.LoadInt64(ch.paused)
return v == pausedEnum
}
// Push will push metrics to the metric channel if the channel
// is not paused
func (ch *metricChan) Push(m metric) bool {
if ch.IsPaused() {
return false
}
select {
case ch.ch <- m:
return true
default:
return false
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/metric_exception.go
================================================
package csm
type metricException interface {
Exception() string
Message() string
}
type requestException struct {
exception string
message string
}
func (e requestException) Exception() string {
return e.exception
}
func (e requestException) Message() string {
return e.message
}
type awsException struct {
requestException
}
type sdkException struct {
requestException
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/csm/reporter.go
================================================
package csm
import (
"encoding/json"
"net"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
)
// Reporter will gather metrics of API requests made and
// send those metrics to the CSM endpoint.
type Reporter struct {
clientID string
url string
conn net.Conn
metricsCh metricChan
done chan struct{}
}
var (
sender *Reporter
)
func connect(url string) error {
const network = "udp"
if err := sender.connect(network, url); err != nil {
return err
}
if sender.done == nil {
sender.done = make(chan struct{})
go sender.start()
}
return nil
}
func newReporter(clientID, url string) *Reporter {
return &Reporter{
clientID: clientID,
url: url,
metricsCh: newMetricChan(MetricsChannelSize),
}
}
func (rep *Reporter) sendAPICallAttemptMetric(r *request.Request) {
if rep == nil {
return
}
now := time.Now()
creds, _ := r.Config.Credentials.Get()
m := metric{
ClientID: aws.String(rep.clientID),
API: aws.String(r.Operation.Name),
Service: aws.String(r.ClientInfo.ServiceID),
Timestamp: (*metricTime)(&now),
UserAgent: aws.String(r.HTTPRequest.Header.Get("User-Agent")),
Region: r.Config.Region,
Type: aws.String("ApiCallAttempt"),
Version: aws.Int(1),
XAmzRequestID: aws.String(r.RequestID),
AttemptLatency: aws.Int(int(now.Sub(r.AttemptTime).Nanoseconds() / int64(time.Millisecond))),
AccessKey: aws.String(creds.AccessKeyID),
}
if r.HTTPResponse != nil {
m.HTTPStatusCode = aws.Int(r.HTTPResponse.StatusCode)
}
if r.Error != nil {
if awserr, ok := r.Error.(awserr.Error); ok {
m.SetException(getMetricException(awserr))
}
}
m.TruncateFields()
rep.metricsCh.Push(m)
}
func getMetricException(err awserr.Error) metricException {
msg := err.Error()
code := err.Code()
switch code {
case request.ErrCodeRequestError,
request.ErrCodeSerialization,
request.CanceledErrorCode:
return sdkException{
requestException{exception: code, message: msg},
}
default:
return awsException{
requestException{exception: code, message: msg},
}
}
}
func (rep *Reporter) sendAPICallMetric(r *request.Request) {
if rep == nil {
return
}
now := time.Now()
m := metric{
ClientID: aws.String(rep.clientID),
API: aws.String(r.Operation.Name),
Service: aws.String(r.ClientInfo.ServiceID),
Timestamp: (*metricTime)(&now),
UserAgent: aws.String(r.HTTPRequest.Header.Get("User-Agent")),
Type: aws.String("ApiCall"),
AttemptCount: aws.Int(r.RetryCount + 1),
Region: r.Config.Region,
Latency: aws.Int(int(time.Since(r.Time) / time.Millisecond)),
XAmzRequestID: aws.String(r.RequestID),
MaxRetriesExceeded: aws.Int(boolIntValue(r.RetryCount >= r.MaxRetries())),
}
if r.HTTPResponse != nil {
m.FinalHTTPStatusCode = aws.Int(r.HTTPResponse.StatusCode)
}
if r.Error != nil {
if awserr, ok := r.Error.(awserr.Error); ok {
m.SetFinalException(getMetricException(awserr))
}
}
m.TruncateFields()
// TODO: Probably want to figure something out for logging dropped
// metrics
rep.metricsCh.Push(m)
}
func (rep *Reporter) connect(network, url string) error {
if rep.conn != nil {
rep.conn.Close()
}
conn, err := net.Dial(network, url)
if err != nil {
return awserr.New("UDPError", "Could not connect", err)
}
rep.conn = conn
return nil
}
func (rep *Reporter) close() {
if rep.done != nil {
close(rep.done)
}
rep.metricsCh.Pause()
}
func (rep *Reporter) start() {
defer func() {
rep.metricsCh.Pause()
}()
for {
select {
case <-rep.done:
rep.done = nil
return
case m := <-rep.metricsCh.ch:
// TODO: What to do with this error? Probably should just log
b, err := json.Marshal(m)
if err != nil {
continue
}
rep.conn.Write(b)
}
}
}
// Pause will pause the metric channel preventing any new metrics from being
// added. It is safe to call concurrently with other calls to Pause, but if
// called concurently with Continue can lead to unexpected state.
func (rep *Reporter) Pause() {
lock.Lock()
defer lock.Unlock()
if rep == nil {
return
}
rep.close()
}
// Continue will reopen the metric channel and allow for monitoring to be
// resumed. It is safe to call concurrently with other calls to Continue, but
// if called concurently with Pause can lead to unexpected state.
func (rep *Reporter) Continue() {
lock.Lock()
defer lock.Unlock()
if rep == nil {
return
}
if !rep.metricsCh.IsPaused() {
return
}
rep.metricsCh.Continue()
}
// Client side metric handler names
const (
APICallMetricHandlerName = "awscsm.SendAPICallMetric"
APICallAttemptMetricHandlerName = "awscsm.SendAPICallAttemptMetric"
)
// InjectHandlers will will enable client side metrics and inject the proper
// handlers to handle how metrics are sent.
//
// InjectHandlers is NOT safe to call concurrently. Calling InjectHandlers
// multiple times may lead to unexpected behavior, (e.g. duplicate metrics).
//
// // Start must be called in order to inject the correct handlers
// r, err := csm.Start("clientID", "127.0.0.1:8094")
// if err != nil {
// panic(fmt.Errorf("expected no error, but received %v", err))
// }
//
// sess := session.NewSession()
// r.InjectHandlers(&sess.Handlers)
//
// // create a new service client with our client side metric session
// svc := s3.New(sess)
func (rep *Reporter) InjectHandlers(handlers *request.Handlers) {
if rep == nil {
return
}
handlers.Complete.PushFrontNamed(request.NamedHandler{
Name: APICallMetricHandlerName,
Fn: rep.sendAPICallMetric,
})
handlers.CompleteAttempt.PushFrontNamed(request.NamedHandler{
Name: APICallAttemptMetricHandlerName,
Fn: rep.sendAPICallAttemptMetric,
})
}
// boolIntValue return 1 for true and 0 for false.
func boolIntValue(b bool) int {
if b {
return 1
}
return 0
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/defaults/defaults.go
================================================
// Package defaults is a collection of helpers to retrieve the SDK's default
// configuration and handlers.
//
// Generally this package shouldn't be used directly, but session.Session
// instead. This package is useful when you need to reset the defaults
// of a session or service client to the SDK defaults before setting
// additional parameters.
package defaults
import (
"fmt"
"net"
"net/http"
"net/url"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/credentials/endpointcreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/shareddefaults"
)
// A Defaults provides a collection of default values for SDK clients.
type Defaults struct {
Config *aws.Config
Handlers request.Handlers
}
// Get returns the SDK's default values with Config and handlers pre-configured.
func Get() Defaults {
cfg := Config()
handlers := Handlers()
cfg.Credentials = CredChain(cfg, handlers)
return Defaults{
Config: cfg,
Handlers: handlers,
}
}
// Config returns the default configuration without credentials.
// To retrieve a config with credentials also included use
// `defaults.Get().Config` instead.
//
// Generally you shouldn't need to use this method directly, but
// is available if you need to reset the configuration of an
// existing service client or session.
func Config() *aws.Config {
return aws.NewConfig().
WithCredentials(credentials.AnonymousCredentials).
WithRegion(os.Getenv("AWS_REGION")).
WithHTTPClient(http.DefaultClient).
WithMaxRetries(aws.UseServiceDefaultRetries).
WithLogger(aws.NewDefaultLogger()).
WithLogLevel(aws.LogOff).
WithEndpointResolver(endpoints.DefaultResolver())
}
// Handlers returns the default request handlers.
//
// Generally you shouldn't need to use this method directly, but
// is available if you need to reset the request handlers of an
// existing service client or session.
func Handlers() request.Handlers {
var handlers request.Handlers
handlers.Validate.PushBackNamed(corehandlers.ValidateEndpointHandler)
handlers.Validate.AfterEachFn = request.HandlerListStopOnError
handlers.Build.PushBackNamed(corehandlers.SDKVersionUserAgentHandler)
handlers.Build.PushBackNamed(corehandlers.AddHostExecEnvUserAgentHander)
handlers.Build.AfterEachFn = request.HandlerListStopOnError
handlers.Sign.PushBackNamed(corehandlers.BuildContentLengthHandler)
handlers.Send.PushBackNamed(corehandlers.ValidateReqSigHandler)
handlers.Send.PushBackNamed(corehandlers.SendHandler)
handlers.AfterRetry.PushBackNamed(corehandlers.AfterRetryHandler)
handlers.ValidateResponse.PushBackNamed(corehandlers.ValidateResponseHandler)
return handlers
}
// CredChain returns the default credential chain.
//
// Generally you shouldn't need to use this method directly, but
// is available if you need to reset the credentials of an
// existing service client or session's Config.
func CredChain(cfg *aws.Config, handlers request.Handlers) *credentials.Credentials {
return credentials.NewCredentials(&credentials.ChainProvider{
VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
Providers: CredProviders(cfg, handlers),
})
}
// CredProviders returns the slice of providers used in
// the default credential chain.
//
// For applications that need to use some other provider (for example use
// different environment variables for legacy reasons) but still fall back
// on the default chain of providers. This allows that default chaint to be
// automatically updated
func CredProviders(cfg *aws.Config, handlers request.Handlers) []credentials.Provider {
return []credentials.Provider{
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
RemoteCredProvider(*cfg, handlers),
}
}
const (
httpProviderAuthorizationEnvVar = "AWS_CONTAINER_AUTHORIZATION_TOKEN"
httpProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_FULL_URI"
)
// RemoteCredProvider returns a credentials provider for the default remote
// endpoints such as EC2 or ECS Roles.
func RemoteCredProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
if u := os.Getenv(httpProviderEnvVar); len(u) > 0 {
return localHTTPCredProvider(cfg, handlers, u)
}
if uri := os.Getenv(shareddefaults.ECSCredsProviderEnvVar); len(uri) > 0 {
u := fmt.Sprintf("%s%s", shareddefaults.ECSContainerCredentialsURI, uri)
return httpCredProvider(cfg, handlers, u)
}
return ec2RoleProvider(cfg, handlers)
}
var lookupHostFn = net.LookupHost
func isLoopbackHost(host string) (bool, error) {
ip := net.ParseIP(host)
if ip != nil {
return ip.IsLoopback(), nil
}
// Host is not an ip, perform lookup
addrs, err := lookupHostFn(host)
if err != nil {
return false, err
}
for _, addr := range addrs {
if !net.ParseIP(addr).IsLoopback() {
return false, nil
}
}
return true, nil
}
func localHTTPCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
var errMsg string
parsed, err := url.Parse(u)
if err != nil {
errMsg = fmt.Sprintf("invalid URL, %v", err)
} else {
host := aws.URLHostname(parsed)
if len(host) == 0 {
errMsg = "unable to parse host from local HTTP cred provider URL"
} else if isLoopback, loopbackErr := isLoopbackHost(host); loopbackErr != nil {
errMsg = fmt.Sprintf("failed to resolve host %q, %v", host, loopbackErr)
} else if !isLoopback {
errMsg = fmt.Sprintf("invalid endpoint host, %q, only loopback hosts are allowed.", host)
}
}
if len(errMsg) > 0 {
if cfg.Logger != nil {
cfg.Logger.Log("Ignoring, HTTP credential provider", errMsg, err)
}
return credentials.ErrorProvider{
Err: awserr.New("CredentialsEndpointError", errMsg, err),
ProviderName: endpointcreds.ProviderName,
}
}
return httpCredProvider(cfg, handlers, u)
}
func httpCredProvider(cfg aws.Config, handlers request.Handlers, u string) credentials.Provider {
return endpointcreds.NewProviderClient(cfg, handlers, u,
func(p *endpointcreds.Provider) {
p.ExpiryWindow = 5 * time.Minute
p.AuthorizationToken = os.Getenv(httpProviderAuthorizationEnvVar)
},
)
}
func ec2RoleProvider(cfg aws.Config, handlers request.Handlers) credentials.Provider {
resolver := cfg.EndpointResolver
if resolver == nil {
resolver = endpoints.DefaultResolver()
}
e, _ := resolver.EndpointFor(endpoints.Ec2metadataServiceID, "")
return &ec2rolecreds.EC2RoleProvider{
Client: ec2metadata.NewClient(cfg, handlers, e.URL, e.SigningRegion),
ExpiryWindow: 5 * time.Minute,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/defaults/shared_config.go
================================================
package defaults
import (
"github.com/aws/aws-sdk-go/internal/shareddefaults"
)
// SharedCredentialsFilename returns the SDK's default file path
// for the shared credentials file.
//
// Builds the shared config file path based on the OS's platform.
//
// - Linux/Unix: $HOME/.aws/credentials
// - Windows: %USERPROFILE%\.aws\credentials
func SharedCredentialsFilename() string {
return shareddefaults.SharedCredentialsFilename()
}
// SharedConfigFilename returns the SDK's default file path for
// the shared config file.
//
// Builds the shared config file path based on the OS's platform.
//
// - Linux/Unix: $HOME/.aws/config
// - Windows: %USERPROFILE%\.aws\config
func SharedConfigFilename() string {
return shareddefaults.SharedConfigFilename()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/doc.go
================================================
// Package aws provides the core SDK's utilities and shared types. Use this package's
// utilities to simplify setting and reading API operations parameters.
//
// Value and Pointer Conversion Utilities
//
// This package includes a helper conversion utility for each scalar type the SDK's
// API use. These utilities make getting a pointer of the scalar, and dereferencing
// a pointer easier.
//
// Each conversion utility comes in two forms. Value to Pointer and Pointer to Value.
// The Pointer to value will safely dereference the pointer and return its value.
// If the pointer was nil, the scalar's zero value will be returned.
//
// The value to pointer functions will be named after the scalar type. So get a
// *string from a string value use the "String" function. This makes it easy to
// to get pointer of a literal string value, because getting the address of a
// literal requires assigning the value to a variable first.
//
// var strPtr *string
//
// // Without the SDK's conversion functions
// str := "my string"
// strPtr = &str
//
// // With the SDK's conversion functions
// strPtr = aws.String("my string")
//
// // Convert *string to string value
// str = aws.StringValue(strPtr)
//
// In addition to scalars the aws package also includes conversion utilities for
// map and slice for commonly types used in API parameters. The map and slice
// conversion functions use similar naming pattern as the scalar conversion
// functions.
//
// var strPtrs []*string
// var strs []string = []string{"Go", "Gophers", "Go"}
//
// // Convert []string to []*string
// strPtrs = aws.StringSlice(strs)
//
// // Convert []*string to []string
// strs = aws.StringValueSlice(strPtrs)
//
// SDK Default HTTP Client
//
// The SDK will use the http.DefaultClient if a HTTP client is not provided to
// the SDK's Session, or service client constructor. This means that if the
// http.DefaultClient is modified by other components of your application the
// modifications will be picked up by the SDK as well.
//
// In some cases this might be intended, but it is a better practice to create
// a custom HTTP Client to share explicitly through your application. You can
// configure the SDK to use the custom HTTP Client by setting the HTTPClient
// value of the SDK's Config type when creating a Session or service client.
package aws
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/api.go
================================================
package ec2metadata
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkuri"
)
// getToken uses the duration to return a token for EC2 metadata service,
// or an error if the request failed.
func (c *EC2Metadata) getToken(ctx aws.Context, duration time.Duration) (tokenOutput, error) {
op := &request.Operation{
Name: "GetToken",
HTTPMethod: "PUT",
HTTPPath: "/latest/api/token",
}
var output tokenOutput
req := c.NewRequest(op, nil, &output)
req.SetContext(ctx)
// remove the fetch token handler from the request handlers to avoid infinite recursion
req.Handlers.Sign.RemoveByName(fetchTokenHandlerName)
// Swap the unmarshalMetadataHandler with unmarshalTokenHandler on this request.
req.Handlers.Unmarshal.Swap(unmarshalMetadataHandlerName, unmarshalTokenHandler)
ttl := strconv.FormatInt(int64(duration/time.Second), 10)
req.HTTPRequest.Header.Set(ttlHeader, ttl)
err := req.Send()
// Errors with bad request status should be returned.
if err != nil {
err = awserr.NewRequestFailure(
awserr.New(req.HTTPResponse.Status, http.StatusText(req.HTTPResponse.StatusCode), err),
req.HTTPResponse.StatusCode, req.RequestID)
}
return output, err
}
// GetMetadata uses the path provided to request information from the EC2
// instance metadata service. The content will be returned as a string, or
// error if the request failed.
func (c *EC2Metadata) GetMetadata(p string) (string, error) {
return c.GetMetadataWithContext(aws.BackgroundContext(), p)
}
// GetMetadataWithContext uses the path provided to request information from the EC2
// instance metadata service. The content will be returned as a string, or
// error if the request failed.
func (c *EC2Metadata) GetMetadataWithContext(ctx aws.Context, p string) (string, error) {
op := &request.Operation{
Name: "GetMetadata",
HTTPMethod: "GET",
HTTPPath: sdkuri.PathJoin("/latest/meta-data", p),
}
output := &metadataOutput{}
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
}
// GetUserData returns the userdata that was configured for the service. If
// there is no user-data setup for the EC2 instance a "NotFoundError" error
// code will be returned.
func (c *EC2Metadata) GetUserData() (string, error) {
return c.GetUserDataWithContext(aws.BackgroundContext())
}
// GetUserDataWithContext returns the userdata that was configured for the service. If
// there is no user-data setup for the EC2 instance a "NotFoundError" error
// code will be returned.
func (c *EC2Metadata) GetUserDataWithContext(ctx aws.Context) (string, error) {
op := &request.Operation{
Name: "GetUserData",
HTTPMethod: "GET",
HTTPPath: "/latest/user-data",
}
output := &metadataOutput{}
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
}
// GetDynamicData uses the path provided to request information from the EC2
// instance metadata service for dynamic data. The content will be returned
// as a string, or error if the request failed.
func (c *EC2Metadata) GetDynamicData(p string) (string, error) {
return c.GetDynamicDataWithContext(aws.BackgroundContext(), p)
}
// GetDynamicDataWithContext uses the path provided to request information from the EC2
// instance metadata service for dynamic data. The content will be returned
// as a string, or error if the request failed.
func (c *EC2Metadata) GetDynamicDataWithContext(ctx aws.Context, p string) (string, error) {
op := &request.Operation{
Name: "GetDynamicData",
HTTPMethod: "GET",
HTTPPath: sdkuri.PathJoin("/latest/dynamic", p),
}
output := &metadataOutput{}
req := c.NewRequest(op, nil, output)
req.SetContext(ctx)
err := req.Send()
return output.Content, err
}
// GetInstanceIdentityDocument retrieves an identity document describing an
// instance. Error is returned if the request fails or is unable to parse
// the response.
func (c *EC2Metadata) GetInstanceIdentityDocument() (EC2InstanceIdentityDocument, error) {
return c.GetInstanceIdentityDocumentWithContext(aws.BackgroundContext())
}
// GetInstanceIdentityDocumentWithContext retrieves an identity document describing an
// instance. Error is returned if the request fails or is unable to parse
// the response.
func (c *EC2Metadata) GetInstanceIdentityDocumentWithContext(ctx aws.Context) (EC2InstanceIdentityDocument, error) {
resp, err := c.GetDynamicDataWithContext(ctx, "instance-identity/document")
if err != nil {
return EC2InstanceIdentityDocument{},
awserr.New("EC2MetadataRequestError",
"failed to get EC2 instance identity document", err)
}
doc := EC2InstanceIdentityDocument{}
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&doc); err != nil {
return EC2InstanceIdentityDocument{},
awserr.New(request.ErrCodeSerialization,
"failed to decode EC2 instance identity document", err)
}
return doc, nil
}
// IAMInfo retrieves IAM info from the metadata API
func (c *EC2Metadata) IAMInfo() (EC2IAMInfo, error) {
return c.IAMInfoWithContext(aws.BackgroundContext())
}
// IAMInfoWithContext retrieves IAM info from the metadata API
func (c *EC2Metadata) IAMInfoWithContext(ctx aws.Context) (EC2IAMInfo, error) {
resp, err := c.GetMetadataWithContext(ctx, "iam/info")
if err != nil {
return EC2IAMInfo{},
awserr.New("EC2MetadataRequestError",
"failed to get EC2 IAM info", err)
}
info := EC2IAMInfo{}
if err := json.NewDecoder(strings.NewReader(resp)).Decode(&info); err != nil {
return EC2IAMInfo{},
awserr.New(request.ErrCodeSerialization,
"failed to decode EC2 IAM info", err)
}
if info.Code != "Success" {
errMsg := fmt.Sprintf("failed to get EC2 IAM Info (%s)", info.Code)
return EC2IAMInfo{},
awserr.New("EC2MetadataError", errMsg, nil)
}
return info, nil
}
// Region returns the region the instance is running in.
func (c *EC2Metadata) Region() (string, error) {
return c.RegionWithContext(aws.BackgroundContext())
}
// RegionWithContext returns the region the instance is running in.
func (c *EC2Metadata) RegionWithContext(ctx aws.Context) (string, error) {
ec2InstanceIdentityDocument, err := c.GetInstanceIdentityDocumentWithContext(ctx)
if err != nil {
return "", err
}
// extract region from the ec2InstanceIdentityDocument
region := ec2InstanceIdentityDocument.Region
if len(region) == 0 {
return "", awserr.New("EC2MetadataError", "invalid region received for ec2metadata instance", nil)
}
// returns region
return region, nil
}
// Available returns if the application has access to the EC2 Metadata service.
// Can be used to determine if application is running within an EC2 Instance and
// the metadata service is available.
func (c *EC2Metadata) Available() bool {
return c.AvailableWithContext(aws.BackgroundContext())
}
// AvailableWithContext returns if the application has access to the EC2 Metadata service.
// Can be used to determine if application is running within an EC2 Instance and
// the metadata service is available.
func (c *EC2Metadata) AvailableWithContext(ctx aws.Context) bool {
if _, err := c.GetMetadataWithContext(ctx, "instance-id"); err != nil {
return false
}
return true
}
// An EC2IAMInfo provides the shape for unmarshaling
// an IAM info from the metadata API
type EC2IAMInfo struct {
Code string
LastUpdated time.Time
InstanceProfileArn string
InstanceProfileID string
}
// An EC2InstanceIdentityDocument provides the shape for unmarshaling
// an instance identity document
type EC2InstanceIdentityDocument struct {
DevpayProductCodes []string `json:"devpayProductCodes"`
MarketplaceProductCodes []string `json:"marketplaceProductCodes"`
AvailabilityZone string `json:"availabilityZone"`
PrivateIP string `json:"privateIp"`
Version string `json:"version"`
Region string `json:"region"`
InstanceID string `json:"instanceId"`
BillingProducts []string `json:"billingProducts"`
InstanceType string `json:"instanceType"`
AccountID string `json:"accountId"`
PendingTime time.Time `json:"pendingTime"`
ImageID string `json:"imageId"`
KernelID string `json:"kernelId"`
RamdiskID string `json:"ramdiskId"`
Architecture string `json:"architecture"`
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go
================================================
// Package ec2metadata provides the client for making API calls to the
// EC2 Metadata service.
//
// This package's client can be disabled completely by setting the environment
// variable "AWS_EC2_METADATA_DISABLED=true". This environment variable set to
// true instructs the SDK to disable the EC2 Metadata client. The client cannot
// be used while the environment variable is set to true, (case insensitive).
//
// The endpoint of the EC2 IMDS client can be configured via the environment
// variable, AWS_EC2_METADATA_SERVICE_ENDPOINT when creating the client with a
// Session. See aws/session#Options.EC2IMDSEndpoint for more details.
package ec2metadata
import (
"bytes"
"io"
"net/http"
"net/url"
"os"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/request"
)
const (
// ServiceName is the name of the service.
ServiceName = "ec2metadata"
disableServiceEnvVar = "AWS_EC2_METADATA_DISABLED"
// Headers for Token and TTL
ttlHeader = "x-aws-ec2-metadata-token-ttl-seconds"
tokenHeader = "x-aws-ec2-metadata-token"
// Named Handler constants
fetchTokenHandlerName = "FetchTokenHandler"
unmarshalMetadataHandlerName = "unmarshalMetadataHandler"
unmarshalTokenHandlerName = "unmarshalTokenHandler"
enableTokenProviderHandlerName = "enableTokenProviderHandler"
// TTL constants
defaultTTL = 21600 * time.Second
ttlExpirationWindow = 30 * time.Second
)
// A EC2Metadata is an EC2 Metadata service Client.
type EC2Metadata struct {
*client.Client
}
// New creates a new instance of the EC2Metadata client with a session.
// This client is safe to use across multiple goroutines.
//
//
// Example:
// // Create a EC2Metadata client from just a session.
// svc := ec2metadata.New(mySession)
//
// // Create a EC2Metadata client with additional configuration
// svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata {
c := p.ClientConfig(ServiceName, cfgs...)
return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
}
// NewClient returns a new EC2Metadata client. Should be used to create
// a client when not using a session. Generally using just New with a session
// is preferred.
//
// Will remove the URL path from the endpoint provided to ensure the EC2 IMDS
// client is able to communicate with the EC2 IMDS API.
//
// If an unmodified HTTP client is provided from the stdlib default, or no client
// the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened.
// To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default.
func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata {
if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) {
// If the http client is unmodified and this feature is not disabled
// set custom timeouts for EC2Metadata requests.
cfg.HTTPClient = &http.Client{
// use a shorter timeout than default because the metadata
// service is local if it is running, and to fail faster
// if not running on an ec2 instance.
Timeout: 1 * time.Second,
}
// max number of retries on the client operation
cfg.MaxRetries = aws.Int(2)
}
if u, err := url.Parse(endpoint); err == nil {
// Remove path from the endpoint since it will be added by requests.
// This is an artifact of the SDK adding `/latest` to the endpoint for
// EC2 IMDS, but this is now moved to the operation definition.
u.Path = ""
u.RawPath = ""
endpoint = u.String()
}
svc := &EC2Metadata{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceName,
Endpoint: endpoint,
APIVersion: "latest",
},
handlers,
),
}
// token provider instance
tp := newTokenProvider(svc, defaultTTL)
// NamedHandler for fetching token
svc.Handlers.Sign.PushBackNamed(request.NamedHandler{
Name: fetchTokenHandlerName,
Fn: tp.fetchTokenHandler,
})
// NamedHandler for enabling token provider
svc.Handlers.Complete.PushBackNamed(request.NamedHandler{
Name: enableTokenProviderHandlerName,
Fn: tp.enableTokenProviderHandler,
})
svc.Handlers.Unmarshal.PushBackNamed(unmarshalHandler)
svc.Handlers.UnmarshalError.PushBack(unmarshalError)
svc.Handlers.Validate.Clear()
svc.Handlers.Validate.PushBack(validateEndpointHandler)
// Disable the EC2 Metadata service if the environment variable is set.
// This short-circuits the service's functionality to always fail to send
// requests.
if strings.ToLower(os.Getenv(disableServiceEnvVar)) == "true" {
svc.Handlers.Send.SwapNamed(request.NamedHandler{
Name: corehandlers.SendHandler.Name,
Fn: func(r *request.Request) {
r.HTTPResponse = &http.Response{
Header: http.Header{},
}
r.Error = awserr.New(
request.CanceledErrorCode,
"EC2 IMDS access disabled via "+disableServiceEnvVar+" env var",
nil)
},
})
}
// Add additional options to the service config
for _, option := range opts {
option(svc.Client)
}
return svc
}
func httpClientZero(c *http.Client) bool {
return c == nil || (c.Transport == nil && c.CheckRedirect == nil && c.Jar == nil && c.Timeout == 0)
}
type metadataOutput struct {
Content string
}
type tokenOutput struct {
Token string
TTL time.Duration
}
// unmarshal token handler is used to parse the response of a getToken operation
var unmarshalTokenHandler = request.NamedHandler{
Name: unmarshalTokenHandlerName,
Fn: func(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var b bytes.Buffer
if _, err := io.Copy(&b, r.HTTPResponse.Body); err != nil {
r.Error = awserr.NewRequestFailure(awserr.New(request.ErrCodeSerialization,
"unable to unmarshal EC2 metadata response", err), r.HTTPResponse.StatusCode, r.RequestID)
return
}
v := r.HTTPResponse.Header.Get(ttlHeader)
data, ok := r.Data.(*tokenOutput)
if !ok {
return
}
data.Token = b.String()
// TTL is in seconds
i, err := strconv.ParseInt(v, 10, 64)
if err != nil {
r.Error = awserr.NewRequestFailure(awserr.New(request.ParamFormatErrCode,
"unable to parse EC2 token TTL response", err), r.HTTPResponse.StatusCode, r.RequestID)
return
}
t := time.Duration(i) * time.Second
data.TTL = t
},
}
var unmarshalHandler = request.NamedHandler{
Name: unmarshalMetadataHandlerName,
Fn: func(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var b bytes.Buffer
if _, err := io.Copy(&b, r.HTTPResponse.Body); err != nil {
r.Error = awserr.NewRequestFailure(awserr.New(request.ErrCodeSerialization,
"unable to unmarshal EC2 metadata response", err), r.HTTPResponse.StatusCode, r.RequestID)
return
}
if data, ok := r.Data.(*metadataOutput); ok {
data.Content = b.String()
}
},
}
func unmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var b bytes.Buffer
if _, err := io.Copy(&b, r.HTTPResponse.Body); err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization, "unable to unmarshal EC2 metadata error response", err),
r.HTTPResponse.StatusCode, r.RequestID)
return
}
// Response body format is not consistent between metadata endpoints.
// Grab the error message as a string and include that as the source error
r.Error = awserr.NewRequestFailure(
awserr.New("EC2MetadataError", "failed to make EC2Metadata request\n"+b.String(), nil),
r.HTTPResponse.StatusCode, r.RequestID)
}
func validateEndpointHandler(r *request.Request) {
if r.ClientInfo.Endpoint == "" {
r.Error = aws.ErrMissingEndpoint
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/token_provider.go
================================================
package ec2metadata
import (
"net/http"
"sync/atomic"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
)
// A tokenProvider struct provides access to EC2Metadata client
// and atomic instance of a token, along with configuredTTL for it.
// tokenProvider also provides an atomic flag to disable the
// fetch token operation.
// The disabled member will use 0 as false, and 1 as true.
type tokenProvider struct {
client *EC2Metadata
token atomic.Value
configuredTTL time.Duration
disabled uint32
}
// A ec2Token struct helps use of token in EC2 Metadata service ops
type ec2Token struct {
token string
credentials.Expiry
}
// newTokenProvider provides a pointer to a tokenProvider instance
func newTokenProvider(c *EC2Metadata, duration time.Duration) *tokenProvider {
return &tokenProvider{client: c, configuredTTL: duration}
}
// fetchTokenHandler fetches token for EC2Metadata service client by default.
func (t *tokenProvider) fetchTokenHandler(r *request.Request) {
// short-circuits to insecure data flow if tokenProvider is disabled.
if v := atomic.LoadUint32(&t.disabled); v == 1 {
return
}
if ec2Token, ok := t.token.Load().(ec2Token); ok && !ec2Token.IsExpired() {
r.HTTPRequest.Header.Set(tokenHeader, ec2Token.token)
return
}
output, err := t.client.getToken(r.Context(), t.configuredTTL)
if err != nil {
// change the disabled flag on token provider to true,
// when error is request timeout error.
if requestFailureError, ok := err.(awserr.RequestFailure); ok {
switch requestFailureError.StatusCode() {
case http.StatusForbidden, http.StatusNotFound, http.StatusMethodNotAllowed:
atomic.StoreUint32(&t.disabled, 1)
case http.StatusBadRequest:
r.Error = requestFailureError
}
// Check if request timed out while waiting for response
if e, ok := requestFailureError.OrigErr().(awserr.Error); ok {
if e.Code() == request.ErrCodeRequestError {
atomic.StoreUint32(&t.disabled, 1)
}
}
}
return
}
newToken := ec2Token{
token: output.Token,
}
newToken.SetExpiration(time.Now().Add(output.TTL), ttlExpirationWindow)
t.token.Store(newToken)
// Inject token header to the request.
if ec2Token, ok := t.token.Load().(ec2Token); ok {
r.HTTPRequest.Header.Set(tokenHeader, ec2Token.token)
}
}
// enableTokenProviderHandler enables the token provider
func (t *tokenProvider) enableTokenProviderHandler(r *request.Request) {
// If the error code status is 401, we enable the token provider
if e, ok := r.Error.(awserr.RequestFailure); ok && e != nil &&
e.StatusCode() == http.StatusUnauthorized {
t.token.Store(ec2Token{})
atomic.StoreUint32(&t.disabled, 0)
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/decode.go
================================================
package endpoints
import (
"encoding/json"
"fmt"
"io"
"github.com/aws/aws-sdk-go/aws/awserr"
)
type modelDefinition map[string]json.RawMessage
// A DecodeModelOptions are the options for how the endpoints model definition
// are decoded.
type DecodeModelOptions struct {
SkipCustomizations bool
}
// Set combines all of the option functions together.
func (d *DecodeModelOptions) Set(optFns ...func(*DecodeModelOptions)) {
for _, fn := range optFns {
fn(d)
}
}
// DecodeModel unmarshals a Regions and Endpoint model definition file into
// a endpoint Resolver. If the file format is not supported, or an error occurs
// when unmarshaling the model an error will be returned.
//
// Casting the return value of this func to a EnumPartitions will
// allow you to get a list of the partitions in the order the endpoints
// will be resolved in.
//
// resolver, err := endpoints.DecodeModel(reader)
//
// partitions := resolver.(endpoints.EnumPartitions).Partitions()
// for _, p := range partitions {
// // ... inspect partitions
// }
func DecodeModel(r io.Reader, optFns ...func(*DecodeModelOptions)) (Resolver, error) {
var opts DecodeModelOptions
opts.Set(optFns...)
// Get the version of the partition file to determine what
// unmarshaling model to use.
modelDef := modelDefinition{}
if err := json.NewDecoder(r).Decode(&modelDef); err != nil {
return nil, newDecodeModelError("failed to decode endpoints model", err)
}
var version string
if b, ok := modelDef["version"]; ok {
version = string(b)
} else {
return nil, newDecodeModelError("endpoints version not found in model", nil)
}
if version == "3" {
return decodeV3Endpoints(modelDef, opts)
}
return nil, newDecodeModelError(
fmt.Sprintf("endpoints version %s, not supported", version), nil)
}
func decodeV3Endpoints(modelDef modelDefinition, opts DecodeModelOptions) (Resolver, error) {
b, ok := modelDef["partitions"]
if !ok {
return nil, newDecodeModelError("endpoints model missing partitions", nil)
}
ps := partitions{}
if err := json.Unmarshal(b, &ps); err != nil {
return nil, newDecodeModelError("failed to decode endpoints model", err)
}
if opts.SkipCustomizations {
return ps, nil
}
// Customization
for i := 0; i < len(ps); i++ {
p := &ps[i]
custRegionalS3(p)
custRmIotDataService(p)
custFixAppAutoscalingChina(p)
custFixAppAutoscalingUsGov(p)
}
return ps, nil
}
func custRegionalS3(p *partition) {
if p.ID != "aws" {
return
}
service, ok := p.Services["s3"]
if !ok {
return
}
const awsGlobal = "aws-global"
const usEast1 = "us-east-1"
// If global endpoint already exists no customization needed.
if _, ok := service.Endpoints[endpointKey{Region: awsGlobal}]; ok {
return
}
service.PartitionEndpoint = awsGlobal
if _, ok := service.Endpoints[endpointKey{Region: usEast1}]; !ok {
service.Endpoints[endpointKey{Region: usEast1}] = endpoint{}
}
service.Endpoints[endpointKey{Region: awsGlobal}] = endpoint{
Hostname: "s3.amazonaws.com",
CredentialScope: credentialScope{
Region: usEast1,
},
}
p.Services["s3"] = service
}
func custRmIotDataService(p *partition) {
delete(p.Services, "data.iot")
}
func custFixAppAutoscalingChina(p *partition) {
if p.ID != "aws-cn" {
return
}
const serviceName = "application-autoscaling"
s, ok := p.Services[serviceName]
if !ok {
return
}
const expectHostname = `autoscaling.{region}.amazonaws.com`
serviceDefault := s.Defaults[defaultKey{}]
if e, a := expectHostname, serviceDefault.Hostname; e != a {
fmt.Printf("custFixAppAutoscalingChina: ignoring customization, expected %s, got %s\n", e, a)
return
}
serviceDefault.Hostname = expectHostname + ".cn"
s.Defaults[defaultKey{}] = serviceDefault
p.Services[serviceName] = s
}
func custFixAppAutoscalingUsGov(p *partition) {
if p.ID != "aws-us-gov" {
return
}
const serviceName = "application-autoscaling"
s, ok := p.Services[serviceName]
if !ok {
return
}
serviceDefault := s.Defaults[defaultKey{}]
if a := serviceDefault.CredentialScope.Service; a != "" {
fmt.Printf("custFixAppAutoscalingUsGov: ignoring customization, expected empty credential scope service, got %s\n", a)
return
}
if a := serviceDefault.Hostname; a != "" {
fmt.Printf("custFixAppAutoscalingUsGov: ignoring customization, expected empty hostname, got %s\n", a)
return
}
serviceDefault.CredentialScope.Service = "application-autoscaling"
serviceDefault.Hostname = "autoscaling.{region}.amazonaws.com"
if s.Defaults == nil {
s.Defaults = make(endpointDefaults)
}
s.Defaults[defaultKey{}] = serviceDefault
p.Services[serviceName] = s
}
type decodeModelError struct {
awsError
}
func newDecodeModelError(msg string, err error) decodeModelError {
return decodeModelError{
awsError: awserr.New("DecodeEndpointsModelError", msg, err),
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
================================================
// Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT.
package endpoints
import (
"regexp"
)
// Partition identifiers
const (
AwsPartitionID = "aws" // AWS Standard partition.
AwsCnPartitionID = "aws-cn" // AWS China partition.
AwsUsGovPartitionID = "aws-us-gov" // AWS GovCloud (US) partition.
AwsIsoPartitionID = "aws-iso" // AWS ISO (US) partition.
AwsIsoBPartitionID = "aws-iso-b" // AWS ISOB (US) partition.
)
// AWS Standard partition's regions.
const (
AfSouth1RegionID = "af-south-1" // Africa (Cape Town).
ApEast1RegionID = "ap-east-1" // Asia Pacific (Hong Kong).
ApNortheast1RegionID = "ap-northeast-1" // Asia Pacific (Tokyo).
ApNortheast2RegionID = "ap-northeast-2" // Asia Pacific (Seoul).
ApNortheast3RegionID = "ap-northeast-3" // Asia Pacific (Osaka).
ApSouth1RegionID = "ap-south-1" // Asia Pacific (Mumbai).
ApSoutheast1RegionID = "ap-southeast-1" // Asia Pacific (Singapore).
ApSoutheast2RegionID = "ap-southeast-2" // Asia Pacific (Sydney).
ApSoutheast3RegionID = "ap-southeast-3" // Asia Pacific (Jakarta).
CaCentral1RegionID = "ca-central-1" // Canada (Central).
EuCentral1RegionID = "eu-central-1" // Europe (Frankfurt).
EuNorth1RegionID = "eu-north-1" // Europe (Stockholm).
EuSouth1RegionID = "eu-south-1" // Europe (Milan).
EuWest1RegionID = "eu-west-1" // Europe (Ireland).
EuWest2RegionID = "eu-west-2" // Europe (London).
EuWest3RegionID = "eu-west-3" // Europe (Paris).
MeSouth1RegionID = "me-south-1" // Middle East (Bahrain).
SaEast1RegionID = "sa-east-1" // South America (Sao Paulo).
UsEast1RegionID = "us-east-1" // US East (N. Virginia).
UsEast2RegionID = "us-east-2" // US East (Ohio).
UsWest1RegionID = "us-west-1" // US West (N. California).
UsWest2RegionID = "us-west-2" // US West (Oregon).
)
// AWS China partition's regions.
const (
CnNorth1RegionID = "cn-north-1" // China (Beijing).
CnNorthwest1RegionID = "cn-northwest-1" // China (Ningxia).
)
// AWS GovCloud (US) partition's regions.
const (
UsGovEast1RegionID = "us-gov-east-1" // AWS GovCloud (US-East).
UsGovWest1RegionID = "us-gov-west-1" // AWS GovCloud (US-West).
)
// AWS ISO (US) partition's regions.
const (
UsIsoEast1RegionID = "us-iso-east-1" // US ISO East.
UsIsoWest1RegionID = "us-iso-west-1" // US ISO WEST.
)
// AWS ISOB (US) partition's regions.
const (
UsIsobEast1RegionID = "us-isob-east-1" // US ISOB East (Ohio).
)
// DefaultResolver returns an Endpoint resolver that will be able
// to resolve endpoints for: AWS Standard, AWS China, AWS GovCloud (US), AWS ISO (US), and AWS ISOB (US).
//
// Use DefaultPartitions() to get the list of the default partitions.
func DefaultResolver() Resolver {
return defaultPartitions
}
// DefaultPartitions returns a list of the partitions the SDK is bundled
// with. The available partitions are: AWS Standard, AWS China, AWS GovCloud (US), AWS ISO (US), and AWS ISOB (US).
//
// partitions := endpoints.DefaultPartitions
// for _, p := range partitions {
// // ... inspect partitions
// }
func DefaultPartitions() []Partition {
return defaultPartitions.Partitions()
}
var defaultPartitions = partitions{
awsPartition,
awscnPartition,
awsusgovPartition,
awsisoPartition,
awsisobPartition,
}
// AwsPartition returns the Resolver for AWS Standard.
func AwsPartition() Partition {
return awsPartition.Partition()
}
var awsPartition = partition{
ID: "aws",
Name: "AWS Standard",
DNSSuffix: "amazonaws.com",
RegionRegex: regionRegex{
Regexp: func() *regexp.Regexp {
reg, _ := regexp.Compile("^(us|eu|ap|sa|ca|me|af)\\-\\w+\\-\\d+$")
return reg
}(),
},
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
DNSSuffix: "api.aws",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "api.aws",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
Regions: regions{
"af-south-1": region{
Description: "Africa (Cape Town)",
},
"ap-east-1": region{
Description: "Asia Pacific (Hong Kong)",
},
"ap-northeast-1": region{
Description: "Asia Pacific (Tokyo)",
},
"ap-northeast-2": region{
Description: "Asia Pacific (Seoul)",
},
"ap-northeast-3": region{
Description: "Asia Pacific (Osaka)",
},
"ap-south-1": region{
Description: "Asia Pacific (Mumbai)",
},
"ap-southeast-1": region{
Description: "Asia Pacific (Singapore)",
},
"ap-southeast-2": region{
Description: "Asia Pacific (Sydney)",
},
"ap-southeast-3": region{
Description: "Asia Pacific (Jakarta)",
},
"ca-central-1": region{
Description: "Canada (Central)",
},
"eu-central-1": region{
Description: "Europe (Frankfurt)",
},
"eu-north-1": region{
Description: "Europe (Stockholm)",
},
"eu-south-1": region{
Description: "Europe (Milan)",
},
"eu-west-1": region{
Description: "Europe (Ireland)",
},
"eu-west-2": region{
Description: "Europe (London)",
},
"eu-west-3": region{
Description: "Europe (Paris)",
},
"me-south-1": region{
Description: "Middle East (Bahrain)",
},
"sa-east-1": region{
Description: "South America (Sao Paulo)",
},
"us-east-1": region{
Description: "US East (N. Virginia)",
},
"us-east-2": region{
Description: "US East (Ohio)",
},
"us-west-1": region{
Description: "US West (N. California)",
},
"us-west-2": region{
Description: "US West (Oregon)",
},
},
Services: services{
"a4b": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"access-analyzer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "access-analyzer-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "access-analyzer-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "access-analyzer-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "access-analyzer-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "access-analyzer-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "access-analyzer-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "access-analyzer-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "access-analyzer-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "access-analyzer-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "access-analyzer-fips.us-west-2.amazonaws.com",
},
},
},
"account": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "account.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"acm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "acm-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "acm-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "acm-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "acm-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "acm-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"acm-pca": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "acm-pca-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "acm-pca-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "acm-pca-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "acm-pca-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "acm-pca-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca-fips.us-west-2.amazonaws.com",
},
},
},
"airflow": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"amplify": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"amplifybackend": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"amplifyuibuilder": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"api.detective": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "api.detective-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "api.detective-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "api.detective-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "api.detective-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"api.ecr": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{
Hostname: "api.ecr.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
},
endpointKey{
Region: "ap-east-1",
}: endpoint{
Hostname: "api.ecr.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "api.ecr.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "api.ecr.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{
Hostname: "api.ecr.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "api.ecr.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "api.ecr.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "api.ecr.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{
Hostname: "api.ecr.ap-southeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-3",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "api.ecr.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "dkr-us-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-west-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "api.ecr.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "api.ecr.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-south-1",
}: endpoint{
Hostname: "api.ecr.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "api.ecr.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "api.ecr.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "api.ecr.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "fips-dkr-us-east-1",
}: endpoint{
Hostname: "ecr-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-dkr-us-east-2",
}: endpoint{
Hostname: "ecr-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-dkr-us-west-1",
}: endpoint{
Hostname: "ecr-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-dkr-us-west-2",
}: endpoint{
Hostname: "ecr-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ecr-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ecr-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ecr-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ecr-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{
Hostname: "api.ecr.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "api.ecr.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "api.ecr.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "api.ecr.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "api.ecr.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "api.ecr.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"api.elastic-inference": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "api.elastic-inference.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "api.elastic-inference.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "api.elastic-inference.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "api.elastic-inference.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "api.elastic-inference.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "api.elastic-inference.us-west-2.amazonaws.com",
},
},
},
"api.fleethub.iot": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.fleethub.iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "api.fleethub.iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.fleethub.iot-fips.us-west-2.amazonaws.com",
},
},
},
"api.iotwireless": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "api.iotwireless.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "api.iotwireless.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "api.iotwireless.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "api.iotwireless.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "api.iotwireless.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"api.mediatailor": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"api.pricing": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "pricing",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"api.sagemaker": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "api-fips.sagemaker.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "api-fips.sagemaker.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "api-fips.sagemaker.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "api-fips.sagemaker.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"api.tunneling.iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-2.amazonaws.com",
},
},
},
"apigateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"app-integrations": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"appconfigdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"appflow": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"application-autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"applicationinsights": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"appmesh": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"apprunner": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "apprunner-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "apprunner-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "apprunner-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "apprunner-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "apprunner-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "apprunner-fips.us-west-2.amazonaws.com",
},
},
},
"appstream2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
CredentialScope: credentialScope{
Service: "appstream",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "appstream2-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "appstream2-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "appstream2-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "appstream2-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "appstream2-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"appsync": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"aps": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"athena": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "athena-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "athena-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "athena-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "athena-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-west-2.amazonaws.com",
},
},
},
"auditmanager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"autoscaling-plans": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"backup": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"batch": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.batch.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "fips.batch.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "fips.batch.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "fips.batch.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "fips.batch.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.batch.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.batch.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.batch.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.batch.us-west-2.amazonaws.com",
},
},
},
"billingconductor": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "billingconductor.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"braket": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"budgets": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "budgets.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"ce": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "ce.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"chime": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "chime.us-east-1.amazonaws.com",
Protocols: []string{"https"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"cloud9": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cloudcontrolapi": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "cloudcontrolapi-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-west-2.amazonaws.com",
},
},
},
"clouddirectory": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cloudformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudformation-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "cloudformation-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudformation-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "cloudformation-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudformation-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "cloudformation-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudformation-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "cloudformation-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"cloudfront": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "cloudfront.amazonaws.com",
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"cloudhsm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"cloudhsmv2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "cloudhsm",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cloudsearch": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cloudtrail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "cloudtrail-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "cloudtrail-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "cloudtrail-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "cloudtrail-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail-fips.us-west-2.amazonaws.com",
},
},
},
"codeartifact": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"codebuild": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "codebuild-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "codebuild-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "codebuild-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "codebuild-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"codecommit": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "codecommit-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "codecommit-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "codecommit-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "codecommit-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "codecommit-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "codecommit-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"codedeploy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"codeguru-reviewer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"codepipeline": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "codepipeline-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "codepipeline-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "codepipeline-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "codepipeline-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "codepipeline-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.us-west-2.amazonaws.com",
},
},
},
"codestar": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"codestar-connections": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cognito-identity": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "cognito-identity-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "cognito-identity-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "cognito-identity-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-identity-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-identity-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-identity-fips.us-west-2.amazonaws.com",
},
},
},
"cognito-idp": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "cognito-idp-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "cognito-idp-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "cognito-idp-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "cognito-idp-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-idp-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-idp-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-idp-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-idp-fips.us-west-2.amazonaws.com",
},
},
},
"cognito-sync": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"comprehend": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "comprehend-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "comprehend-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "comprehend-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehend-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehend-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehend-fips.us-west-2.amazonaws.com",
},
},
},
"comprehendmedical": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "comprehendmedical-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "comprehendmedical-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "comprehendmedical-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehendmedical-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehendmedical-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehendmedical-fips.us-west-2.amazonaws.com",
},
},
},
"compute-optimizer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "compute-optimizer.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "compute-optimizer.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "compute-optimizer.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "compute-optimizer.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "compute-optimizer.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "compute-optimizer.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "compute-optimizer.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "compute-optimizer.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "compute-optimizer.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "compute-optimizer.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "compute-optimizer.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "compute-optimizer.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "compute-optimizer.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "compute-optimizer.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "compute-optimizer.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "compute-optimizer.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"config": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "config-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "config-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "config-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "config-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "config-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "config-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "config-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "config-fips.us-west-2.amazonaws.com",
},
},
},
"connect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"contact-lens": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"cur": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"data-ats.iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
CredentialScope: credentialScope{
Service: "iotdata",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "data.iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "data.iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "data.iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "data.iot-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "data.iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-west-2.amazonaws.com",
},
},
},
"data.jobs.iot": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "data.jobs.iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-west-2.amazonaws.com",
},
},
},
"data.mediastore": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"databrew": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"dataexchange": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"datapipeline": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"datasync": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "datasync-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "datasync-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "datasync-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "datasync-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "datasync-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-west-2.amazonaws.com",
},
},
},
"dax": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"devicefarm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "directconnect-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "directconnect-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "directconnect-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "directconnect-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-west-2.amazonaws.com",
},
},
},
"discovery": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"dms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "dms",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms-fips",
}: endpoint{
Hostname: "dms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "dms-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "dms-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "dms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "dms-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"docdb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "rds.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "rds.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "rds.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "rds.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "rds.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "rds.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "rds.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "rds.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "rds.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "rds.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "rds.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "rds.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "rds.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "rds.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"drs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"ds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "ds-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ds-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ds-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ds-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ds-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-west-2.amazonaws.com",
},
},
},
"dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "dynamodb-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "local",
}: endpoint{
Hostname: "localhost:8000",
Protocols: []string{"http"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "dynamodb-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "dynamodb-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "dynamodb-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "dynamodb-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"ebs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ebs-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "ebs-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ebs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ebs-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ebs-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ebs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ebs-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ebs-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ebs-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ebs-fips.us-west-2.amazonaws.com",
},
},
},
"ec2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.ap-south-1.aws",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.eu-west-1.aws",
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "ec2-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ec2-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ec2-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ec2-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ec2-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.sa-east-1.aws",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.us-east-1.aws",
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.us-east-2.aws",
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "api.ec2.us-west-2.aws",
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2-fips.us-west-2.amazonaws.com",
},
},
},
"ecs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ecs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ecs-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ecs-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ecs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-west-2.amazonaws.com",
},
},
},
"eks": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.eks.{region}.{dnsSuffix}",
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "fips.eks.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "fips.eks.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "fips.eks.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "fips.eks.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.eks.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.eks.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.eks.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.eks.us-west-2.amazonaws.com",
},
},
},
"elasticache": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "elasticache-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "elasticache-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "elasticache-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "elasticache-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "elasticache-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"elasticbeanstalk": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticbeanstalk-fips.us-west-2.amazonaws.com",
},
},
},
"elasticfilesystem": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "af-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.af-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-east-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-3.amazonaws.com",
},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-3.amazonaws.com",
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-north-1.amazonaws.com",
},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-south-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-3.amazonaws.com",
},
endpointKey{
Region: "fips-af-south-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-east-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-2",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-3",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-south-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-2",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-3",
}: endpoint{
Hostname: "elasticfilesystem-fips.ap-southeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-central-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-north-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-south-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-2",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-3",
}: endpoint{
Hostname: "elasticfilesystem-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-me-south-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-sa-east-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "me-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.me-south-1.amazonaws.com",
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.sa-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-west-2.amazonaws.com",
},
},
},
"elasticloadbalancing": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing-fips.us-west-2.amazonaws.com",
},
},
},
"elasticmapreduce": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SSLCommonName: "{region}.{service}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
SSLCommonName: "{service}.{region}.{dnsSuffix}",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "elasticmapreduce-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "elasticmapreduce-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "elasticmapreduce-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "elasticmapreduce-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "elasticmapreduce-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{
SSLCommonName: "{service}.{region}.{dnsSuffix}",
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce-fips.us-east-1.amazonaws.com",
SSLCommonName: "{service}.{region}.{dnsSuffix}",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce-fips.us-west-2.amazonaws.com",
},
},
},
"elastictranscoder": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"email": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"emr-containers": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "emr-containers-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "emr-containers-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "emr-containers-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "emr-containers-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "emr-containers-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "emr-containers-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "emr-containers-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "emr-containers-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "emr-containers-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "emr-containers-fips.us-west-2.amazonaws.com",
},
},
},
"entitlement.marketplace": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "aws-marketplace",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"es": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "es-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "es-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "es-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "es-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "es-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"events": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "events-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "events-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "events-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "events-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "events-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "events-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "events-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "events-fips.us-west-2.amazonaws.com",
},
},
},
"evidently": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "evidently.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "evidently.ap-southeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "evidently.ap-southeast-2.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "evidently.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "evidently.eu-north-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "evidently.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "evidently.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "evidently.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "evidently.us-west-2.amazonaws.com",
},
},
},
"finspace": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"finspace-api": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"firehose": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "firehose-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "firehose-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "firehose-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "firehose-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-west-2.amazonaws.com",
},
},
},
"fms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "af-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.af-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-east-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-southeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ap-southeast-2.amazonaws.com",
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.eu-south-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.eu-west-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.eu-west-3.amazonaws.com",
},
endpointKey{
Region: "fips-af-south-1",
}: endpoint{
Hostname: "fms-fips.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-east-1",
}: endpoint{
Hostname: "fms-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-1",
}: endpoint{
Hostname: "fms-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-2",
}: endpoint{
Hostname: "fms-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-south-1",
}: endpoint{
Hostname: "fms-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-1",
}: endpoint{
Hostname: "fms-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-2",
}: endpoint{
Hostname: "fms-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "fms-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-central-1",
}: endpoint{
Hostname: "fms-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-south-1",
}: endpoint{
Hostname: "fms-fips.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-1",
}: endpoint{
Hostname: "fms-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-2",
}: endpoint{
Hostname: "fms-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-3",
}: endpoint{
Hostname: "fms-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-me-south-1",
}: endpoint{
Hostname: "fms-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-sa-east-1",
}: endpoint{
Hostname: "fms-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "fms-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "fms-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "fms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "fms-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "me-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.me-south-1.amazonaws.com",
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.sa-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-west-2.amazonaws.com",
},
},
},
"forecast": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "forecast-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "forecast-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "forecast-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecast-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecast-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecast-fips.us-west-2.amazonaws.com",
},
},
},
"forecastquery": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "forecastquery-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "forecastquery-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "forecastquery-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecastquery-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecastquery-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "forecastquery-fips.us-west-2.amazonaws.com",
},
},
},
"frauddetector": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"fsx": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "fsx-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-ca-central-1",
}: endpoint{
Hostname: "fsx-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-us-east-1",
}: endpoint{
Hostname: "fsx-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-us-east-2",
}: endpoint{
Hostname: "fsx-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-us-west-1",
}: endpoint{
Hostname: "fsx-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-us-west-2",
}: endpoint{
Hostname: "fsx-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "fsx-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "fsx-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "fsx-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "fsx-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "prod-ca-central-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-west-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-west-2.amazonaws.com",
},
},
},
"gamelift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"gamesparks": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"glacier": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glacier-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "glacier-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "glacier-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "glacier-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "glacier-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "glacier-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glacier-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "glacier-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glacier-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "glacier-fips.us-west-2.amazonaws.com",
},
},
},
"glue": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "glue-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "glue-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "glue-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "glue-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-west-2.amazonaws.com",
},
},
},
"grafana": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "grafana.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "grafana.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "grafana.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "grafana.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "grafana.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "grafana.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "grafana.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "grafana.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "grafana.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "grafana.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"greengrass": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"groundstation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "groundstation-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "groundstation-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "groundstation-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "groundstation-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "groundstation-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "groundstation-fips.us-west-2.amazonaws.com",
},
},
},
"guardduty": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "guardduty-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "guardduty-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "guardduty-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "guardduty-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"health": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "health-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "health-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
},
},
"healthlake": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"honeycode": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"iam": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "iam.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "iam-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global-fips",
}: endpoint{
Hostname: "iam-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam",
Variant: fipsVariant,
}: endpoint{
Hostname: "iam-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam-fips",
}: endpoint{
Hostname: "iam-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"identity-chime": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "identity-chime-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "identity-chime-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"identitystore": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"importexport": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "importexport.amazonaws.com",
SignatureVersions: []string{"v2", "v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
Service: "IngestionService",
},
},
},
},
"inspector": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "inspector-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "inspector-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "inspector-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "inspector-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-west-2.amazonaws.com",
},
},
},
"inspector2": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "execute-api",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "iot-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-west-2.amazonaws.com",
},
},
},
"iotanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"iotevents": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"ioteventsdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "data.iotevents.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "data.iotevents.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "data.iotevents.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "data.iotevents.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "data.iotevents.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "data.iotevents.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "data.iotevents.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "data.iotevents.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "data.iotevents.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "data.iotevents.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "data.iotevents.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"iotsecuredtunneling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-west-2.amazonaws.com",
},
},
},
"iotsitewise": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "iotsitewise-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "iotsitewise-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iotsitewise-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "iotsitewise-fips.us-west-2.amazonaws.com",
},
},
},
"iotthingsgraph": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "iotthingsgraph",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"iottwinmaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"iotwireless": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "api.iotwireless.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "api.iotwireless.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "api.iotwireless.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "api.iotwireless.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "api.iotwireless.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"ivs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"kafka": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"kafkaconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"kendra": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "kendra-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "kendra-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "kendra-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kendra-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kendra-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kendra-fips.us-west-2.amazonaws.com",
},
},
},
"kinesis": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "kinesis-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "kinesis-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "kinesis-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "kinesis-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kinesis-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kinesis-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kinesis-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kinesis-fips.us-west-2.amazonaws.com",
},
},
},
"kinesisanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"kinesisvideo": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"kms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "af-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.af-south-1.amazonaws.com",
},
endpointKey{
Region: "af-south-1-fips",
}: endpoint{
Hostname: "kms-fips.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-east-1.amazonaws.com",
},
endpointKey{
Region: "ap-east-1-fips",
}: endpoint{
Hostname: "kms-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-1-fips",
}: endpoint{
Hostname: "kms-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-2-fips",
}: endpoint{
Hostname: "kms-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-northeast-3.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-3-fips",
}: endpoint{
Hostname: "kms-fips.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-south-1-fips",
}: endpoint{
Hostname: "kms-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-southeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1-fips",
}: endpoint{
Hostname: "kms-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-southeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-2-fips",
}: endpoint{
Hostname: "kms-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ap-southeast-3.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-3-fips",
}: endpoint{
Hostname: "kms-fips.ap-southeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "kms-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1-fips",
}: endpoint{
Hostname: "kms-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-north-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1-fips",
}: endpoint{
Hostname: "kms-fips.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-south-1.amazonaws.com",
},
endpointKey{
Region: "eu-south-1-fips",
}: endpoint{
Hostname: "kms-fips.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-1-fips",
}: endpoint{
Hostname: "kms-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-west-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-2-fips",
}: endpoint{
Hostname: "kms-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.eu-west-3.amazonaws.com",
},
endpointKey{
Region: "eu-west-3-fips",
}: endpoint{
Hostname: "kms-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "me-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.me-south-1.amazonaws.com",
},
endpointKey{
Region: "me-south-1-fips",
}: endpoint{
Hostname: "kms-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.sa-east-1.amazonaws.com",
},
endpointKey{
Region: "sa-east-1-fips",
}: endpoint{
Hostname: "kms-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "kms-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "kms-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "kms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "kms-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"lakeformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "lakeformation-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "lakeformation-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "lakeformation-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "lakeformation-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lakeformation-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "lakeformation-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lakeformation-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "lakeformation-fips.us-west-2.amazonaws.com",
},
},
},
"lambda": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "af-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.af-south-1.api.aws",
},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-east-1.api.aws",
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-northeast-1.api.aws",
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-northeast-2.api.aws",
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-northeast-3.api.aws",
},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-south-1.api.aws",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-southeast-1.api.aws",
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-southeast-2.api.aws",
},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ap-southeast-3.api.aws",
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.ca-central-1.api.aws",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-central-1.api.aws",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-north-1.api.aws",
},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-south-1.api.aws",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-west-1.api.aws",
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-west-2.api.aws",
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.eu-west-3.api.aws",
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "lambda-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "lambda-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "lambda-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "lambda-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "me-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.me-south-1.api.aws",
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.sa-east-1.api.aws",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.us-east-1.api.aws",
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.us-east-2.api.aws",
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.us-west-1.api.aws",
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.us-west-2.api.aws",
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-west-2.amazonaws.com",
},
},
},
"license-manager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "license-manager-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "license-manager-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "license-manager-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "license-manager-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-west-2.amazonaws.com",
},
},
},
"lightsail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"logs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "logs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "logs-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "logs-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "logs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs-fips.us-west-2.amazonaws.com",
},
},
},
"lookoutequipment": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"lookoutmetrics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"lookoutvision": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"machinelearning": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"macie": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "macie-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "macie-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie-fips.us-west-2.amazonaws.com",
},
},
},
"macie2": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "macie2-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "macie2-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "macie2-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "macie2-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie2-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie2-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie2-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "macie2-fips.us-west-2.amazonaws.com",
},
},
},
"managedblockchain": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"marketplacecommerceanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"mediaconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mediaconvert": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mediaconvert-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "mediaconvert-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "mediaconvert-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "mediaconvert-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "mediaconvert-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "mediaconvert-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mediaconvert-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "mediaconvert-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mediaconvert-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "mediaconvert-fips.us-west-2.amazonaws.com",
},
},
},
"medialive": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "medialive-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "medialive-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "medialive-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "medialive-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "medialive-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "medialive-fips.us-west-2.amazonaws.com",
},
},
},
"mediapackage": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mediapackage-vod": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mediastore": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"meetings-chime": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "meetings-chime-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "meetings-chime-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "meetings-chime-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "meetings-chime-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"messaging-chime": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "messaging-chime-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "messaging-chime-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"metering.marketplace": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "aws-marketplace",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mgh": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mgn": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"migrationhub-strategy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"mobileanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"models-v2-lex": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"models.lex": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "lex",
},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "models-fips.lex.{region}.{dnsSuffix}",
CredentialScope: credentialScope{
Service: "lex",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "models-fips.lex.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "models-fips.lex.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "models-fips.lex.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "models-fips.lex.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"monitoring": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "monitoring-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "monitoring-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "monitoring-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "monitoring-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring-fips.us-west-2.amazonaws.com",
},
},
},
"mq": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "mq-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "mq-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "mq-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "mq-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-west-2.amazonaws.com",
},
},
},
"mturk-requester": service{
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "sandbox",
}: endpoint{
Hostname: "mturk-requester-sandbox.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"neptune": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{
Hostname: "rds.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "rds.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "rds.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "rds.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "rds.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "rds.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "rds.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "rds.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "rds.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "rds.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "rds.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "rds.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "me-south-1",
}: endpoint{
Hostname: "rds.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "rds.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "rds.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "rds.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "rds.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "rds.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"network-firewall": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "network-firewall-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "network-firewall-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "network-firewall-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "network-firewall-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-west-2.amazonaws.com",
},
},
},
"networkmanager": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "networkmanager.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"nimble": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"oidc": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "oidc.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "oidc.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "oidc.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "oidc.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "oidc.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "oidc.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "oidc.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "oidc.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "oidc.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "oidc.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "oidc.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "oidc.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "oidc.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "oidc.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "oidc.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"opsworks": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"opsworks-cm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"organizations": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "organizations.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "organizations-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "fips-aws-global",
}: endpoint{
Hostname: "organizations-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"outposts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "outposts-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "outposts-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "outposts-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "outposts-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "outposts-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "outposts-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "outposts-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "outposts-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "outposts-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "outposts-fips.us-west-2.amazonaws.com",
},
},
},
"personalize": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"pi": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"pinpoint": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "mobiletargeting",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "pinpoint-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "pinpoint-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "pinpoint.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "pinpoint-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "pinpoint.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "pinpoint-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"polly": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "polly-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "polly-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "polly-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "polly-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "polly-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "polly-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "polly-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "polly-fips.us-west-2.amazonaws.com",
},
},
},
"portal.sso": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "portal.sso.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "portal.sso.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "portal.sso.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "portal.sso.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "portal.sso.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "portal.sso.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "portal.sso.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "portal.sso.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "portal.sso.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "portal.sso.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "portal.sso.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "portal.sso.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "portal.sso.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "portal.sso.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "portal.sso.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"profile": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"projects.iot1click": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"qldb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "qldb-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "qldb-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "qldb-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "qldb-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "qldb-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "qldb-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "qldb-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "qldb-fips.us-west-2.amazonaws.com",
},
},
},
"quicksight": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "api",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"ram": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ram-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "ram-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ram-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ram-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ram-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ram-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ram-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ram-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ram-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ram-fips.us-west-2.amazonaws.com",
},
},
},
"rbin": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"rds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "rds-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "rds-fips.ca-central-1",
}: endpoint{
Hostname: "rds-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds-fips.us-east-1",
}: endpoint{
Hostname: "rds-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds-fips.us-east-2",
}: endpoint{
Hostname: "rds-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds-fips.us-west-1",
}: endpoint{
Hostname: "rds-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds-fips.us-west-2",
}: endpoint{
Hostname: "rds-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.ca-central-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-west-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{
SSLCommonName: "{service}.{dnsSuffix}",
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-east-1.amazonaws.com",
SSLCommonName: "{service}.{dnsSuffix}",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "rds-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "rds-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "rds-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "rds-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"redshift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "redshift-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "redshift-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "redshift-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "redshift-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "redshift-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "redshift-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "redshift-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "redshift-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "redshift-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "redshift-fips.us-west-2.amazonaws.com",
},
},
},
"rekognition": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "rekognition-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "rekognition-fips.ca-central-1",
}: endpoint{
Hostname: "rekognition-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition-fips.us-east-1",
}: endpoint{
Hostname: "rekognition-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition-fips.us-east-2",
}: endpoint{
Hostname: "rekognition-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition-fips.us-west-1",
}: endpoint{
Hostname: "rekognition-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition-fips.us-west-2",
}: endpoint{
Hostname: "rekognition-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.ca-central-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-west-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "rekognition-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "rekognition-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "rekognition-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "rekognition-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"resource-groups": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "resource-groups-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "resource-groups-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "resource-groups-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "resource-groups-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups-fips.us-west-2.amazonaws.com",
},
},
},
"robomaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"route53": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "route53.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "route53-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "fips-aws-global",
}: endpoint{
Hostname: "route53-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"route53-recovery-control-config": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "route53-recovery-control-config.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"route53domains": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-east-1",
}: endpoint{},
},
},
"route53resolver": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"rum": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"runtime-v2-lex": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"runtime.lex": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "lex",
},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.lex.{region}.{dnsSuffix}",
CredentialScope: credentialScope{
Service: "lex",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.lex.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "runtime-fips.lex.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.lex.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "runtime-fips.lex.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"runtime.sagemaker": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.sagemaker.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "runtime-fips.sagemaker.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"s3": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "af-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.af-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-east-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "s3.ap-northeast-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-northeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-northeast-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-northeast-3.amazonaws.com",
},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "s3.ap-southeast-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-southeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-southeast-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "s3.ap-southeast-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-southeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-southeast-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ap-southeast-3.amazonaws.com",
},
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "s3.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-fips.dualstack.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-north-1.amazonaws.com",
},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-south-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "s3.eu-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "eu-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-west-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.eu-west-3.amazonaws.com",
},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "s3-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "s3-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "s3-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "s3-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "s3-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "me-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.me-south-1.amazonaws.com",
},
endpointKey{
Region: "s3-external-1",
}: endpoint{
Hostname: "s3-external-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "s3.sa-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "sa-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.sa-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "s3.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-fips.dualstack.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-fips.dualstack.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "s3.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-fips.dualstack.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "s3.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-fips.dualstack.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
},
},
"s3-control": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "s3-control.ap-northeast-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-northeast-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "s3-control.ap-northeast-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-northeast-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{
Hostname: "s3-control.ap-northeast-3.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
},
endpointKey{
Region: "ap-northeast-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-northeast-3.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "s3-control.ap-south-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-south-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-south-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "s3-control.ap-southeast-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-southeast-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "s3-control.ap-southeast-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ap-southeast-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ap-southeast-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "s3-control.ca-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.ca-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.ca-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.ca-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "s3-control-fips.ca-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "s3-control.eu-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-central-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.eu-central-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "s3-control.eu-north-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.eu-north-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "s3-control.eu-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.eu-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "s3-control.eu-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.eu-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "s3-control.eu-west-3.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "eu-west-3",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.eu-west-3.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "s3-control.sa-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "sa-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.sa-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "s3-control.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "s3-control-fips.us-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "s3-control.us-east-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-east-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-east-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-east-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "s3-control-fips.us-east-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "s3-control.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "s3-control-fips.us-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "s3-control.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "s3-control-fips.us-west-2.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"s3-outposts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{},
},
},
"savingsplans": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "savingsplans.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"schemas": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"sdb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
SignatureVersions: []string{"v2"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "sdb.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"secretsmanager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "secretsmanager-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"securityhub": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "securityhub-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "securityhub-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "securityhub-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "securityhub-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-west-2.amazonaws.com",
},
},
},
"serverlessrepo": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "me-south-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Protocols: []string{"https"},
},
},
},
"servicecatalog": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"servicecatalog-appregistry": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry-fips.us-west-2.amazonaws.com",
},
},
},
"servicediscovery": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "servicediscovery-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "servicediscovery",
}: endpoint{
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "servicediscovery",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "servicediscovery-fips",
}: endpoint{
Hostname: "servicediscovery-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"servicequotas": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"session.qldb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "session.qldb-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "session.qldb-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "session.qldb-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "session.qldb-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "session.qldb-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "session.qldb-fips.us-west-2.amazonaws.com",
},
},
},
"shield": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SSLCommonName: "shield.us-east-1.amazonaws.com",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "shield.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "shield-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "fips-aws-global",
}: endpoint{
Hostname: "shield-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"sms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "sms-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "sms-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "sms-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "sms-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-west-2.amazonaws.com",
},
},
},
"sms-voice": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"snowball": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-northeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-northeast-2.amazonaws.com",
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-northeast-3.amazonaws.com",
},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-south-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-southeast-1.amazonaws.com",
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ap-southeast-2.amazonaws.com",
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.eu-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.eu-west-1.amazonaws.com",
},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.eu-west-2.amazonaws.com",
},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.eu-west-3.amazonaws.com",
},
endpointKey{
Region: "fips-ap-northeast-1",
}: endpoint{
Hostname: "snowball-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-2",
}: endpoint{
Hostname: "snowball-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-3",
}: endpoint{
Hostname: "snowball-fips.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-south-1",
}: endpoint{
Hostname: "snowball-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-1",
}: endpoint{
Hostname: "snowball-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-2",
}: endpoint{
Hostname: "snowball-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "snowball-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-central-1",
}: endpoint{
Hostname: "snowball-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-1",
}: endpoint{
Hostname: "snowball-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-2",
}: endpoint{
Hostname: "snowball-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-3",
}: endpoint{
Hostname: "snowball-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-sa-east-1",
}: endpoint{
Hostname: "snowball-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "snowball-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "snowball-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "snowball-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "snowball-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.sa-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-west-2.amazonaws.com",
},
},
},
"sns": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "sns-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "sns-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "sns-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "sns-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns-fips.us-west-2.amazonaws.com",
},
},
},
"sqs": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SSLCommonName: "{region}.queue.{dnsSuffix}",
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "sqs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "sqs-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "sqs-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "sqs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{
SSLCommonName: "queue.{dnsSuffix}",
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sqs-fips.us-east-1.amazonaws.com",
SSLCommonName: "queue.{dnsSuffix}",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sqs-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sqs-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sqs-fips.us-west-2.amazonaws.com",
},
},
},
"ssm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "ssm-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "ssm-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "ssm-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "ssm-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "ssm-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm-fips.us-west-2.amazonaws.com",
},
},
},
"ssm-incidents": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"states": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "states-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "states-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "states-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "states-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "states-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "states-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "states-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "states-fips.us-west-2.amazonaws.com",
},
},
},
"storagegateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-central-1-fips",
}: endpoint{
Hostname: "storagegateway-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "storagegateway-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"streams.dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "local",
}: endpoint{
Hostname: "localhost:8000",
Protocols: []string{"http"},
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"sts": service{
PartitionEndpoint: "aws-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "sts.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "sts-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "sts-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-1-fips",
}: endpoint{
Hostname: "sts-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "sts-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"support": service{
PartitionEndpoint: "aws-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "support.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"swf": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "swf-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "swf-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "swf-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "swf-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "swf-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "swf-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "swf-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "swf-fips.us-west-2.amazonaws.com",
},
},
},
"synthetics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"tagging": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"textract": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "textract-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "textract-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "textract-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "textract-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "textract-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-west-2.amazonaws.com",
},
},
},
"transcribe": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.{region}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "fips.transcribe.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "fips.transcribe.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "fips.transcribe.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "fips.transcribe.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "fips.transcribe.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-west-2.amazonaws.com",
},
},
},
"transcribestreaming": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "transcribestreaming-ca-central-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transcribestreaming-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-fips-ca-central-1",
}: endpoint{
Hostname: "transcribestreaming-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-fips-us-east-1",
}: endpoint{
Hostname: "transcribestreaming-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-fips-us-east-2",
}: endpoint{
Hostname: "transcribestreaming-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-fips-us-west-2",
}: endpoint{
Hostname: "transcribestreaming-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transcribestreaming-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-east-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "transcribestreaming-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-west-2",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "transcribestreaming-us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "transcribestreaming-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"transfer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "transfer-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "transfer-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "transfer-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "transfer-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "transfer-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-west-2.amazonaws.com",
},
},
},
"translate": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "translate-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-1-fips",
}: endpoint{
Hostname: "translate-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "translate-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-east-2-fips",
}: endpoint{
Hostname: "translate-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "translate-fips.us-west-2.amazonaws.com",
},
endpointKey{
Region: "us-west-2-fips",
}: endpoint{
Hostname: "translate-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
},
},
"voiceid": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"waf": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "aws",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "aws-fips",
}: endpoint{
Hostname: "waf-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "waf.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "aws-global-fips",
}: endpoint{
Hostname: "waf-fips.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
},
},
"waf-regional": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{
Hostname: "waf-regional.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
},
endpointKey{
Region: "af-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
},
endpointKey{
Region: "ap-east-1",
}: endpoint{
Hostname: "waf-regional.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
endpointKey{
Region: "ap-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{
Hostname: "waf-regional.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{
Hostname: "waf-regional.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{
Hostname: "waf-regional.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
},
endpointKey{
Region: "ap-northeast-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
},
endpointKey{
Region: "ap-south-1",
}: endpoint{
Hostname: "waf-regional.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{
Hostname: "waf-regional.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{
Hostname: "waf-regional.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ap-southeast-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
},
endpointKey{
Region: "ca-central-1",
}: endpoint{
Hostname: "waf-regional.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
Hostname: "waf-regional.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-central-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
},
endpointKey{
Region: "eu-north-1",
}: endpoint{
Hostname: "waf-regional.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
},
endpointKey{
Region: "eu-south-1",
}: endpoint{
Hostname: "waf-regional.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
},
endpointKey{
Region: "eu-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
},
endpointKey{
Region: "eu-west-1",
}: endpoint{
Hostname: "waf-regional.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
},
endpointKey{
Region: "eu-west-2",
}: endpoint{
Hostname: "waf-regional.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
},
endpointKey{
Region: "eu-west-3",
}: endpoint{
Hostname: "waf-regional.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "eu-west-3",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
},
endpointKey{
Region: "fips-af-south-1",
}: endpoint{
Hostname: "waf-regional-fips.af-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "af-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-east-1",
}: endpoint{
Hostname: "waf-regional-fips.ap-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-1",
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-2",
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-northeast-3",
}: endpoint{
Hostname: "waf-regional-fips.ap-northeast-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-northeast-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-south-1",
}: endpoint{
Hostname: "waf-regional-fips.ap-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-1",
}: endpoint{
Hostname: "waf-regional-fips.ap-southeast-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ap-southeast-2",
}: endpoint{
Hostname: "waf-regional-fips.ap-southeast-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "ap-southeast-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-ca-central-1",
}: endpoint{
Hostname: "waf-regional-fips.ca-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-central-1",
}: endpoint{
Hostname: "waf-regional-fips.eu-central-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-central-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-north-1",
}: endpoint{
Hostname: "waf-regional-fips.eu-north-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-south-1",
}: endpoint{
Hostname: "waf-regional-fips.eu-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-1",
}: endpoint{
Hostname: "waf-regional-fips.eu-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-2",
}: endpoint{
Hostname: "waf-regional-fips.eu-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-eu-west-3",
}: endpoint{
Hostname: "waf-regional-fips.eu-west-3.amazonaws.com",
CredentialScope: credentialScope{
Region: "eu-west-3",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-me-south-1",
}: endpoint{
Hostname: "waf-regional-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-sa-east-1",
}: endpoint{
Hostname: "waf-regional-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "waf-regional-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "waf-regional-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "waf-regional-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "waf-regional-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{
Hostname: "waf-regional.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
endpointKey{
Region: "me-south-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.me-south-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "me-south-1",
},
},
endpointKey{
Region: "sa-east-1",
}: endpoint{
Hostname: "waf-regional.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "sa-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.sa-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "sa-east-1",
},
},
endpointKey{
Region: "us-east-1",
}: endpoint{
Hostname: "waf-regional.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
endpointKey{
Region: "us-east-2",
}: endpoint{
Hostname: "waf-regional.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
},
endpointKey{
Region: "us-west-1",
}: endpoint{
Hostname: "waf-regional.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
},
endpointKey{
Region: "us-west-2",
}: endpoint{
Hostname: "waf-regional.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
},
},
},
"wisdom": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"workdocs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "workdocs-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "workdocs-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "workdocs-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "workdocs-fips.us-west-2.amazonaws.com",
},
},
},
"workmail": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"workspaces": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "workspaces-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "workspaces-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "workspaces-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "workspaces-fips.us-west-2.amazonaws.com",
},
},
},
"workspaces-web": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-west-2",
}: endpoint{},
},
},
"xray": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "af-south-1",
}: endpoint{},
endpointKey{
Region: "ap-east-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-1",
}: endpoint{},
endpointKey{
Region: "ap-northeast-2",
}: endpoint{},
endpointKey{
Region: "ap-northeast-3",
}: endpoint{},
endpointKey{
Region: "ap-south-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-1",
}: endpoint{},
endpointKey{
Region: "ap-southeast-2",
}: endpoint{},
endpointKey{
Region: "ap-southeast-3",
}: endpoint{},
endpointKey{
Region: "ca-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
endpointKey{
Region: "eu-south-1",
}: endpoint{},
endpointKey{
Region: "eu-west-1",
}: endpoint{},
endpointKey{
Region: "eu-west-2",
}: endpoint{},
endpointKey{
Region: "eu-west-3",
}: endpoint{},
endpointKey{
Region: "fips-us-east-1",
}: endpoint{
Hostname: "xray-fips.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-east-2",
}: endpoint{
Hostname: "xray-fips.us-east-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-1",
}: endpoint{
Hostname: "xray-fips.us-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-west-2",
}: endpoint{
Hostname: "xray-fips.us-west-2.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-west-2",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "me-south-1",
}: endpoint{},
endpointKey{
Region: "sa-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
}: endpoint{},
endpointKey{
Region: "us-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-east-1.amazonaws.com",
},
endpointKey{
Region: "us-east-2",
}: endpoint{},
endpointKey{
Region: "us-east-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-east-2.amazonaws.com",
},
endpointKey{
Region: "us-west-1",
}: endpoint{},
endpointKey{
Region: "us-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-west-1.amazonaws.com",
},
endpointKey{
Region: "us-west-2",
}: endpoint{},
endpointKey{
Region: "us-west-2",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-west-2.amazonaws.com",
},
},
},
},
}
// AwsCnPartition returns the Resolver for AWS China.
func AwsCnPartition() Partition {
return awscnPartition.Partition()
}
var awscnPartition = partition{
ID: "aws-cn",
Name: "AWS China",
DNSSuffix: "amazonaws.com.cn",
RegionRegex: regionRegex{
Regexp: func() *regexp.Regexp {
reg, _ := regexp.Compile("^cn\\-\\w+\\-\\d+$")
return reg
}(),
},
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
DNSSuffix: "api.amazonwebservices.com.cn",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com.cn",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "api.amazonwebservices.com.cn",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
Regions: regions{
"cn-north-1": region{
Description: "China (Beijing)",
},
"cn-northwest-1": region{
Description: "China (Ningxia)",
},
},
Services: services{
"access-analyzer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"account": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "account.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"acm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"api.ecr": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "api.ecr.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "api.ecr.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"api.sagemaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"api.tunneling.iot": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"apigateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"appconfigdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"application-autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"applicationinsights": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"appmesh": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"appsync": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"athena": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"autoscaling-plans": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"backup": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"batch": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"budgets": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "budgets.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"ce": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "ce.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"cloudcontrolapi": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"cloudformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"cloudfront": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "cloudfront.cn-northwest-1.amazonaws.com.cn",
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"cloudtrail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"codebuild": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"codecommit": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"codedeploy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"codepipeline": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"cognito-identity": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"compute-optimizer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "compute-optimizer.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "compute-optimizer.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"config": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"cur": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"data-ats.iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
CredentialScope: credentialScope{
Service: "iotdata",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"data.jobs.iot": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"databrew": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"dax": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"dms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"docdb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "rds.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"ds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"ebs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"ec2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"ecs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"eks": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"elasticache": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"elasticbeanstalk": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"elasticfilesystem": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.cn-north-1.amazonaws.com.cn",
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.cn-northwest-1.amazonaws.com.cn",
},
endpointKey{
Region: "fips-cn-north-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-cn-northwest-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
Deprecated: boxedTrue,
},
},
},
"elasticloadbalancing": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"elasticmapreduce": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"emr-containers": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"es": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"events": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"firehose": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"fms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"fsx": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"gamelift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"glacier": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"glue": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"greengrass": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"guardduty": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"health": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"iam": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "iam.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
},
},
"iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "execute-api",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"iotanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"iotevents": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"ioteventsdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "data.iotevents.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
},
},
"iotsecuredtunneling": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"iotsitewise": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"kafka": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"kinesis": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"kinesisanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"kms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"lakeformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"lambda": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.cn-north-1.api.amazonwebservices.com.cn",
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "lambda.cn-northwest-1.api.amazonwebservices.com.cn",
},
},
},
"license-manager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"logs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"mediaconvert": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "subscribe.mediaconvert.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"monitoring": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"mq": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"neptune": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "rds.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "rds.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"organizations": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "organizations.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"personalize": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
},
},
"pi": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"polly": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"ram": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"rds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"redshift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"resource-groups": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"route53": service{
PartitionEndpoint: "aws-cn-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "route53.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"route53resolver": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"runtime.sagemaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"s3": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com.cn",
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.cn-north-1.amazonaws.com.cn",
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.cn-northwest-1.amazonaws.com.cn",
},
},
},
"s3-control": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com.cn",
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "s3-control.cn-north-1.amazonaws.com.cn",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-north-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.cn-north-1.amazonaws.com.cn",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "s3-control.cn-northwest-1.amazonaws.com.cn",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
endpointKey{
Region: "cn-northwest-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.cn-northwest-1.amazonaws.com.cn",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"secretsmanager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"securityhub": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"serverlessrepo": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Protocols: []string{"https"},
},
},
},
"servicecatalog": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"servicediscovery": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"sms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"snowball": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.cn-north-1.amazonaws.com.cn",
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.cn-northwest-1.amazonaws.com.cn",
},
endpointKey{
Region: "fips-cn-north-1",
}: endpoint{
Hostname: "snowball-fips.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-cn-northwest-1",
}: endpoint{
Hostname: "snowball-fips.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
Deprecated: boxedTrue,
},
},
},
"sns": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"sqs": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SSLCommonName: "{region}.queue.{dnsSuffix}",
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"ssm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"states": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"storagegateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"streams.dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"sts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"support": service{
PartitionEndpoint: "aws-cn-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-cn-global",
}: endpoint{
Hostname: "support.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
},
},
"swf": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"synthetics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"tagging": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"transcribe": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "cn.transcribe.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "cn.transcribe.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
},
},
"transcribestreaming": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"transfer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"waf-regional": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{
Hostname: "waf-regional.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-north-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{
Hostname: "waf-regional.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
endpointKey{
Region: "cn-northwest-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
},
endpointKey{
Region: "fips-cn-north-1",
}: endpoint{
Hostname: "waf-regional-fips.cn-north-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-north-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-cn-northwest-1",
}: endpoint{
Hostname: "waf-regional-fips.cn-northwest-1.amazonaws.com.cn",
CredentialScope: credentialScope{
Region: "cn-northwest-1",
},
Deprecated: boxedTrue,
},
},
},
"workspaces": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
"xray": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "cn-north-1",
}: endpoint{},
endpointKey{
Region: "cn-northwest-1",
}: endpoint{},
},
},
},
}
// AwsUsGovPartition returns the Resolver for AWS GovCloud (US).
func AwsUsGovPartition() Partition {
return awsusgovPartition.Partition()
}
var awsusgovPartition = partition{
ID: "aws-us-gov",
Name: "AWS GovCloud (US)",
DNSSuffix: "amazonaws.com",
RegionRegex: regionRegex{
Regexp: func() *regexp.Regexp {
reg, _ := regexp.Compile("^us\\-gov\\-\\w+\\-\\d+$")
return reg
}(),
},
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
DNSSuffix: "api.aws",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "api.aws",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
Regions: regions{
"us-gov-east-1": region{
Description: "AWS GovCloud (US-East)",
},
"us-gov-west-1": region{
Description: "AWS GovCloud (US-West)",
},
},
Services: services{
"access-analyzer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "access-analyzer.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "access-analyzer.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"acm": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "acm.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "acm.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "acm.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"acm-pca": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca.{region}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "acm-pca.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "acm-pca.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "acm-pca.us-gov-west-1.amazonaws.com",
},
},
},
"api.detective": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "api.detective-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.detective-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "api.detective-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"api.ecr": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "dkr-us-gov-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-gov-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dkr-us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-dkr-us-gov-east-1",
}: endpoint{
Hostname: "ecr-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-dkr-us-gov-west-1",
}: endpoint{
Hostname: "ecr-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "ecr-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "ecr-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "api.ecr.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "api.ecr.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecr-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"api.sagemaker": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api-fips.sagemaker.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "api-fips.sagemaker.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1-fips-secondary",
}: endpoint{
Hostname: "api.sagemaker.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1-secondary",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1-secondary",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.sagemaker.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"api.tunneling.iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-west-1.amazonaws.com",
},
},
},
"apigateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"appconfigdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"application-autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "autoscaling.{region}.amazonaws.com",
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Service: "application-autoscaling",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
},
},
"applicationinsights": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "applicationinsights.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "applicationinsights.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"appstream2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
CredentialScope: credentialScope{
Service: "appstream",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "appstream2-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "appstream2-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "appstream2-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"athena": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "athena-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "athena-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "athena-fips.us-gov-west-1.amazonaws.com",
},
},
},
"autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "autoscaling.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
},
},
"autoscaling-plans": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
},
},
"backup": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"batch": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "batch.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "batch.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "batch.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "batch.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "batch.us-gov-west-1.amazonaws.com",
},
},
},
"cloudcontrolapi": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudcontrolapi-fips.us-gov-west-1.amazonaws.com",
},
},
},
"clouddirectory": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"cloudformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "cloudformation.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "cloudformation.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"cloudhsm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"cloudhsmv2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "cloudhsm",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"cloudtrail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "cloudtrail.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "cloudtrail.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cloudtrail.us-gov-west-1.amazonaws.com",
},
},
},
"codebuild": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "codebuild-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codebuild-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "codebuild-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"codecommit": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "codecommit-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "codecommit-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codecommit-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "codecommit-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"codedeploy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codedeploy-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "codedeploy-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"codepipeline": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "codepipeline-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "codepipeline-fips.us-gov-west-1.amazonaws.com",
},
},
},
"cognito-identity": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "cognito-identity-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-identity-fips.us-gov-west-1.amazonaws.com",
},
},
},
"cognito-idp": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "cognito-idp-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "cognito-idp-fips.us-gov-west-1.amazonaws.com",
},
},
},
"comprehend": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "comprehend-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehend-fips.us-gov-west-1.amazonaws.com",
},
},
},
"comprehendmedical": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "comprehendmedical-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "comprehendmedical-fips.us-gov-west-1.amazonaws.com",
},
},
},
"config": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "config.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "config.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "config.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "config.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "config.us-gov-west-1.amazonaws.com",
},
},
},
"connect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"data-ats.iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
CredentialScope: credentialScope{
Service: "iotdata",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "data.iot-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "data.iot-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "iotdata",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.iot-fips.us-gov-west-1.amazonaws.com",
},
},
},
"data.jobs.iot": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "data.jobs.iot-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "data.jobs.iot-fips.us-gov-west-1.amazonaws.com",
},
},
},
"databrew": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"datasync": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "datasync-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "datasync-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "datasync-fips.us-gov-west-1.amazonaws.com",
},
},
},
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "directconnect.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "directconnect.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"dms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "dms",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms-fips",
}: endpoint{
Hostname: "dms.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "dms.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "dms.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"docdb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "rds.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"ds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "ds-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "ds-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ds-fips.us-gov-west-1.amazonaws.com",
},
},
},
"dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "dynamodb.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dynamodb.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "dynamodb.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"ebs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"ec2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "ec2.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "ec2.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "ec2.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"ecs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "ecs-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "ecs-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ecs-fips.us-gov-west-1.amazonaws.com",
},
},
},
"eks": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "eks.{region}.{dnsSuffix}",
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "eks.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "eks.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "eks.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "eks.us-gov-west-1.amazonaws.com",
},
},
},
"elasticache": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "elasticache.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticache.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "elasticache.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"elasticbeanstalk": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "elasticbeanstalk.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "elasticbeanstalk.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"elasticfilesystem": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-gov-west-1.amazonaws.com",
},
},
},
"elasticloadbalancing": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "elasticloadbalancing.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "elasticloadbalancing.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticloadbalancing.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
},
},
"elasticmapreduce": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "elasticmapreduce.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "elasticmapreduce.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticmapreduce.us-gov-west-1.amazonaws.com",
Protocols: []string{"https"},
},
},
},
"email": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "email-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "email-fips.us-gov-west-1.amazonaws.com",
},
},
},
"es": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "es-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "es-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "es-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "es-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"events": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "events.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "events.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "events.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "events.us-gov-west-1.amazonaws.com",
},
},
},
"firehose": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "firehose-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "firehose-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "firehose-fips.us-gov-west-1.amazonaws.com",
},
},
},
"fms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "fms-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "fms-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fms-fips.us-gov-west-1.amazonaws.com",
},
},
},
"fsx": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-prod-us-gov-east-1",
}: endpoint{
Hostname: "fsx-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-prod-us-gov-west-1",
}: endpoint{
Hostname: "fsx-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "fsx-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "fsx-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-gov-east-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-gov-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "prod-us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fsx-fips.us-gov-west-1.amazonaws.com",
},
},
},
"glacier": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "glacier.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "glacier.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"glue": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "glue-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "glue-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "glue-fips.us-gov-west-1.amazonaws.com",
},
},
},
"greengrass": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "dataplane-us-gov-east-1",
}: endpoint{
Hostname: "greengrass-ats.iot.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "dataplane-us-gov-west-1",
}: endpoint{
Hostname: "greengrass-ats.iot.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "greengrass-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "greengrass.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "greengrass-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "greengrass.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"guardduty": service{
IsRegionalized: boxedTrue,
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty.{region}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "guardduty.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "guardduty.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "guardduty.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"health": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "health-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "health-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"iam": service{
PartitionEndpoint: "aws-us-gov-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-us-gov-global",
}: endpoint{
Hostname: "iam.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "aws-us-gov-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "iam.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "aws-us-gov-global-fips",
}: endpoint{
Hostname: "iam.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam-govcloud",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam-govcloud",
Variant: fipsVariant,
}: endpoint{
Hostname: "iam.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "iam-govcloud-fips",
}: endpoint{
Hostname: "iam.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"identitystore": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "identitystore.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "identitystore.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "identitystore.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "identitystore.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "identitystore.us-gov-west-1.amazonaws.com",
},
},
},
"inspector": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "inspector-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "inspector-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "inspector-fips.us-gov-west-1.amazonaws.com",
},
},
},
"iot": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "execute-api",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "iot-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "iot-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Service: "execute-api",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iot-fips.us-gov-west-1.amazonaws.com",
},
},
},
"iotevents": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"ioteventsdata": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "data.iotevents.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"iotsecuredtunneling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "api.tunneling.iot-fips.us-gov-west-1.amazonaws.com",
},
},
},
"iotsitewise": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "iotsitewise-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "iotsitewise-fips.us-gov-west-1.amazonaws.com",
},
},
},
"kafka": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"kendra": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "kendra-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kendra-fips.us-gov-west-1.amazonaws.com",
},
},
},
"kinesis": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "kinesis.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "kinesis.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"kinesisanalytics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"kms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ProdFips",
}: endpoint{
Hostname: "kms-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "kms-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "kms-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"lakeformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "lakeformation-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lakeformation-fips.us-gov-west-1.amazonaws.com",
},
},
},
"lambda": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "lambda-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "lambda-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "lambda-fips.us-gov-west-1.amazonaws.com",
},
},
},
"license-manager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "license-manager-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "license-manager-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "license-manager-fips.us-gov-west-1.amazonaws.com",
},
},
},
"logs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "logs.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "logs.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "logs.us-gov-west-1.amazonaws.com",
},
},
},
"mediaconvert": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "mediaconvert.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"meetings-chime": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "meetings-chime-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "meetings-chime-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "meetings-chime-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "meetings-chime-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"metering.marketplace": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "aws-marketplace",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"models.lex": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "lex",
},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "models-fips.lex.{region}.{dnsSuffix}",
CredentialScope: credentialScope{
Service: "lex",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "models-fips.lex.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "models-fips.lex.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"monitoring": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "monitoring.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "monitoring.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "monitoring.us-gov-west-1.amazonaws.com",
},
},
},
"mq": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "mq-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "mq-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "mq-fips.us-gov-west-1.amazonaws.com",
},
},
},
"neptune": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "rds.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "rds.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"network-firewall": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "network-firewall-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "network-firewall-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "network-firewall-fips.us-gov-west-1.amazonaws.com",
},
},
},
"networkmanager": service{
PartitionEndpoint: "aws-us-gov-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-us-gov-global",
}: endpoint{
Hostname: "networkmanager.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"oidc": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "oidc.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "oidc.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"organizations": service{
PartitionEndpoint: "aws-us-gov-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-us-gov-global",
}: endpoint{
Hostname: "organizations.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "aws-us-gov-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "organizations.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "fips-aws-us-gov-global",
}: endpoint{
Hostname: "organizations.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"outposts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "outposts.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "outposts.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"pinpoint": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "mobiletargeting",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "pinpoint-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "pinpoint.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "pinpoint-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"polly": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "polly-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "polly-fips.us-gov-west-1.amazonaws.com",
},
},
},
"portal.sso": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "portal.sso.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "portal.sso.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"quicksight": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "api",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"ram": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "ram.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "ram.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"rds": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "rds.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "rds.us-gov-east-1",
}: endpoint{
Hostname: "rds.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rds.us-gov-west-1",
}: endpoint{
Hostname: "rds.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "rds.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rds.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "rds.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"redshift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "redshift.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "redshift.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"rekognition": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "rekognition-fips.us-gov-west-1",
}: endpoint{
Hostname: "rekognition-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-gov-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "rekognition.us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "rekognition-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "rekognition-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"resource-groups": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "resource-groups.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "resource-groups.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "resource-groups.us-gov-west-1.amazonaws.com",
},
},
},
"route53": service{
PartitionEndpoint: "aws-us-gov-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-us-gov-global",
}: endpoint{
Hostname: "route53.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "aws-us-gov-global",
Variant: fipsVariant,
}: endpoint{
Hostname: "route53.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "fips-aws-us-gov-global",
}: endpoint{
Hostname: "route53.us-gov.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"route53resolver": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"runtime.lex": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "lex",
},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.lex.{region}.{dnsSuffix}",
CredentialScope: credentialScope{
Service: "lex",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime-fips.lex.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "runtime-fips.lex.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"runtime.sagemaker": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime.sagemaker.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "runtime.sagemaker.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "runtime.sagemaker.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"s3": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SignatureVersions: []string{"s3", "s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
SignatureVersions: []string{"s3", "s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "s3-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "s3-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "s3.us-gov-east-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-gov-east-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-gov-east-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "s3.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3.dualstack.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-fips.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
},
},
"s3-control": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: dualStackVariant,
}: endpoint{
Hostname: "{service}.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
defaultKey{
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "{service}-fips.dualstack.{region}.{dnsSuffix}",
DNSSuffix: "amazonaws.com",
Protocols: []string{"https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "s3-control.us-gov-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-gov-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-gov-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-gov-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "s3-control-fips.us-gov-east-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "s3-control.us-gov-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: dualStackVariant,
}: endpoint{
Hostname: "s3-control.dualstack.us-gov-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "s3-control-fips.us-gov-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant | dualStackVariant,
}: endpoint{
Hostname: "s3-control-fips.dualstack.us-gov-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "s3-control-fips.us-gov-west-1.amazonaws.com",
SignatureVersions: []string{"s3v4"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"s3-outposts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{},
},
},
"secretsmanager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "secretsmanager-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "secretsmanager-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"securityhub": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "securityhub-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "securityhub-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "securityhub-fips.us-gov-west-1.amazonaws.com",
},
},
},
"serverlessrepo": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "serverlessrepo.us-gov-east-1.amazonaws.com",
Protocols: []string{"https"},
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "serverlessrepo.us-gov-west-1.amazonaws.com",
Protocols: []string{"https"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"servicecatalog": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "servicecatalog-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"servicecatalog-appregistry": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "servicecatalog-appregistry.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "servicecatalog-appregistry.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicecatalog-appregistry.us-gov-west-1.amazonaws.com",
},
},
},
"servicediscovery": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "servicediscovery",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "servicediscovery",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "servicediscovery-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "servicediscovery-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"servicequotas": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "servicequotas.{region}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "servicequotas.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "servicequotas.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicequotas.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "servicequotas.us-gov-west-1.amazonaws.com",
},
},
},
"sms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "sms-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "sms-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sms-fips.us-gov-west-1.amazonaws.com",
},
},
},
"sms-voice": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"snowball": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "snowball-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "snowball-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "snowball-fips.us-gov-west-1.amazonaws.com",
},
},
},
"sns": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "sns.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "sns.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sns.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
},
},
"sqs": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "sqs.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "sqs.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "sqs.us-gov-west-1.amazonaws.com",
SSLCommonName: "{region}.queue.{dnsSuffix}",
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"ssm": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "ssm.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "ssm.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "ssm.us-gov-west-1.amazonaws.com",
},
},
},
"states": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "states-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "states.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "states-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "states.us-gov-west-1.amazonaws.com",
},
},
},
"storagegateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips",
}: endpoint{
Hostname: "storagegateway-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "storagegateway-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "storagegateway-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"streams.dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "streams.dynamodb.{region}.{dnsSuffix}",
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "streams.dynamodb.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "streams.dynamodb.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "streams.dynamodb.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "streams.dynamodb.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"sts": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "sts.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-east-1-fips",
}: endpoint{
Hostname: "sts.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "sts.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "sts.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"support": service{
PartitionEndpoint: "aws-us-gov-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-us-gov-global",
}: endpoint{
Hostname: "support.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "support.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "support.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"swf": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "swf.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "swf.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"synthetics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"tagging": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
},
},
"textract": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "textract-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "textract-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "textract-fips.us-gov-west-1.amazonaws.com",
},
},
},
"transcribe": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.{region}.{dnsSuffix}",
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "fips.transcribe.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "fips.transcribe.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "fips.transcribe.us-gov-west-1.amazonaws.com",
},
},
},
"transfer": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "transfer-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "transfer-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "transfer-fips.us-gov-west-1.amazonaws.com",
},
},
},
"translate": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "translate-fips.us-gov-west-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1-fips",
}: endpoint{
Hostname: "translate-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
},
},
"waf-regional": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "waf-regional-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "waf-regional-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "waf-regional.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "waf-regional.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "waf-regional-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
},
},
},
"workspaces": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "workspaces-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "workspaces-fips.us-gov-west-1.amazonaws.com",
},
},
},
"xray": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "xray-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "xray-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "xray-fips.us-gov-west-1.amazonaws.com",
},
},
},
},
}
// AwsIsoPartition returns the Resolver for AWS ISO (US).
func AwsIsoPartition() Partition {
return awsisoPartition.Partition()
}
var awsisoPartition = partition{
ID: "aws-iso",
Name: "AWS ISO (US)",
DNSSuffix: "c2s.ic.gov",
RegionRegex: regionRegex{
Regexp: func() *regexp.Regexp {
reg, _ := regexp.Compile("^us\\-iso\\-\\w+\\-\\d+$")
return reg
}(),
},
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "c2s.ic.gov",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
Regions: regions{
"us-iso-east-1": region{
Description: "US ISO East",
},
"us-iso-west-1": region{
Description: "US ISO WEST",
},
},
Services: services{
"api.ecr": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Hostname: "api.ecr.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{
Hostname: "api.ecr.us-iso-west-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-west-1",
},
},
},
},
"api.sagemaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"apigateway": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"application-autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"autoscaling": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"cloudformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"cloudtrail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"codedeploy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"comprehend": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"config": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"datapipeline": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"dms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "dms",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms-fips",
}: endpoint{
Hostname: "dms.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-iso-east-1.c2s.ic.gov",
},
endpointKey{
Region: "us-iso-east-1-fips",
}: endpoint{
Hostname: "dms.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-iso-west-1.c2s.ic.gov",
},
endpointKey{
Region: "us-iso-west-1-fips",
}: endpoint{
Hostname: "dms.us-iso-west-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-west-1",
},
Deprecated: boxedTrue,
},
},
},
"ds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"dynamodb": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"ebs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"ec2": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"ecs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"eks": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"elasticache": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"elasticfilesystem": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "fips-us-iso-east-1",
}: endpoint{
Hostname: "elasticfilesystem-fips.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "elasticfilesystem-fips.us-iso-east-1.c2s.ic.gov",
},
},
},
"elasticloadbalancing": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"elasticmapreduce": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"es": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"events": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"firehose": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"glacier": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"health": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"iam": service{
PartitionEndpoint: "aws-iso-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-global",
}: endpoint{
Hostname: "iam.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
},
},
},
"kinesis": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"kms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ProdFips",
}: endpoint{
Hostname: "kms-fips.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-iso-east-1.c2s.ic.gov",
},
endpointKey{
Region: "us-iso-east-1-fips",
}: endpoint{
Hostname: "kms-fips.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-iso-west-1.c2s.ic.gov",
},
endpointKey{
Region: "us-iso-west-1-fips",
}: endpoint{
Hostname: "kms-fips.us-iso-west-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-west-1",
},
Deprecated: boxedTrue,
},
},
},
"lambda": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"license-manager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"logs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"medialive": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"mediapackage": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"monitoring": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"outposts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"ram": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"rds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"redshift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"route53": service{
PartitionEndpoint: "aws-iso-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-global",
}: endpoint{
Hostname: "route53.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
},
},
},
"route53resolver": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"runtime.sagemaker": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"s3": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"secretsmanager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"snowball": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"sns": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"sqs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"ssm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"states": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"streams.dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"sts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"support": service{
PartitionEndpoint: "aws-iso-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-global",
}: endpoint{
Hostname: "support.us-iso-east-1.c2s.ic.gov",
CredentialScope: credentialScope{
Region: "us-iso-east-1",
},
},
},
},
"swf": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
endpointKey{
Region: "us-iso-west-1",
}: endpoint{},
},
},
"synthetics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"tagging": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"transcribe": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"transcribestreaming": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"translate": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
"workspaces": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-iso-east-1",
}: endpoint{},
},
},
},
}
// AwsIsoBPartition returns the Resolver for AWS ISOB (US).
func AwsIsoBPartition() Partition {
return awsisobPartition.Partition()
}
var awsisobPartition = partition{
ID: "aws-iso-b",
Name: "AWS ISOB (US)",
DNSSuffix: "sc2s.sgov.gov",
RegionRegex: regionRegex{
Regexp: func() *regexp.Regexp {
reg, _ := regexp.Compile("^us\\-isob\\-\\w+\\-\\d+$")
return reg
}(),
},
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Hostname: "{service}.{region}.{dnsSuffix}",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "{service}-fips.{region}.{dnsSuffix}",
DNSSuffix: "sc2s.sgov.gov",
Protocols: []string{"https"},
SignatureVersions: []string{"v4"},
},
},
Regions: regions{
"us-isob-east-1": region{
Description: "US ISOB East (Ohio)",
},
},
Services: services{
"api.ecr": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{
Hostname: "api.ecr.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
},
},
},
"application-autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"autoscaling": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"cloudformation": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"cloudtrail": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"codedeploy": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"config": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"dms": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{},
defaultKey{
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.{region}.{dnsSuffix}",
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "dms",
}: endpoint{
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "dms-fips",
}: endpoint{
Hostname: "dms.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
endpointKey{
Region: "us-isob-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "dms.us-isob-east-1.sc2s.sgov.gov",
},
endpointKey{
Region: "us-isob-east-1-fips",
}: endpoint{
Hostname: "dms.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
},
},
"ds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"ebs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"ec2": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"ecs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"eks": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"elasticache": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"elasticloadbalancing": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{
Protocols: []string{"https"},
},
},
},
"elasticmapreduce": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"es": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"events": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"glacier": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"health": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"iam": service{
PartitionEndpoint: "aws-iso-b-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-b-global",
}: endpoint{
Hostname: "iam.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
},
},
},
"kinesis": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"kms": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "ProdFips",
}: endpoint{
Hostname: "kms-fips.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
endpointKey{
Region: "us-isob-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "kms-fips.us-isob-east-1.sc2s.sgov.gov",
},
endpointKey{
Region: "us-isob-east-1-fips",
}: endpoint{
Hostname: "kms-fips.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
Deprecated: boxedTrue,
},
},
},
"lambda": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"license-manager": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"logs": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"monitoring": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"rds": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"redshift": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"route53": service{
PartitionEndpoint: "aws-iso-b-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-b-global",
}: endpoint{
Hostname: "route53.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
},
},
},
"s3": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
SignatureVersions: []string{"s3v4"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"snowball": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"sns": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"sqs": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
SSLCommonName: "{region}.queue.{dnsSuffix}",
Protocols: []string{"http", "https"},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"ssm": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"states": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"streams.dynamodb": service{
Defaults: endpointDefaults{
defaultKey{}: endpoint{
Protocols: []string{"http", "https"},
CredentialScope: credentialScope{
Service: "dynamodb",
},
},
},
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"sts": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"support": service{
PartitionEndpoint: "aws-iso-b-global",
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-iso-b-global",
}: endpoint{
Hostname: "support.us-isob-east-1.sc2s.sgov.gov",
CredentialScope: credentialScope{
Region: "us-isob-east-1",
},
},
},
},
"swf": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"synthetics": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
"tagging": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-isob-east-1",
}: endpoint{},
},
},
},
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/dep_service_ids.go
================================================
package endpoints
// Service identifiers
//
// Deprecated: Use client package's EndpointsID value instead of these
// ServiceIDs. These IDs are not maintained, and are out of date.
const (
A4bServiceID = "a4b" // A4b.
AcmServiceID = "acm" // Acm.
AcmPcaServiceID = "acm-pca" // AcmPca.
ApiMediatailorServiceID = "api.mediatailor" // ApiMediatailor.
ApiPricingServiceID = "api.pricing" // ApiPricing.
ApiSagemakerServiceID = "api.sagemaker" // ApiSagemaker.
ApigatewayServiceID = "apigateway" // Apigateway.
ApplicationAutoscalingServiceID = "application-autoscaling" // ApplicationAutoscaling.
Appstream2ServiceID = "appstream2" // Appstream2.
AppsyncServiceID = "appsync" // Appsync.
AthenaServiceID = "athena" // Athena.
AutoscalingServiceID = "autoscaling" // Autoscaling.
AutoscalingPlansServiceID = "autoscaling-plans" // AutoscalingPlans.
BatchServiceID = "batch" // Batch.
BudgetsServiceID = "budgets" // Budgets.
CeServiceID = "ce" // Ce.
ChimeServiceID = "chime" // Chime.
Cloud9ServiceID = "cloud9" // Cloud9.
ClouddirectoryServiceID = "clouddirectory" // Clouddirectory.
CloudformationServiceID = "cloudformation" // Cloudformation.
CloudfrontServiceID = "cloudfront" // Cloudfront.
CloudhsmServiceID = "cloudhsm" // Cloudhsm.
Cloudhsmv2ServiceID = "cloudhsmv2" // Cloudhsmv2.
CloudsearchServiceID = "cloudsearch" // Cloudsearch.
CloudtrailServiceID = "cloudtrail" // Cloudtrail.
CodebuildServiceID = "codebuild" // Codebuild.
CodecommitServiceID = "codecommit" // Codecommit.
CodedeployServiceID = "codedeploy" // Codedeploy.
CodepipelineServiceID = "codepipeline" // Codepipeline.
CodestarServiceID = "codestar" // Codestar.
CognitoIdentityServiceID = "cognito-identity" // CognitoIdentity.
CognitoIdpServiceID = "cognito-idp" // CognitoIdp.
CognitoSyncServiceID = "cognito-sync" // CognitoSync.
ComprehendServiceID = "comprehend" // Comprehend.
ConfigServiceID = "config" // Config.
CurServiceID = "cur" // Cur.
DatapipelineServiceID = "datapipeline" // Datapipeline.
DaxServiceID = "dax" // Dax.
DevicefarmServiceID = "devicefarm" // Devicefarm.
DirectconnectServiceID = "directconnect" // Directconnect.
DiscoveryServiceID = "discovery" // Discovery.
DmsServiceID = "dms" // Dms.
DsServiceID = "ds" // Ds.
DynamodbServiceID = "dynamodb" // Dynamodb.
Ec2ServiceID = "ec2" // Ec2.
Ec2metadataServiceID = "ec2metadata" // Ec2metadata.
EcrServiceID = "ecr" // Ecr.
EcsServiceID = "ecs" // Ecs.
ElasticacheServiceID = "elasticache" // Elasticache.
ElasticbeanstalkServiceID = "elasticbeanstalk" // Elasticbeanstalk.
ElasticfilesystemServiceID = "elasticfilesystem" // Elasticfilesystem.
ElasticloadbalancingServiceID = "elasticloadbalancing" // Elasticloadbalancing.
ElasticmapreduceServiceID = "elasticmapreduce" // Elasticmapreduce.
ElastictranscoderServiceID = "elastictranscoder" // Elastictranscoder.
EmailServiceID = "email" // Email.
EntitlementMarketplaceServiceID = "entitlement.marketplace" // EntitlementMarketplace.
EsServiceID = "es" // Es.
EventsServiceID = "events" // Events.
FirehoseServiceID = "firehose" // Firehose.
FmsServiceID = "fms" // Fms.
GameliftServiceID = "gamelift" // Gamelift.
GlacierServiceID = "glacier" // Glacier.
GlueServiceID = "glue" // Glue.
GreengrassServiceID = "greengrass" // Greengrass.
GuarddutyServiceID = "guardduty" // Guardduty.
HealthServiceID = "health" // Health.
IamServiceID = "iam" // Iam.
ImportexportServiceID = "importexport" // Importexport.
InspectorServiceID = "inspector" // Inspector.
IotServiceID = "iot" // Iot.
IotanalyticsServiceID = "iotanalytics" // Iotanalytics.
KinesisServiceID = "kinesis" // Kinesis.
KinesisanalyticsServiceID = "kinesisanalytics" // Kinesisanalytics.
KinesisvideoServiceID = "kinesisvideo" // Kinesisvideo.
KmsServiceID = "kms" // Kms.
LambdaServiceID = "lambda" // Lambda.
LightsailServiceID = "lightsail" // Lightsail.
LogsServiceID = "logs" // Logs.
MachinelearningServiceID = "machinelearning" // Machinelearning.
MarketplacecommerceanalyticsServiceID = "marketplacecommerceanalytics" // Marketplacecommerceanalytics.
MediaconvertServiceID = "mediaconvert" // Mediaconvert.
MedialiveServiceID = "medialive" // Medialive.
MediapackageServiceID = "mediapackage" // Mediapackage.
MediastoreServiceID = "mediastore" // Mediastore.
MeteringMarketplaceServiceID = "metering.marketplace" // MeteringMarketplace.
MghServiceID = "mgh" // Mgh.
MobileanalyticsServiceID = "mobileanalytics" // Mobileanalytics.
ModelsLexServiceID = "models.lex" // ModelsLex.
MonitoringServiceID = "monitoring" // Monitoring.
MturkRequesterServiceID = "mturk-requester" // MturkRequester.
NeptuneServiceID = "neptune" // Neptune.
OpsworksServiceID = "opsworks" // Opsworks.
OpsworksCmServiceID = "opsworks-cm" // OpsworksCm.
OrganizationsServiceID = "organizations" // Organizations.
PinpointServiceID = "pinpoint" // Pinpoint.
PollyServiceID = "polly" // Polly.
RdsServiceID = "rds" // Rds.
RedshiftServiceID = "redshift" // Redshift.
RekognitionServiceID = "rekognition" // Rekognition.
ResourceGroupsServiceID = "resource-groups" // ResourceGroups.
Route53ServiceID = "route53" // Route53.
Route53domainsServiceID = "route53domains" // Route53domains.
RuntimeLexServiceID = "runtime.lex" // RuntimeLex.
RuntimeSagemakerServiceID = "runtime.sagemaker" // RuntimeSagemaker.
S3ServiceID = "s3" // S3.
S3ControlServiceID = "s3-control" // S3Control.
SagemakerServiceID = "api.sagemaker" // Sagemaker.
SdbServiceID = "sdb" // Sdb.
SecretsmanagerServiceID = "secretsmanager" // Secretsmanager.
ServerlessrepoServiceID = "serverlessrepo" // Serverlessrepo.
ServicecatalogServiceID = "servicecatalog" // Servicecatalog.
ServicediscoveryServiceID = "servicediscovery" // Servicediscovery.
ShieldServiceID = "shield" // Shield.
SmsServiceID = "sms" // Sms.
SnowballServiceID = "snowball" // Snowball.
SnsServiceID = "sns" // Sns.
SqsServiceID = "sqs" // Sqs.
SsmServiceID = "ssm" // Ssm.
StatesServiceID = "states" // States.
StoragegatewayServiceID = "storagegateway" // Storagegateway.
StreamsDynamodbServiceID = "streams.dynamodb" // StreamsDynamodb.
StsServiceID = "sts" // Sts.
SupportServiceID = "support" // Support.
SwfServiceID = "swf" // Swf.
TaggingServiceID = "tagging" // Tagging.
TransferServiceID = "transfer" // Transfer.
TranslateServiceID = "translate" // Translate.
WafServiceID = "waf" // Waf.
WafRegionalServiceID = "waf-regional" // WafRegional.
WorkdocsServiceID = "workdocs" // Workdocs.
WorkmailServiceID = "workmail" // Workmail.
WorkspacesServiceID = "workspaces" // Workspaces.
XrayServiceID = "xray" // Xray.
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/doc.go
================================================
// Package endpoints provides the types and functionality for defining regions
// and endpoints, as well as querying those definitions.
//
// The SDK's Regions and Endpoints metadata is code generated into the endpoints
// package, and is accessible via the DefaultResolver function. This function
// returns a endpoint Resolver will search the metadata and build an associated
// endpoint if one is found. The default resolver will search all partitions
// known by the SDK. e.g AWS Standard (aws), AWS China (aws-cn), and
// AWS GovCloud (US) (aws-us-gov).
// .
//
// Enumerating Regions and Endpoint Metadata
//
// Casting the Resolver returned by DefaultResolver to a EnumPartitions interface
// will allow you to get access to the list of underlying Partitions with the
// Partitions method. This is helpful if you want to limit the SDK's endpoint
// resolving to a single partition, or enumerate regions, services, and endpoints
// in the partition.
//
// resolver := endpoints.DefaultResolver()
// partitions := resolver.(endpoints.EnumPartitions).Partitions()
//
// for _, p := range partitions {
// fmt.Println("Regions for", p.ID())
// for id, _ := range p.Regions() {
// fmt.Println("*", id)
// }
//
// fmt.Println("Services for", p.ID())
// for id, _ := range p.Services() {
// fmt.Println("*", id)
// }
// }
//
// Using Custom Endpoints
//
// The endpoints package also gives you the ability to use your own logic how
// endpoints are resolved. This is a great way to define a custom endpoint
// for select services, without passing that logic down through your code.
//
// If a type implements the Resolver interface it can be used to resolve
// endpoints. To use this with the SDK's Session and Config set the value
// of the type to the EndpointsResolver field of aws.Config when initializing
// the session, or service client.
//
// In addition the ResolverFunc is a wrapper for a func matching the signature
// of Resolver.EndpointFor, converting it to a type that satisfies the
// Resolver interface.
//
//
// myCustomResolver := func(service, region string, optFns ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) {
// if service == endpoints.S3ServiceID {
// return endpoints.ResolvedEndpoint{
// URL: "s3.custom.endpoint.com",
// SigningRegion: "custom-signing-region",
// }, nil
// }
//
// return endpoints.DefaultResolver().EndpointFor(service, region, optFns...)
// }
//
// sess := session.Must(session.NewSession(&aws.Config{
// Region: aws.String("us-west-2"),
// EndpointResolver: endpoints.ResolverFunc(myCustomResolver),
// }))
package endpoints
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/endpoints.go
================================================
package endpoints
import (
"fmt"
"regexp"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// A Logger is a minimalistic interface for the SDK to log messages to.
type Logger interface {
Log(...interface{})
}
// DualStackEndpointState is a constant to describe the dual-stack endpoint resolution
// behavior.
type DualStackEndpointState uint
const (
// DualStackEndpointStateUnset is the default value behavior for dual-stack endpoint
// resolution.
DualStackEndpointStateUnset DualStackEndpointState = iota
// DualStackEndpointStateEnabled enable dual-stack endpoint resolution for endpoints.
DualStackEndpointStateEnabled
// DualStackEndpointStateDisabled disables dual-stack endpoint resolution for endpoints.
DualStackEndpointStateDisabled
)
// FIPSEndpointState is a constant to describe the FIPS endpoint resolution behavior.
type FIPSEndpointState uint
const (
// FIPSEndpointStateUnset is the default value behavior for FIPS endpoint resolution.
FIPSEndpointStateUnset FIPSEndpointState = iota
// FIPSEndpointStateEnabled enables FIPS endpoint resolution for service endpoints.
FIPSEndpointStateEnabled
// FIPSEndpointStateDisabled disables FIPS endpoint resolution for endpoints.
FIPSEndpointStateDisabled
)
// Options provide the configuration needed to direct how the
// endpoints will be resolved.
type Options struct {
// DisableSSL forces the endpoint to be resolved as HTTP.
// instead of HTTPS if the service supports it.
DisableSSL bool
// Sets the resolver to resolve the endpoint as a dualstack endpoint
// for the service. If dualstack support for a service is not known and
// StrictMatching is not enabled a dualstack endpoint for the service will
// be returned. This endpoint may not be valid. If StrictMatching is
// enabled only services that are known to support dualstack will return
// dualstack endpoints.
//
// Deprecated: This option will continue to function for S3 and S3 Control for backwards compatibility.
// UseDualStackEndpoint should be used to enable usage of a service's dual-stack endpoint for all service clients
// moving forward. For S3 and S3 Control, when UseDualStackEndpoint is set to a non-zero value it takes higher
// precedence then this option.
UseDualStack bool
// Sets the resolver to resolve a dual-stack endpoint for the service.
UseDualStackEndpoint DualStackEndpointState
// UseFIPSEndpoint specifies the resolver must resolve a FIPS endpoint.
UseFIPSEndpoint FIPSEndpointState
// Enables strict matching of services and regions resolved endpoints.
// If the partition doesn't enumerate the exact service and region an
// error will be returned. This option will prevent returning endpoints
// that look valid, but may not resolve to any real endpoint.
StrictMatching bool
// Enables resolving a service endpoint based on the region provided if the
// service does not exist. The service endpoint ID will be used as the service
// domain name prefix. By default the endpoint resolver requires the service
// to be known when resolving endpoints.
//
// If resolving an endpoint on the partition list the provided region will
// be used to determine which partition's domain name pattern to the service
// endpoint ID with. If both the service and region are unknown and resolving
// the endpoint on partition list an UnknownEndpointError error will be returned.
//
// If resolving and endpoint on a partition specific resolver that partition's
// domain name pattern will be used with the service endpoint ID. If both
// region and service do not exist when resolving an endpoint on a specific
// partition the partition's domain pattern will be used to combine the
// endpoint and region together.
//
// This option is ignored if StrictMatching is enabled.
ResolveUnknownService bool
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
EC2MetadataEndpointMode EC2IMDSEndpointModeState
// STS Regional Endpoint flag helps with resolving the STS endpoint
STSRegionalEndpoint STSRegionalEndpoint
// S3 Regional Endpoint flag helps with resolving the S3 endpoint
S3UsEast1RegionalEndpoint S3UsEast1RegionalEndpoint
// ResolvedRegion is the resolved region string. If provided (non-zero length) it takes priority
// over the region name passed to the ResolveEndpoint call.
ResolvedRegion string
// Logger is the logger that will be used to log messages.
Logger Logger
// Determines whether logging of deprecated endpoints usage is enabled.
LogDeprecated bool
}
func (o Options) getEndpointVariant(service string) (v endpointVariant) {
const s3 = "s3"
const s3Control = "s3-control"
if (o.UseDualStackEndpoint == DualStackEndpointStateEnabled) ||
((service == s3 || service == s3Control) && (o.UseDualStackEndpoint == DualStackEndpointStateUnset && o.UseDualStack)) {
v |= dualStackVariant
}
if o.UseFIPSEndpoint == FIPSEndpointStateEnabled {
v |= fipsVariant
}
return v
}
// EC2IMDSEndpointModeState is an enum configuration variable describing the client endpoint mode.
type EC2IMDSEndpointModeState uint
// Enumeration values for EC2IMDSEndpointModeState
const (
EC2IMDSEndpointModeStateUnset EC2IMDSEndpointModeState = iota
EC2IMDSEndpointModeStateIPv4
EC2IMDSEndpointModeStateIPv6
)
// SetFromString sets the EC2IMDSEndpointModeState based on the provided string value. Unknown values will default to EC2IMDSEndpointModeStateUnset
func (e *EC2IMDSEndpointModeState) SetFromString(v string) error {
v = strings.TrimSpace(v)
switch {
case len(v) == 0:
*e = EC2IMDSEndpointModeStateUnset
case strings.EqualFold(v, "IPv6"):
*e = EC2IMDSEndpointModeStateIPv6
case strings.EqualFold(v, "IPv4"):
*e = EC2IMDSEndpointModeStateIPv4
default:
return fmt.Errorf("unknown EC2 IMDS endpoint mode, must be either IPv6 or IPv4")
}
return nil
}
// STSRegionalEndpoint is an enum for the states of the STS Regional Endpoint
// options.
type STSRegionalEndpoint int
func (e STSRegionalEndpoint) String() string {
switch e {
case LegacySTSEndpoint:
return "legacy"
case RegionalSTSEndpoint:
return "regional"
case UnsetSTSEndpoint:
return ""
default:
return "unknown"
}
}
const (
// UnsetSTSEndpoint represents that STS Regional Endpoint flag is not specified.
UnsetSTSEndpoint STSRegionalEndpoint = iota
// LegacySTSEndpoint represents when STS Regional Endpoint flag is specified
// to use legacy endpoints.
LegacySTSEndpoint
// RegionalSTSEndpoint represents when STS Regional Endpoint flag is specified
// to use regional endpoints.
RegionalSTSEndpoint
)
// GetSTSRegionalEndpoint function returns the STSRegionalEndpointFlag based
// on the input string provided in env config or shared config by the user.
//
// `legacy`, `regional` are the only case-insensitive valid strings for
// resolving the STS regional Endpoint flag.
func GetSTSRegionalEndpoint(s string) (STSRegionalEndpoint, error) {
switch {
case strings.EqualFold(s, "legacy"):
return LegacySTSEndpoint, nil
case strings.EqualFold(s, "regional"):
return RegionalSTSEndpoint, nil
default:
return UnsetSTSEndpoint, fmt.Errorf("unable to resolve the value of STSRegionalEndpoint for %v", s)
}
}
// S3UsEast1RegionalEndpoint is an enum for the states of the S3 us-east-1
// Regional Endpoint options.
type S3UsEast1RegionalEndpoint int
func (e S3UsEast1RegionalEndpoint) String() string {
switch e {
case LegacyS3UsEast1Endpoint:
return "legacy"
case RegionalS3UsEast1Endpoint:
return "regional"
case UnsetS3UsEast1Endpoint:
return ""
default:
return "unknown"
}
}
const (
// UnsetS3UsEast1Endpoint represents that S3 Regional Endpoint flag is not
// specified.
UnsetS3UsEast1Endpoint S3UsEast1RegionalEndpoint = iota
// LegacyS3UsEast1Endpoint represents when S3 Regional Endpoint flag is
// specified to use legacy endpoints.
LegacyS3UsEast1Endpoint
// RegionalS3UsEast1Endpoint represents when S3 Regional Endpoint flag is
// specified to use regional endpoints.
RegionalS3UsEast1Endpoint
)
// GetS3UsEast1RegionalEndpoint function returns the S3UsEast1RegionalEndpointFlag based
// on the input string provided in env config or shared config by the user.
//
// `legacy`, `regional` are the only case-insensitive valid strings for
// resolving the S3 regional Endpoint flag.
func GetS3UsEast1RegionalEndpoint(s string) (S3UsEast1RegionalEndpoint, error) {
switch {
case strings.EqualFold(s, "legacy"):
return LegacyS3UsEast1Endpoint, nil
case strings.EqualFold(s, "regional"):
return RegionalS3UsEast1Endpoint, nil
default:
return UnsetS3UsEast1Endpoint,
fmt.Errorf("unable to resolve the value of S3UsEast1RegionalEndpoint for %v", s)
}
}
// Set combines all of the option functions together.
func (o *Options) Set(optFns ...func(*Options)) {
for _, fn := range optFns {
fn(o)
}
}
// DisableSSLOption sets the DisableSSL options. Can be used as a functional
// option when resolving endpoints.
func DisableSSLOption(o *Options) {
o.DisableSSL = true
}
// UseDualStackOption sets the UseDualStack option. Can be used as a functional
// option when resolving endpoints.
//
// Deprecated: UseDualStackEndpointOption should be used to enable usage of a service's dual-stack endpoint.
// When DualStackEndpointState is set to a non-zero value it takes higher precedence then this option.
func UseDualStackOption(o *Options) {
o.UseDualStack = true
}
// UseDualStackEndpointOption sets the UseDualStackEndpoint option to enabled. Can be used as a functional
// option when resolving endpoints.
func UseDualStackEndpointOption(o *Options) {
o.UseDualStackEndpoint = DualStackEndpointStateEnabled
}
// UseFIPSEndpointOption sets the UseFIPSEndpoint option to enabled. Can be used as a functional
// option when resolving endpoints.
func UseFIPSEndpointOption(o *Options) {
o.UseFIPSEndpoint = FIPSEndpointStateEnabled
}
// StrictMatchingOption sets the StrictMatching option. Can be used as a functional
// option when resolving endpoints.
func StrictMatchingOption(o *Options) {
o.StrictMatching = true
}
// ResolveUnknownServiceOption sets the ResolveUnknownService option. Can be used
// as a functional option when resolving endpoints.
func ResolveUnknownServiceOption(o *Options) {
o.ResolveUnknownService = true
}
// STSRegionalEndpointOption enables the STS endpoint resolver behavior to resolve
// STS endpoint to their regional endpoint, instead of the global endpoint.
func STSRegionalEndpointOption(o *Options) {
o.STSRegionalEndpoint = RegionalSTSEndpoint
}
// A Resolver provides the interface for functionality to resolve endpoints.
// The build in Partition and DefaultResolver return value satisfy this interface.
type Resolver interface {
EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
}
// ResolverFunc is a helper utility that wraps a function so it satisfies the
// Resolver interface. This is useful when you want to add additional endpoint
// resolving logic, or stub out specific endpoints with custom values.
type ResolverFunc func(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error)
// EndpointFor wraps the ResolverFunc function to satisfy the Resolver interface.
func (fn ResolverFunc) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
return fn(service, region, opts...)
}
var schemeRE = regexp.MustCompile("^([^:]+)://")
// AddScheme adds the HTTP or HTTPS schemes to a endpoint URL if there is no
// scheme. If disableSSL is true HTTP will set HTTP instead of the default HTTPS.
//
// If disableSSL is set, it will only set the URL's scheme if the URL does not
// contain a scheme.
func AddScheme(endpoint string, disableSSL bool) string {
if !schemeRE.MatchString(endpoint) {
scheme := "https"
if disableSSL {
scheme = "http"
}
endpoint = fmt.Sprintf("%s://%s", scheme, endpoint)
}
return endpoint
}
// EnumPartitions a provides a way to retrieve the underlying partitions that
// make up the SDK's default Resolver, or any resolver decoded from a model
// file.
//
// Use this interface with DefaultResolver and DecodeModels to get the list of
// Partitions.
type EnumPartitions interface {
Partitions() []Partition
}
// RegionsForService returns a map of regions for the partition and service.
// If either the partition or service does not exist false will be returned
// as the second parameter.
//
// This example shows how to get the regions for DynamoDB in the AWS partition.
// rs, exists := endpoints.RegionsForService(endpoints.DefaultPartitions(), endpoints.AwsPartitionID, endpoints.DynamodbServiceID)
//
// This is equivalent to using the partition directly.
// rs := endpoints.AwsPartition().Services()[endpoints.DynamodbServiceID].Regions()
func RegionsForService(ps []Partition, partitionID, serviceID string) (map[string]Region, bool) {
for _, p := range ps {
if p.ID() != partitionID {
continue
}
if _, ok := p.p.Services[serviceID]; !(ok || serviceID == Ec2metadataServiceID) {
break
}
s := Service{
id: serviceID,
p: p.p,
}
return s.Regions(), true
}
return map[string]Region{}, false
}
// PartitionForRegion returns the first partition which includes the region
// passed in. This includes both known regions and regions which match
// a pattern supported by the partition which may include regions that are
// not explicitly known by the partition. Use the Regions method of the
// returned Partition if explicit support is needed.
func PartitionForRegion(ps []Partition, regionID string) (Partition, bool) {
for _, p := range ps {
if _, ok := p.p.Regions[regionID]; ok || p.p.RegionRegex.MatchString(regionID) {
return p, true
}
}
return Partition{}, false
}
// A Partition provides the ability to enumerate the partition's regions
// and services.
type Partition struct {
id, dnsSuffix string
p *partition
}
// DNSSuffix returns the base domain name of the partition.
func (p Partition) DNSSuffix() string { return p.dnsSuffix }
// ID returns the identifier of the partition.
func (p Partition) ID() string { return p.id }
// EndpointFor attempts to resolve the endpoint based on service and region.
// See Options for information on configuring how the endpoint is resolved.
//
// If the service cannot be found in the metadata the UnknownServiceError
// error will be returned. This validation will occur regardless if
// StrictMatching is enabled. To enable resolving unknown services set the
// "ResolveUnknownService" option to true. When StrictMatching is disabled
// this option allows the partition resolver to resolve a endpoint based on
// the service endpoint ID provided.
//
// When resolving endpoints you can choose to enable StrictMatching. This will
// require the provided service and region to be known by the partition.
// If the endpoint cannot be strictly resolved an error will be returned. This
// mode is useful to ensure the endpoint resolved is valid. Without
// StrictMatching enabled the endpoint returned may look valid but may not work.
// StrictMatching requires the SDK to be updated if you want to take advantage
// of new regions and services expansions.
//
// Errors that can be returned.
// * UnknownServiceError
// * UnknownEndpointError
func (p Partition) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
return p.p.EndpointFor(service, region, opts...)
}
// Regions returns a map of Regions indexed by their ID. This is useful for
// enumerating over the regions in a partition.
func (p Partition) Regions() map[string]Region {
rs := make(map[string]Region, len(p.p.Regions))
for id, r := range p.p.Regions {
rs[id] = Region{
id: id,
desc: r.Description,
p: p.p,
}
}
return rs
}
// Services returns a map of Service indexed by their ID. This is useful for
// enumerating over the services in a partition.
func (p Partition) Services() map[string]Service {
ss := make(map[string]Service, len(p.p.Services))
for id := range p.p.Services {
ss[id] = Service{
id: id,
p: p.p,
}
}
// Since we have removed the customization that injected this into the model
// we still need to pretend that this is a modeled service.
if _, ok := ss[Ec2metadataServiceID]; !ok {
ss[Ec2metadataServiceID] = Service{
id: Ec2metadataServiceID,
p: p.p,
}
}
return ss
}
// A Region provides information about a region, and ability to resolve an
// endpoint from the context of a region, given a service.
type Region struct {
id, desc string
p *partition
}
// ID returns the region's identifier.
func (r Region) ID() string { return r.id }
// Description returns the region's description. The region description
// is free text, it can be empty, and it may change between SDK releases.
func (r Region) Description() string { return r.desc }
// ResolveEndpoint resolves an endpoint from the context of the region given
// a service. See Partition.EndpointFor for usage and errors that can be returned.
func (r Region) ResolveEndpoint(service string, opts ...func(*Options)) (ResolvedEndpoint, error) {
return r.p.EndpointFor(service, r.id, opts...)
}
// Services returns a list of all services that are known to be in this region.
func (r Region) Services() map[string]Service {
ss := map[string]Service{}
for id, s := range r.p.Services {
if _, ok := s.Endpoints[endpointKey{Region: r.id}]; ok {
ss[id] = Service{
id: id,
p: r.p,
}
}
}
return ss
}
// A Service provides information about a service, and ability to resolve an
// endpoint from the context of a service, given a region.
type Service struct {
id string
p *partition
}
// ID returns the identifier for the service.
func (s Service) ID() string { return s.id }
// ResolveEndpoint resolves an endpoint from the context of a service given
// a region. See Partition.EndpointFor for usage and errors that can be returned.
func (s Service) ResolveEndpoint(region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
return s.p.EndpointFor(s.id, region, opts...)
}
// Regions returns a map of Regions that the service is present in.
//
// A region is the AWS region the service exists in. Whereas a Endpoint is
// an URL that can be resolved to a instance of a service.
func (s Service) Regions() map[string]Region {
rs := map[string]Region{}
service, ok := s.p.Services[s.id]
// Since ec2metadata customization has been removed we need to check
// if it was defined in non-standard endpoints.json file. If it's not
// then we can return the empty map as there is no regional-endpoints for IMDS.
// Otherwise, we iterate need to iterate the non-standard model.
if s.id == Ec2metadataServiceID && !ok {
return rs
}
for id := range service.Endpoints {
if id.Variant != 0 {
continue
}
if r, ok := s.p.Regions[id.Region]; ok {
rs[id.Region] = Region{
id: id.Region,
desc: r.Description,
p: s.p,
}
}
}
return rs
}
// Endpoints returns a map of Endpoints indexed by their ID for all known
// endpoints for a service.
//
// A region is the AWS region the service exists in. Whereas a Endpoint is
// an URL that can be resolved to a instance of a service.
func (s Service) Endpoints() map[string]Endpoint {
es := make(map[string]Endpoint, len(s.p.Services[s.id].Endpoints))
for id := range s.p.Services[s.id].Endpoints {
if id.Variant != 0 {
continue
}
es[id.Region] = Endpoint{
id: id.Region,
serviceID: s.id,
p: s.p,
}
}
return es
}
// A Endpoint provides information about endpoints, and provides the ability
// to resolve that endpoint for the service, and the region the endpoint
// represents.
type Endpoint struct {
id string
serviceID string
p *partition
}
// ID returns the identifier for an endpoint.
func (e Endpoint) ID() string { return e.id }
// ServiceID returns the identifier the endpoint belongs to.
func (e Endpoint) ServiceID() string { return e.serviceID }
// ResolveEndpoint resolves an endpoint from the context of a service and
// region the endpoint represents. See Partition.EndpointFor for usage and
// errors that can be returned.
func (e Endpoint) ResolveEndpoint(opts ...func(*Options)) (ResolvedEndpoint, error) {
return e.p.EndpointFor(e.serviceID, e.id, opts...)
}
// A ResolvedEndpoint is an endpoint that has been resolved based on a partition
// service, and region.
type ResolvedEndpoint struct {
// The endpoint URL
URL string
// The endpoint partition
PartitionID string
// The region that should be used for signing requests.
SigningRegion string
// The service name that should be used for signing requests.
SigningName string
// States that the signing name for this endpoint was derived from metadata
// passed in, but was not explicitly modeled.
SigningNameDerived bool
// The signing method that should be used for signing requests.
SigningMethod string
}
// So that the Error interface type can be included as an anonymous field
// in the requestError struct and not conflict with the error.Error() method.
type awsError awserr.Error
// A EndpointNotFoundError is returned when in StrictMatching mode, and the
// endpoint for the service and region cannot be found in any of the partitions.
type EndpointNotFoundError struct {
awsError
Partition string
Service string
Region string
}
// A UnknownServiceError is returned when the service does not resolve to an
// endpoint. Includes a list of all known services for the partition. Returned
// when a partition does not support the service.
type UnknownServiceError struct {
awsError
Partition string
Service string
Known []string
}
// NewUnknownServiceError builds and returns UnknownServiceError.
func NewUnknownServiceError(p, s string, known []string) UnknownServiceError {
return UnknownServiceError{
awsError: awserr.New("UnknownServiceError",
"could not resolve endpoint for unknown service", nil),
Partition: p,
Service: s,
Known: known,
}
}
// String returns the string representation of the error.
func (e UnknownServiceError) Error() string {
extra := fmt.Sprintf("partition: %q, service: %q",
e.Partition, e.Service)
if len(e.Known) > 0 {
extra += fmt.Sprintf(", known: %v", e.Known)
}
return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
}
// String returns the string representation of the error.
func (e UnknownServiceError) String() string {
return e.Error()
}
// A UnknownEndpointError is returned when in StrictMatching mode and the
// service is valid, but the region does not resolve to an endpoint. Includes
// a list of all known endpoints for the service.
type UnknownEndpointError struct {
awsError
Partition string
Service string
Region string
Known []string
}
// NewUnknownEndpointError builds and returns UnknownEndpointError.
func NewUnknownEndpointError(p, s, r string, known []string) UnknownEndpointError {
return UnknownEndpointError{
awsError: awserr.New("UnknownEndpointError",
"could not resolve endpoint", nil),
Partition: p,
Service: s,
Region: r,
Known: known,
}
}
// String returns the string representation of the error.
func (e UnknownEndpointError) Error() string {
extra := fmt.Sprintf("partition: %q, service: %q, region: %q",
e.Partition, e.Service, e.Region)
if len(e.Known) > 0 {
extra += fmt.Sprintf(", known: %v", e.Known)
}
return awserr.SprintError(e.Code(), e.Message(), extra, e.OrigErr())
}
// String returns the string representation of the error.
func (e UnknownEndpointError) String() string {
return e.Error()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/legacy_regions.go
================================================
package endpoints
var legacyGlobalRegions = map[string]map[string]struct{}{
"sts": {
"ap-northeast-1": {},
"ap-south-1": {},
"ap-southeast-1": {},
"ap-southeast-2": {},
"ca-central-1": {},
"eu-central-1": {},
"eu-north-1": {},
"eu-west-1": {},
"eu-west-2": {},
"eu-west-3": {},
"sa-east-1": {},
"us-east-1": {},
"us-east-2": {},
"us-west-1": {},
"us-west-2": {},
},
"s3": {
"us-east-1": {},
},
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model.go
================================================
package endpoints
import (
"encoding/json"
"fmt"
"regexp"
"strconv"
"strings"
)
const (
ec2MetadataEndpointIPv6 = "http://[fd00:ec2::254]/latest"
ec2MetadataEndpointIPv4 = "http://169.254.169.254/latest"
)
const dnsSuffixTemplateKey = "{dnsSuffix}"
// defaultKey is a compound map key of a variant and other values.
type defaultKey struct {
Variant endpointVariant
ServiceVariant serviceVariant
}
// endpointKey is a compound map key of a region and associated variant value.
type endpointKey struct {
Region string
Variant endpointVariant
}
// endpointVariant is a bit field to describe the endpoints attributes.
type endpointVariant uint64
// serviceVariant is a bit field to describe the service endpoint attributes.
type serviceVariant uint64
const (
// fipsVariant indicates that the endpoint is FIPS capable.
fipsVariant endpointVariant = 1 << (64 - 1 - iota)
// dualStackVariant indicates that the endpoint is DualStack capable.
dualStackVariant
)
var regionValidationRegex = regexp.MustCompile(`^[[:alnum:]]([[:alnum:]\-]*[[:alnum:]])?$`)
type partitions []partition
func (ps partitions) EndpointFor(service, region string, opts ...func(*Options)) (ResolvedEndpoint, error) {
var opt Options
opt.Set(opts...)
if len(opt.ResolvedRegion) > 0 {
region = opt.ResolvedRegion
}
for i := 0; i < len(ps); i++ {
if !ps[i].canResolveEndpoint(service, region, opt) {
continue
}
return ps[i].EndpointFor(service, region, opts...)
}
// If loose matching fallback to first partition format to use
// when resolving the endpoint.
if !opt.StrictMatching && len(ps) > 0 {
return ps[0].EndpointFor(service, region, opts...)
}
return ResolvedEndpoint{}, NewUnknownEndpointError("all partitions", service, region, []string{})
}
// Partitions satisfies the EnumPartitions interface and returns a list
// of Partitions representing each partition represented in the SDK's
// endpoints model.
func (ps partitions) Partitions() []Partition {
parts := make([]Partition, 0, len(ps))
for i := 0; i < len(ps); i++ {
parts = append(parts, ps[i].Partition())
}
return parts
}
type endpointWithVariants struct {
endpoint
Variants []endpointWithTags `json:"variants"`
}
type endpointWithTags struct {
endpoint
Tags []string `json:"tags"`
}
type endpointDefaults map[defaultKey]endpoint
func (p *endpointDefaults) UnmarshalJSON(data []byte) error {
if *p == nil {
*p = make(endpointDefaults)
}
var e endpointWithVariants
if err := json.Unmarshal(data, &e); err != nil {
return err
}
(*p)[defaultKey{Variant: 0}] = e.endpoint
e.Hostname = ""
e.DNSSuffix = ""
for _, variant := range e.Variants {
endpointVariant, unknown := parseVariantTags(variant.Tags)
if unknown {
continue
}
var ve endpoint
ve.mergeIn(e.endpoint)
ve.mergeIn(variant.endpoint)
(*p)[defaultKey{Variant: endpointVariant}] = ve
}
return nil
}
func parseVariantTags(tags []string) (ev endpointVariant, unknown bool) {
if len(tags) == 0 {
unknown = true
return
}
for _, tag := range tags {
switch {
case strings.EqualFold("fips", tag):
ev |= fipsVariant
case strings.EqualFold("dualstack", tag):
ev |= dualStackVariant
default:
unknown = true
}
}
return ev, unknown
}
type partition struct {
ID string `json:"partition"`
Name string `json:"partitionName"`
DNSSuffix string `json:"dnsSuffix"`
RegionRegex regionRegex `json:"regionRegex"`
Defaults endpointDefaults `json:"defaults"`
Regions regions `json:"regions"`
Services services `json:"services"`
}
func (p partition) Partition() Partition {
return Partition{
dnsSuffix: p.DNSSuffix,
id: p.ID,
p: &p,
}
}
func (p partition) canResolveEndpoint(service, region string, options Options) bool {
s, hasService := p.Services[service]
_, hasEndpoint := s.Endpoints[endpointKey{
Region: region,
Variant: options.getEndpointVariant(service),
}]
if hasEndpoint && hasService {
return true
}
if options.StrictMatching {
return false
}
return p.RegionRegex.MatchString(region)
}
func allowLegacyEmptyRegion(service string) bool {
legacy := map[string]struct{}{
"budgets": {},
"ce": {},
"chime": {},
"cloudfront": {},
"ec2metadata": {},
"iam": {},
"importexport": {},
"organizations": {},
"route53": {},
"sts": {},
"support": {},
"waf": {},
}
_, allowed := legacy[service]
return allowed
}
func (p partition) EndpointFor(service, region string, opts ...func(*Options)) (resolved ResolvedEndpoint, err error) {
var opt Options
opt.Set(opts...)
if len(opt.ResolvedRegion) > 0 {
region = opt.ResolvedRegion
}
s, hasService := p.Services[service]
if service == Ec2metadataServiceID && !hasService {
endpoint := getEC2MetadataEndpoint(p.ID, service, opt.EC2MetadataEndpointMode)
return endpoint, nil
}
if len(service) == 0 || !(hasService || opt.ResolveUnknownService) {
// Only return error if the resolver will not fallback to creating
// endpoint based on service endpoint ID passed in.
return resolved, NewUnknownServiceError(p.ID, service, serviceList(p.Services))
}
if len(region) == 0 && allowLegacyEmptyRegion(service) && len(s.PartitionEndpoint) != 0 {
region = s.PartitionEndpoint
}
if r, ok := isLegacyGlobalRegion(service, region, opt); ok {
region = r
}
variant := opt.getEndpointVariant(service)
endpoints := s.Endpoints
serviceDefaults, hasServiceDefault := s.Defaults[defaultKey{Variant: variant}]
// If we searched for a variant which may have no explicit service defaults,
// then we need to inherit the standard service defaults except the hostname and dnsSuffix
if variant != 0 && !hasServiceDefault {
serviceDefaults = s.Defaults[defaultKey{}]
serviceDefaults.Hostname = ""
serviceDefaults.DNSSuffix = ""
}
partitionDefaults, hasPartitionDefault := p.Defaults[defaultKey{Variant: variant}]
var dnsSuffix string
if len(serviceDefaults.DNSSuffix) > 0 {
dnsSuffix = serviceDefaults.DNSSuffix
} else if variant == 0 {
// For legacy reasons the partition dnsSuffix is not in the defaults, so if we looked for
// a non-variant endpoint then we need to set the dnsSuffix.
dnsSuffix = p.DNSSuffix
}
noDefaults := !hasServiceDefault && !hasPartitionDefault
e, hasEndpoint := s.endpointForRegion(region, endpoints, variant)
if len(region) == 0 || (!hasEndpoint && (opt.StrictMatching || noDefaults)) {
return resolved, NewUnknownEndpointError(p.ID, service, region, endpointList(endpoints, variant))
}
defs := []endpoint{partitionDefaults, serviceDefaults}
return e.resolve(service, p.ID, region, dnsSuffixTemplateKey, dnsSuffix, defs, opt)
}
func getEC2MetadataEndpoint(partitionID, service string, mode EC2IMDSEndpointModeState) ResolvedEndpoint {
switch mode {
case EC2IMDSEndpointModeStateIPv6:
return ResolvedEndpoint{
URL: ec2MetadataEndpointIPv6,
PartitionID: partitionID,
SigningRegion: "aws-global",
SigningName: service,
SigningNameDerived: true,
SigningMethod: "v4",
}
case EC2IMDSEndpointModeStateIPv4:
fallthrough
default:
return ResolvedEndpoint{
URL: ec2MetadataEndpointIPv4,
PartitionID: partitionID,
SigningRegion: "aws-global",
SigningName: service,
SigningNameDerived: true,
SigningMethod: "v4",
}
}
}
func isLegacyGlobalRegion(service string, region string, opt Options) (string, bool) {
if opt.getEndpointVariant(service) != 0 {
return "", false
}
const (
sts = "sts"
s3 = "s3"
awsGlobal = "aws-global"
)
switch {
case service == sts && opt.STSRegionalEndpoint == RegionalSTSEndpoint:
return region, false
case service == s3 && opt.S3UsEast1RegionalEndpoint == RegionalS3UsEast1Endpoint:
return region, false
default:
if _, ok := legacyGlobalRegions[service][region]; ok {
return awsGlobal, true
}
}
return region, false
}
func serviceList(ss services) []string {
list := make([]string, 0, len(ss))
for k := range ss {
list = append(list, k)
}
return list
}
func endpointList(es serviceEndpoints, variant endpointVariant) []string {
list := make([]string, 0, len(es))
for k := range es {
if k.Variant != variant {
continue
}
list = append(list, k.Region)
}
return list
}
type regionRegex struct {
*regexp.Regexp
}
func (rr *regionRegex) UnmarshalJSON(b []byte) (err error) {
// Strip leading and trailing quotes
regex, err := strconv.Unquote(string(b))
if err != nil {
return fmt.Errorf("unable to strip quotes from regex, %v", err)
}
rr.Regexp, err = regexp.Compile(regex)
if err != nil {
return fmt.Errorf("unable to unmarshal region regex, %v", err)
}
return nil
}
type regions map[string]region
type region struct {
Description string `json:"description"`
}
type services map[string]service
type service struct {
PartitionEndpoint string `json:"partitionEndpoint"`
IsRegionalized boxedBool `json:"isRegionalized,omitempty"`
Defaults endpointDefaults `json:"defaults"`
Endpoints serviceEndpoints `json:"endpoints"`
}
func (s *service) endpointForRegion(region string, endpoints serviceEndpoints, variant endpointVariant) (endpoint, bool) {
if e, ok := endpoints[endpointKey{Region: region, Variant: variant}]; ok {
return e, true
}
if s.IsRegionalized == boxedFalse {
return endpoints[endpointKey{Region: s.PartitionEndpoint, Variant: variant}], region == s.PartitionEndpoint
}
// Unable to find any matching endpoint, return
// blank that will be used for generic endpoint creation.
return endpoint{}, false
}
type serviceEndpoints map[endpointKey]endpoint
func (s *serviceEndpoints) UnmarshalJSON(data []byte) error {
if *s == nil {
*s = make(serviceEndpoints)
}
var regionToEndpoint map[string]endpointWithVariants
if err := json.Unmarshal(data, ®ionToEndpoint); err != nil {
return err
}
for region, e := range regionToEndpoint {
(*s)[endpointKey{Region: region}] = e.endpoint
e.Hostname = ""
e.DNSSuffix = ""
for _, variant := range e.Variants {
endpointVariant, unknown := parseVariantTags(variant.Tags)
if unknown {
continue
}
var ve endpoint
ve.mergeIn(e.endpoint)
ve.mergeIn(variant.endpoint)
(*s)[endpointKey{Region: region, Variant: endpointVariant}] = ve
}
}
return nil
}
type endpoint struct {
Hostname string `json:"hostname"`
Protocols []string `json:"protocols"`
CredentialScope credentialScope `json:"credentialScope"`
DNSSuffix string `json:"dnsSuffix"`
// Signature Version not used
SignatureVersions []string `json:"signatureVersions"`
// SSLCommonName not used.
SSLCommonName string `json:"sslCommonName"`
Deprecated boxedBool `json:"deprecated"`
}
// isZero returns whether the endpoint structure is an empty (zero) value.
func (e endpoint) isZero() bool {
switch {
case len(e.Hostname) != 0:
return false
case len(e.Protocols) != 0:
return false
case e.CredentialScope != (credentialScope{}):
return false
case len(e.SignatureVersions) != 0:
return false
case len(e.SSLCommonName) != 0:
return false
}
return true
}
const (
defaultProtocol = "https"
defaultSigner = "v4"
)
var (
protocolPriority = []string{"https", "http"}
signerPriority = []string{"v4", "v2"}
)
func getByPriority(s []string, p []string, def string) string {
if len(s) == 0 {
return def
}
for i := 0; i < len(p); i++ {
for j := 0; j < len(s); j++ {
if s[j] == p[i] {
return s[j]
}
}
}
return s[0]
}
func (e endpoint) resolve(service, partitionID, region, dnsSuffixTemplateVariable, dnsSuffix string, defs []endpoint, opts Options) (ResolvedEndpoint, error) {
var merged endpoint
for _, def := range defs {
merged.mergeIn(def)
}
merged.mergeIn(e)
e = merged
signingRegion := e.CredentialScope.Region
if len(signingRegion) == 0 {
signingRegion = region
}
signingName := e.CredentialScope.Service
var signingNameDerived bool
if len(signingName) == 0 {
signingName = service
signingNameDerived = true
}
hostname := e.Hostname
if !validateInputRegion(region) {
return ResolvedEndpoint{}, fmt.Errorf("invalid region identifier format provided")
}
if len(merged.DNSSuffix) > 0 {
dnsSuffix = merged.DNSSuffix
}
u := strings.Replace(hostname, "{service}", service, 1)
u = strings.Replace(u, "{region}", region, 1)
u = strings.Replace(u, dnsSuffixTemplateVariable, dnsSuffix, 1)
scheme := getEndpointScheme(e.Protocols, opts.DisableSSL)
u = fmt.Sprintf("%s://%s", scheme, u)
if e.Deprecated == boxedTrue && opts.LogDeprecated && opts.Logger != nil {
opts.Logger.Log(fmt.Sprintf("endpoint identifier %q, url %q marked as deprecated", region, u))
}
return ResolvedEndpoint{
URL: u,
PartitionID: partitionID,
SigningRegion: signingRegion,
SigningName: signingName,
SigningNameDerived: signingNameDerived,
SigningMethod: getByPriority(e.SignatureVersions, signerPriority, defaultSigner),
}, nil
}
func getEndpointScheme(protocols []string, disableSSL bool) string {
if disableSSL {
return "http"
}
return getByPriority(protocols, protocolPriority, defaultProtocol)
}
func (e *endpoint) mergeIn(other endpoint) {
if len(other.Hostname) > 0 {
e.Hostname = other.Hostname
}
if len(other.Protocols) > 0 {
e.Protocols = other.Protocols
}
if len(other.SignatureVersions) > 0 {
e.SignatureVersions = other.SignatureVersions
}
if len(other.CredentialScope.Region) > 0 {
e.CredentialScope.Region = other.CredentialScope.Region
}
if len(other.CredentialScope.Service) > 0 {
e.CredentialScope.Service = other.CredentialScope.Service
}
if len(other.SSLCommonName) > 0 {
e.SSLCommonName = other.SSLCommonName
}
if len(other.DNSSuffix) > 0 {
e.DNSSuffix = other.DNSSuffix
}
if other.Deprecated != boxedBoolUnset {
e.Deprecated = other.Deprecated
}
}
type credentialScope struct {
Region string `json:"region"`
Service string `json:"service"`
}
type boxedBool int
func (b *boxedBool) UnmarshalJSON(buf []byte) error {
v, err := strconv.ParseBool(string(buf))
if err != nil {
return err
}
if v {
*b = boxedTrue
} else {
*b = boxedFalse
}
return nil
}
const (
boxedBoolUnset boxedBool = iota
boxedFalse
boxedTrue
)
func validateInputRegion(region string) bool {
return regionValidationRegex.MatchString(region)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/endpoints/v3model_codegen.go
================================================
//go:build codegen
// +build codegen
package endpoints
import (
"fmt"
"io"
"reflect"
"strings"
"text/template"
"unicode"
)
// A CodeGenOptions are the options for code generating the endpoints into
// Go code from the endpoints model definition.
type CodeGenOptions struct {
// Options for how the model will be decoded.
DecodeModelOptions DecodeModelOptions
// Disables code generation of the service endpoint prefix IDs defined in
// the model.
DisableGenerateServiceIDs bool
}
// Set combines all of the option functions together
func (d *CodeGenOptions) Set(optFns ...func(*CodeGenOptions)) {
for _, fn := range optFns {
fn(d)
}
}
// CodeGenModel given a endpoints model file will decode it and attempt to
// generate Go code from the model definition. Error will be returned if
// the code is unable to be generated, or decoded.
func CodeGenModel(modelFile io.Reader, outFile io.Writer, optFns ...func(*CodeGenOptions)) error {
var opts CodeGenOptions
opts.Set(optFns...)
resolver, err := DecodeModel(modelFile, func(d *DecodeModelOptions) {
*d = opts.DecodeModelOptions
})
if err != nil {
return err
}
v := struct {
Resolver
CodeGenOptions
}{
Resolver: resolver,
CodeGenOptions: opts,
}
tmpl := template.Must(template.New("tmpl").Funcs(funcMap).Parse(v3Tmpl))
if err := tmpl.ExecuteTemplate(outFile, "defaults", v); err != nil {
return fmt.Errorf("failed to execute template, %v", err)
}
return nil
}
func toSymbol(v string) string {
out := []rune{}
for _, c := range strings.Title(v) {
if !(unicode.IsNumber(c) || unicode.IsLetter(c)) {
continue
}
out = append(out, c)
}
return string(out)
}
func quoteString(v string) string {
return fmt.Sprintf("%q", v)
}
func regionConstName(p, r string) string {
return toSymbol(p) + toSymbol(r)
}
func partitionGetter(id string) string {
return fmt.Sprintf("%sPartition", toSymbol(id))
}
func partitionVarName(id string) string {
return fmt.Sprintf("%sPartition", strings.ToLower(toSymbol(id)))
}
func listPartitionNames(ps partitions) string {
names := []string{}
switch len(ps) {
case 1:
return ps[0].Name
case 2:
return fmt.Sprintf("%s and %s", ps[0].Name, ps[1].Name)
default:
for i, p := range ps {
if i == len(ps)-1 {
names = append(names, "and "+p.Name)
} else {
names = append(names, p.Name)
}
}
return strings.Join(names, ", ")
}
}
func boxedBoolIfSet(msg string, v boxedBool) string {
switch v {
case boxedTrue:
return fmt.Sprintf(msg, "boxedTrue")
case boxedFalse:
return fmt.Sprintf(msg, "boxedFalse")
default:
return ""
}
}
func stringIfSet(msg, v string) string {
if len(v) == 0 {
return ""
}
return fmt.Sprintf(msg, v)
}
func stringSliceIfSet(msg string, vs []string) string {
if len(vs) == 0 {
return ""
}
names := []string{}
for _, v := range vs {
names = append(names, `"`+v+`"`)
}
return fmt.Sprintf(msg, strings.Join(names, ","))
}
func endpointIsSet(v endpoint) bool {
return !reflect.DeepEqual(v, endpoint{})
}
func serviceSet(ps partitions) map[string]struct{} {
set := map[string]struct{}{}
for _, p := range ps {
for id := range p.Services {
set[id] = struct{}{}
}
}
return set
}
func endpointVariantSetter(variant endpointVariant) (string, error) {
if variant == 0 {
return "0", nil
}
if variant > (fipsVariant | dualStackVariant) {
return "", fmt.Errorf("unknown endpoint variant")
}
var symbols []string
if variant&fipsVariant != 0 {
symbols = append(symbols, "fipsVariant")
}
if variant&dualStackVariant != 0 {
symbols = append(symbols, "dualStackVariant")
}
v := strings.Join(symbols, "|")
return v, nil
}
func endpointKeySetter(e endpointKey) (string, error) {
var sb strings.Builder
sb.WriteString("endpointKey{\n")
sb.WriteString(fmt.Sprintf("Region: %q,\n", e.Region))
if e.Variant != 0 {
variantSetter, err := endpointVariantSetter(e.Variant)
if err != nil {
return "", err
}
sb.WriteString(fmt.Sprintf("Variant: %s,\n", variantSetter))
}
sb.WriteString("}")
return sb.String(), nil
}
func defaultKeySetter(e defaultKey) (string, error) {
var sb strings.Builder
sb.WriteString("defaultKey{\n")
if e.Variant != 0 {
variantSetter, err := endpointVariantSetter(e.Variant)
if err != nil {
return "", err
}
sb.WriteString(fmt.Sprintf("Variant: %s,\n", variantSetter))
}
sb.WriteString("}")
return sb.String(), nil
}
var funcMap = template.FuncMap{
"ToSymbol": toSymbol,
"QuoteString": quoteString,
"RegionConst": regionConstName,
"PartitionGetter": partitionGetter,
"PartitionVarName": partitionVarName,
"ListPartitionNames": listPartitionNames,
"BoxedBoolIfSet": boxedBoolIfSet,
"StringIfSet": stringIfSet,
"StringSliceIfSet": stringSliceIfSet,
"EndpointIsSet": endpointIsSet,
"ServicesSet": serviceSet,
"EndpointVariantSetter": endpointVariantSetter,
"EndpointKeySetter": endpointKeySetter,
"DefaultKeySetter": defaultKeySetter,
}
const v3Tmpl = `
{{ define "defaults" -}}
// Code generated by aws/endpoints/v3model_codegen.go. DO NOT EDIT.
package endpoints
import (
"regexp"
)
{{ template "partition consts" $.Resolver }}
{{ range $_, $partition := $.Resolver }}
{{ template "partition region consts" $partition }}
{{ end }}
{{ if not $.DisableGenerateServiceIDs -}}
{{ template "service consts" $.Resolver }}
{{- end }}
{{ template "endpoint resolvers" $.Resolver }}
{{- end }}
{{ define "partition consts" }}
// Partition identifiers
const (
{{ range $_, $p := . -}}
{{ ToSymbol $p.ID }}PartitionID = {{ QuoteString $p.ID }} // {{ $p.Name }} partition.
{{ end -}}
)
{{- end }}
{{ define "partition region consts" }}
// {{ .Name }} partition's regions.
const (
{{ range $id, $region := .Regions -}}
{{ ToSymbol $id }}RegionID = {{ QuoteString $id }} // {{ $region.Description }}.
{{ end -}}
)
{{- end }}
{{ define "service consts" }}
// Service identifiers
const (
{{ $serviceSet := ServicesSet . -}}
{{ range $id, $_ := $serviceSet -}}
{{ ToSymbol $id }}ServiceID = {{ QuoteString $id }} // {{ ToSymbol $id }}.
{{ end -}}
)
{{- end }}
{{ define "endpoint resolvers" }}
// DefaultResolver returns an Endpoint resolver that will be able
// to resolve endpoints for: {{ ListPartitionNames . }}.
//
// Use DefaultPartitions() to get the list of the default partitions.
func DefaultResolver() Resolver {
return defaultPartitions
}
// DefaultPartitions returns a list of the partitions the SDK is bundled
// with. The available partitions are: {{ ListPartitionNames . }}.
//
// partitions := endpoints.DefaultPartitions
// for _, p := range partitions {
// // ... inspect partitions
// }
func DefaultPartitions() []Partition {
return defaultPartitions.Partitions()
}
var defaultPartitions = partitions{
{{ range $_, $partition := . -}}
{{ PartitionVarName $partition.ID }},
{{ end }}
}
{{ range $_, $partition := . -}}
{{ $name := PartitionGetter $partition.ID -}}
// {{ $name }} returns the Resolver for {{ $partition.Name }}.
func {{ $name }}() Partition {
return {{ PartitionVarName $partition.ID }}.Partition()
}
var {{ PartitionVarName $partition.ID }} = {{ template "gocode Partition" $partition }}
{{ end }}
{{ end }}
{{ define "default partitions" }}
func DefaultPartitions() []Partition {
return []partition{
{{ range $_, $partition := . -}}
// {{ ToSymbol $partition.ID}}Partition(),
{{ end }}
}
}
{{ end }}
{{ define "gocode Partition" -}}
partition{
{{ StringIfSet "ID: %q,\n" .ID -}}
{{ StringIfSet "Name: %q,\n" .Name -}}
{{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}}
RegionRegex: {{ template "gocode RegionRegex" .RegionRegex }},
{{ if (gt (len .Defaults) 0) -}}
Defaults: {{ template "gocode Defaults" .Defaults -}},
{{ end -}}
Regions: {{ template "gocode Regions" .Regions }},
Services: {{ template "gocode Services" .Services }},
}
{{- end }}
{{ define "gocode RegionRegex" -}}
regionRegex{
Regexp: func() *regexp.Regexp{
reg, _ := regexp.Compile({{ QuoteString .Regexp.String }})
return reg
}(),
}
{{- end }}
{{ define "gocode Regions" -}}
regions{
{{ range $id, $region := . -}}
"{{ $id }}": {{ template "gocode Region" $region }},
{{ end -}}
}
{{- end }}
{{ define "gocode Region" -}}
region{
{{ StringIfSet "Description: %q,\n" .Description -}}
}
{{- end }}
{{ define "gocode Services" -}}
services{
{{ range $id, $service := . -}}
"{{ $id }}": {{ template "gocode Service" $service }},
{{ end }}
}
{{- end }}
{{ define "gocode Service" -}}
service{
{{ StringIfSet "PartitionEndpoint: %q,\n" .PartitionEndpoint -}}
{{ BoxedBoolIfSet "IsRegionalized: %s,\n" .IsRegionalized -}}
{{ if (gt (len .Defaults) 0) -}}
Defaults: {{ template "gocode Defaults" .Defaults -}},
{{ end -}}
{{ if .Endpoints -}}
Endpoints: {{ template "gocode Endpoints" .Endpoints }},
{{- end }}
}
{{- end }}
{{ define "gocode Defaults" -}}
endpointDefaults{
{{ range $id, $endpoint := . -}}
{{ DefaultKeySetter $id }}: {{ template "gocode Endpoint" $endpoint }},
{{ end }}
}
{{- end }}
{{ define "gocode Endpoints" -}}
serviceEndpoints{
{{ range $id, $endpoint := . -}}
{{ EndpointKeySetter $id }}: {{ template "gocode Endpoint" $endpoint }},
{{ end }}
}
{{- end }}
{{ define "gocode Endpoint" -}}
endpoint{
{{ StringIfSet "Hostname: %q,\n" .Hostname -}}
{{ StringIfSet "DNSSuffix: %q,\n" .DNSSuffix -}}
{{ StringIfSet "SSLCommonName: %q,\n" .SSLCommonName -}}
{{ StringSliceIfSet "Protocols: []string{%s},\n" .Protocols -}}
{{ StringSliceIfSet "SignatureVersions: []string{%s},\n" .SignatureVersions -}}
{{ if or .CredentialScope.Region .CredentialScope.Service -}}
CredentialScope: credentialScope{
{{ StringIfSet "Region: %q,\n" .CredentialScope.Region -}}
{{ StringIfSet "Service: %q,\n" .CredentialScope.Service -}}
},
{{- end }}
{{ BoxedBoolIfSet "Deprecated: %s,\n" .Deprecated -}}
}
{{- end }}
`
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/errors.go
================================================
package aws
import "github.com/aws/aws-sdk-go/aws/awserr"
var (
// ErrMissingRegion is an error that is returned if region configuration is
// not found.
ErrMissingRegion = awserr.New("MissingRegion", "could not find region configuration", nil)
// ErrMissingEndpoint is an error that is returned if an endpoint cannot be
// resolved for a service.
ErrMissingEndpoint = awserr.New("MissingEndpoint", "'Endpoint' configuration is required for this service", nil)
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/jsonvalue.go
================================================
package aws
// JSONValue is a representation of a grab bag type that will be marshaled
// into a json string. This type can be used just like any other map.
//
// Example:
//
// values := aws.JSONValue{
// "Foo": "Bar",
// }
// values["Baz"] = "Qux"
type JSONValue map[string]interface{}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/logger.go
================================================
package aws
import (
"log"
"os"
)
// A LogLevelType defines the level logging should be performed at. Used to instruct
// the SDK which statements should be logged.
type LogLevelType uint
// LogLevel returns the pointer to a LogLevel. Should be used to workaround
// not being able to take the address of a non-composite literal.
func LogLevel(l LogLevelType) *LogLevelType {
return &l
}
// Value returns the LogLevel value or the default value LogOff if the LogLevel
// is nil. Safe to use on nil value LogLevelTypes.
func (l *LogLevelType) Value() LogLevelType {
if l != nil {
return *l
}
return LogOff
}
// Matches returns true if the v LogLevel is enabled by this LogLevel. Should be
// used with logging sub levels. Is safe to use on nil value LogLevelTypes. If
// LogLevel is nil, will default to LogOff comparison.
func (l *LogLevelType) Matches(v LogLevelType) bool {
c := l.Value()
return c&v == v
}
// AtLeast returns true if this LogLevel is at least high enough to satisfies v.
// Is safe to use on nil value LogLevelTypes. If LogLevel is nil, will default
// to LogOff comparison.
func (l *LogLevelType) AtLeast(v LogLevelType) bool {
c := l.Value()
return c >= v
}
const (
// LogOff states that no logging should be performed by the SDK. This is the
// default state of the SDK, and should be use to disable all logging.
LogOff LogLevelType = iota * 0x1000
// LogDebug state that debug output should be logged by the SDK. This should
// be used to inspect request made and responses received.
LogDebug
)
// Debug Logging Sub Levels
const (
// LogDebugWithSigning states that the SDK should log request signing and
// presigning events. This should be used to log the signing details of
// requests for debugging. Will also enable LogDebug.
LogDebugWithSigning LogLevelType = LogDebug | (1 << iota)
// LogDebugWithHTTPBody states the SDK should log HTTP request and response
// HTTP bodys in addition to the headers and path. This should be used to
// see the body content of requests and responses made while using the SDK
// Will also enable LogDebug.
LogDebugWithHTTPBody
// LogDebugWithRequestRetries states the SDK should log when service requests will
// be retried. This should be used to log when you want to log when service
// requests are being retried. Will also enable LogDebug.
LogDebugWithRequestRetries
// LogDebugWithRequestErrors states the SDK should log when service requests fail
// to build, send, validate, or unmarshal.
LogDebugWithRequestErrors
// LogDebugWithEventStreamBody states the SDK should log EventStream
// request and response bodys. This should be used to log the EventStream
// wire unmarshaled message content of requests and responses made while
// using the SDK Will also enable LogDebug.
LogDebugWithEventStreamBody
// LogDebugWithDeprecated states the SDK should log details about deprecated functionality.
LogDebugWithDeprecated
)
// A Logger is a minimalistic interface for the SDK to log messages to. Should
// be used to provide custom logging writers for the SDK to use.
type Logger interface {
Log(...interface{})
}
// A LoggerFunc is a convenience type to convert a function taking a variadic
// list of arguments and wrap it so the Logger interface can be used.
//
// Example:
// s3.New(sess, &aws.Config{Logger: aws.LoggerFunc(func(args ...interface{}) {
// fmt.Fprintln(os.Stdout, args...)
// })})
type LoggerFunc func(...interface{})
// Log calls the wrapped function with the arguments provided
func (f LoggerFunc) Log(args ...interface{}) {
f(args...)
}
// NewDefaultLogger returns a Logger which will write log messages to stdout, and
// use same formatting runes as the stdlib log.Logger
func NewDefaultLogger() Logger {
return &defaultLogger{
logger: log.New(os.Stdout, "", log.LstdFlags),
}
}
// A defaultLogger provides a minimalistic logger satisfying the Logger interface.
type defaultLogger struct {
logger *log.Logger
}
// Log logs the parameters to the stdlib logger. See log.Println.
func (l defaultLogger) Log(args ...interface{}) {
l.logger.Println(args...)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
================================================
package request
import (
"strings"
)
func isErrConnectionReset(err error) bool {
if strings.Contains(err.Error(), "read: connection reset") {
return false
}
if strings.Contains(err.Error(), "use of closed network connection") ||
strings.Contains(err.Error(), "connection reset") ||
strings.Contains(err.Error(), "broken pipe") {
return true
}
return false
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
================================================
package request
import (
"fmt"
"strings"
)
// A Handlers provides a collection of request handlers for various
// stages of handling requests.
type Handlers struct {
Validate HandlerList
Build HandlerList
BuildStream HandlerList
Sign HandlerList
Send HandlerList
ValidateResponse HandlerList
Unmarshal HandlerList
UnmarshalStream HandlerList
UnmarshalMeta HandlerList
UnmarshalError HandlerList
Retry HandlerList
AfterRetry HandlerList
CompleteAttempt HandlerList
Complete HandlerList
}
// Copy returns a copy of this handler's lists.
func (h *Handlers) Copy() Handlers {
return Handlers{
Validate: h.Validate.copy(),
Build: h.Build.copy(),
BuildStream: h.BuildStream.copy(),
Sign: h.Sign.copy(),
Send: h.Send.copy(),
ValidateResponse: h.ValidateResponse.copy(),
Unmarshal: h.Unmarshal.copy(),
UnmarshalStream: h.UnmarshalStream.copy(),
UnmarshalError: h.UnmarshalError.copy(),
UnmarshalMeta: h.UnmarshalMeta.copy(),
Retry: h.Retry.copy(),
AfterRetry: h.AfterRetry.copy(),
CompleteAttempt: h.CompleteAttempt.copy(),
Complete: h.Complete.copy(),
}
}
// Clear removes callback functions for all handlers.
func (h *Handlers) Clear() {
h.Validate.Clear()
h.Build.Clear()
h.BuildStream.Clear()
h.Send.Clear()
h.Sign.Clear()
h.Unmarshal.Clear()
h.UnmarshalStream.Clear()
h.UnmarshalMeta.Clear()
h.UnmarshalError.Clear()
h.ValidateResponse.Clear()
h.Retry.Clear()
h.AfterRetry.Clear()
h.CompleteAttempt.Clear()
h.Complete.Clear()
}
// IsEmpty returns if there are no handlers in any of the handlerlists.
func (h *Handlers) IsEmpty() bool {
if h.Validate.Len() != 0 {
return false
}
if h.Build.Len() != 0 {
return false
}
if h.BuildStream.Len() != 0 {
return false
}
if h.Send.Len() != 0 {
return false
}
if h.Sign.Len() != 0 {
return false
}
if h.Unmarshal.Len() != 0 {
return false
}
if h.UnmarshalStream.Len() != 0 {
return false
}
if h.UnmarshalMeta.Len() != 0 {
return false
}
if h.UnmarshalError.Len() != 0 {
return false
}
if h.ValidateResponse.Len() != 0 {
return false
}
if h.Retry.Len() != 0 {
return false
}
if h.AfterRetry.Len() != 0 {
return false
}
if h.CompleteAttempt.Len() != 0 {
return false
}
if h.Complete.Len() != 0 {
return false
}
return true
}
// A HandlerListRunItem represents an entry in the HandlerList which
// is being run.
type HandlerListRunItem struct {
Index int
Handler NamedHandler
Request *Request
}
// A HandlerList manages zero or more handlers in a list.
type HandlerList struct {
list []NamedHandler
// Called after each request handler in the list is called. If set
// and the func returns true the HandlerList will continue to iterate
// over the request handlers. If false is returned the HandlerList
// will stop iterating.
//
// Should be used if extra logic to be performed between each handler
// in the list. This can be used to terminate a list's iteration
// based on a condition such as error like, HandlerListStopOnError.
// Or for logging like HandlerListLogItem.
AfterEachFn func(item HandlerListRunItem) bool
}
// A NamedHandler is a struct that contains a name and function callback.
type NamedHandler struct {
Name string
Fn func(*Request)
}
// copy creates a copy of the handler list.
func (l *HandlerList) copy() HandlerList {
n := HandlerList{
AfterEachFn: l.AfterEachFn,
}
if len(l.list) == 0 {
return n
}
n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...)
return n
}
// Clear clears the handler list.
func (l *HandlerList) Clear() {
l.list = l.list[0:0]
}
// Len returns the number of handlers in the list.
func (l *HandlerList) Len() int {
return len(l.list)
}
// PushBack pushes handler f to the back of the handler list.
func (l *HandlerList) PushBack(f func(*Request)) {
l.PushBackNamed(NamedHandler{"__anonymous", f})
}
// PushBackNamed pushes named handler f to the back of the handler list.
func (l *HandlerList) PushBackNamed(n NamedHandler) {
if cap(l.list) == 0 {
l.list = make([]NamedHandler, 0, 5)
}
l.list = append(l.list, n)
}
// PushFront pushes handler f to the front of the handler list.
func (l *HandlerList) PushFront(f func(*Request)) {
l.PushFrontNamed(NamedHandler{"__anonymous", f})
}
// PushFrontNamed pushes named handler f to the front of the handler list.
func (l *HandlerList) PushFrontNamed(n NamedHandler) {
if cap(l.list) == len(l.list) {
// Allocating new list required
l.list = append([]NamedHandler{n}, l.list...)
} else {
// Enough room to prepend into list.
l.list = append(l.list, NamedHandler{})
copy(l.list[1:], l.list)
l.list[0] = n
}
}
// Remove removes a NamedHandler n
func (l *HandlerList) Remove(n NamedHandler) {
l.RemoveByName(n.Name)
}
// RemoveByName removes a NamedHandler by name.
func (l *HandlerList) RemoveByName(name string) {
for i := 0; i < len(l.list); i++ {
m := l.list[i]
if m.Name == name {
// Shift array preventing creating new arrays
copy(l.list[i:], l.list[i+1:])
l.list[len(l.list)-1] = NamedHandler{}
l.list = l.list[:len(l.list)-1]
// decrement list so next check to length is correct
i--
}
}
}
// SwapNamed will swap out any existing handlers with the same name as the
// passed in NamedHandler returning true if handlers were swapped. False is
// returned otherwise.
func (l *HandlerList) SwapNamed(n NamedHandler) (swapped bool) {
for i := 0; i < len(l.list); i++ {
if l.list[i].Name == n.Name {
l.list[i].Fn = n.Fn
swapped = true
}
}
return swapped
}
// Swap will swap out all handlers matching the name passed in. The matched
// handlers will be swapped in. True is returned if the handlers were swapped.
func (l *HandlerList) Swap(name string, replace NamedHandler) bool {
var swapped bool
for i := 0; i < len(l.list); i++ {
if l.list[i].Name == name {
l.list[i] = replace
swapped = true
}
}
return swapped
}
// SetBackNamed will replace the named handler if it exists in the handler list.
// If the handler does not exist the handler will be added to the end of the list.
func (l *HandlerList) SetBackNamed(n NamedHandler) {
if !l.SwapNamed(n) {
l.PushBackNamed(n)
}
}
// SetFrontNamed will replace the named handler if it exists in the handler list.
// If the handler does not exist the handler will be added to the beginning of
// the list.
func (l *HandlerList) SetFrontNamed(n NamedHandler) {
if !l.SwapNamed(n) {
l.PushFrontNamed(n)
}
}
// Run executes all handlers in the list with a given request object.
func (l *HandlerList) Run(r *Request) {
for i, h := range l.list {
h.Fn(r)
item := HandlerListRunItem{
Index: i, Handler: h, Request: r,
}
if l.AfterEachFn != nil && !l.AfterEachFn(item) {
return
}
}
}
// HandlerListLogItem logs the request handler and the state of the
// request's Error value. Always returns true to continue iterating
// request handlers in a HandlerList.
func HandlerListLogItem(item HandlerListRunItem) bool {
if item.Request.Config.Logger == nil {
return true
}
item.Request.Config.Logger.Log("DEBUG: RequestHandler",
item.Index, item.Handler.Name, item.Request.Error)
return true
}
// HandlerListStopOnError returns false to stop the HandlerList iterating
// over request handlers if Request.Error is not nil. True otherwise
// to continue iterating.
func HandlerListStopOnError(item HandlerListRunItem) bool {
return item.Request.Error == nil
}
// WithAppendUserAgent will add a string to the user agent prefixed with a
// single white space.
func WithAppendUserAgent(s string) Option {
return func(r *Request) {
r.Handlers.Build.PushBack(func(r2 *Request) {
AddToUserAgent(r, s)
})
}
}
// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request
// header. If the extra parameters are provided they will be added as metadata to the
// name/version pair resulting in the following format.
// "name/version (extra0; extra1; ...)"
// The user agent part will be concatenated with this current request's user agent string.
func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) {
ua := fmt.Sprintf("%s/%s", name, version)
if len(extra) > 0 {
ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; "))
}
return func(r *Request) {
AddToUserAgent(r, ua)
}
}
// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header.
// The input string will be concatenated with the current request's user agent string.
func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) {
return func(r *Request) {
AddToUserAgent(r, s)
}
}
// WithSetRequestHeaders updates the operation request's HTTP header to contain
// the header key value pairs provided. If the header key already exists in the
// request's HTTP header set, the existing value(s) will be replaced.
func WithSetRequestHeaders(h map[string]string) Option {
return withRequestHeader(h).SetRequestHeaders
}
type withRequestHeader map[string]string
func (h withRequestHeader) SetRequestHeaders(r *Request) {
for k, v := range h {
r.HTTPRequest.Header[k] = []string{v}
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
================================================
package request
import (
"io"
"net/http"
"net/url"
)
func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
req := new(http.Request)
*req = *r
req.URL = &url.URL{}
*req.URL = *r.URL
req.Body = body
req.Header = http.Header{}
for k, v := range r.Header {
for _, vv := range v {
req.Header.Add(k, vv)
}
}
return req
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
================================================
package request
import (
"io"
"sync"
"github.com/aws/aws-sdk-go/internal/sdkio"
)
// offsetReader is a thread-safe io.ReadCloser to prevent racing
// with retrying requests
type offsetReader struct {
buf io.ReadSeeker
lock sync.Mutex
closed bool
}
func newOffsetReader(buf io.ReadSeeker, offset int64) (*offsetReader, error) {
reader := &offsetReader{}
_, err := buf.Seek(offset, sdkio.SeekStart)
if err != nil {
return nil, err
}
reader.buf = buf
return reader, nil
}
// Close will close the instance of the offset reader's access to
// the underlying io.ReadSeeker.
func (o *offsetReader) Close() error {
o.lock.Lock()
defer o.lock.Unlock()
o.closed = true
return nil
}
// Read is a thread-safe read of the underlying io.ReadSeeker
func (o *offsetReader) Read(p []byte) (int, error) {
o.lock.Lock()
defer o.lock.Unlock()
if o.closed {
return 0, io.EOF
}
return o.buf.Read(p)
}
// Seek is a thread-safe seeking operation.
func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
o.lock.Lock()
defer o.lock.Unlock()
return o.buf.Seek(offset, whence)
}
// CloseAndCopy will return a new offsetReader with a copy of the old buffer
// and close the old buffer.
func (o *offsetReader) CloseAndCopy(offset int64) (*offsetReader, error) {
if err := o.Close(); err != nil {
return nil, err
}
return newOffsetReader(o.buf, offset)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request.go
================================================
package request
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/internal/sdkio"
)
const (
// ErrCodeSerialization is the serialization error code that is received
// during protocol unmarshaling.
ErrCodeSerialization = "SerializationError"
// ErrCodeRead is an error that is returned during HTTP reads.
ErrCodeRead = "ReadError"
// ErrCodeResponseTimeout is the connection timeout error that is received
// during body reads.
ErrCodeResponseTimeout = "ResponseTimeout"
// ErrCodeInvalidPresignExpire is returned when the expire time provided to
// presign is invalid
ErrCodeInvalidPresignExpire = "InvalidPresignExpireError"
// CanceledErrorCode is the error code that will be returned by an
// API request that was canceled. Requests given a aws.Context may
// return this error when canceled.
CanceledErrorCode = "RequestCanceled"
// ErrCodeRequestError is an error preventing the SDK from continuing to
// process the request.
ErrCodeRequestError = "RequestError"
)
// A Request is the service request to be made.
type Request struct {
Config aws.Config
ClientInfo metadata.ClientInfo
Handlers Handlers
Retryer
AttemptTime time.Time
Time time.Time
Operation *Operation
HTTPRequest *http.Request
HTTPResponse *http.Response
Body io.ReadSeeker
streamingBody io.ReadCloser
BodyStart int64 // offset from beginning of Body that the request body starts
Params interface{}
Error error
Data interface{}
RequestID string
RetryCount int
Retryable *bool
RetryDelay time.Duration
NotHoist bool
SignedHeaderVals http.Header
LastSignedAt time.Time
DisableFollowRedirects bool
// Additional API error codes that should be retried. IsErrorRetryable
// will consider these codes in addition to its built in cases.
RetryErrorCodes []string
// Additional API error codes that should be retried with throttle backoff
// delay. IsErrorThrottle will consider these codes in addition to its
// built in cases.
ThrottleErrorCodes []string
// A value greater than 0 instructs the request to be signed as Presigned URL
// You should not set this field directly. Instead use Request's
// Presign or PresignRequest methods.
ExpireTime time.Duration
context aws.Context
built bool
// Need to persist an intermediate body between the input Body and HTTP
// request body because the HTTP Client's transport can maintain a reference
// to the HTTP request's body after the client has returned. This value is
// safe to use concurrently and wrap the input Body for each HTTP request.
safeBody *offsetReader
}
// An Operation is the service API operation to be made.
type Operation struct {
Name string
HTTPMethod string
HTTPPath string
*Paginator
BeforePresignFn func(r *Request) error
}
// New returns a new Request pointer for the service API operation and
// parameters.
//
// A Retryer should be provided to direct how the request is retried. If
// Retryer is nil, a default no retry value will be used. You can use
// NoOpRetryer in the Client package to disable retry behavior directly.
//
// Params is any value of input parameters to be the request payload.
// Data is pointer value to an object which the request's response
// payload will be deserialized to.
func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
if retryer == nil {
retryer = noOpRetryer{}
}
method := operation.HTTPMethod
if method == "" {
method = "POST"
}
httpReq, _ := http.NewRequest(method, "", nil)
var err error
httpReq.URL, err = url.Parse(clientInfo.Endpoint)
if err != nil {
httpReq.URL = &url.URL{}
err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
}
if len(operation.HTTPPath) != 0 {
opHTTPPath := operation.HTTPPath
var opQueryString string
if idx := strings.Index(opHTTPPath, "?"); idx >= 0 {
opQueryString = opHTTPPath[idx+1:]
opHTTPPath = opHTTPPath[:idx]
}
if strings.HasSuffix(httpReq.URL.Path, "/") && strings.HasPrefix(opHTTPPath, "/") {
opHTTPPath = opHTTPPath[1:]
}
httpReq.URL.Path += opHTTPPath
httpReq.URL.RawQuery = opQueryString
}
r := &Request{
Config: cfg,
ClientInfo: clientInfo,
Handlers: handlers.Copy(),
Retryer: retryer,
Time: time.Now(),
ExpireTime: 0,
Operation: operation,
HTTPRequest: httpReq,
Body: nil,
Params: params,
Error: err,
Data: data,
}
r.SetBufferBody([]byte{})
return r
}
// A Option is a functional option that can augment or modify a request when
// using a WithContext API operation method.
type Option func(*Request)
// WithGetResponseHeader builds a request Option which will retrieve a single
// header value from the HTTP Response. If there are multiple values for the
// header key use WithGetResponseHeaders instead to access the http.Header
// map directly. The passed in val pointer must be non-nil.
//
// This Option can be used multiple times with a single API operation.
//
// var id2, versionID string
// svc.PutObjectWithContext(ctx, params,
// request.WithGetResponseHeader("x-amz-id-2", &id2),
// request.WithGetResponseHeader("x-amz-version-id", &versionID),
// )
func WithGetResponseHeader(key string, val *string) Option {
return func(r *Request) {
r.Handlers.Complete.PushBack(func(req *Request) {
*val = req.HTTPResponse.Header.Get(key)
})
}
}
// WithGetResponseHeaders builds a request Option which will retrieve the
// headers from the HTTP response and assign them to the passed in headers
// variable. The passed in headers pointer must be non-nil.
//
// var headers http.Header
// svc.PutObjectWithContext(ctx, params, request.WithGetResponseHeaders(&headers))
func WithGetResponseHeaders(headers *http.Header) Option {
return func(r *Request) {
r.Handlers.Complete.PushBack(func(req *Request) {
*headers = req.HTTPResponse.Header
})
}
}
// WithLogLevel is a request option that will set the request to use a specific
// log level when the request is made.
//
// svc.PutObjectWithContext(ctx, params, request.WithLogLevel(aws.LogDebugWithHTTPBody)
func WithLogLevel(l aws.LogLevelType) Option {
return func(r *Request) {
r.Config.LogLevel = aws.LogLevel(l)
}
}
// ApplyOptions will apply each option to the request calling them in the order
// the were provided.
func (r *Request) ApplyOptions(opts ...Option) {
for _, opt := range opts {
opt(r)
}
}
// Context will always returns a non-nil context. If Request does not have a
// context aws.BackgroundContext will be returned.
func (r *Request) Context() aws.Context {
if r.context != nil {
return r.context
}
return aws.BackgroundContext()
}
// SetContext adds a Context to the current request that can be used to cancel
// a in-flight request. The Context value must not be nil, or this method will
// panic.
//
// Unlike http.Request.WithContext, SetContext does not return a copy of the
// Request. It is not safe to use use a single Request value for multiple
// requests. A new Request should be created for each API operation request.
//
// Go 1.6 and below:
// The http.Request's Cancel field will be set to the Done() value of
// the context. This will overwrite the Cancel field's value.
//
// Go 1.7 and above:
// The http.Request.WithContext will be used to set the context on the underlying
// http.Request. This will create a shallow copy of the http.Request. The SDK
// may create sub contexts in the future for nested requests such as retries.
func (r *Request) SetContext(ctx aws.Context) {
if ctx == nil {
panic("context cannot be nil")
}
setRequestContext(r, ctx)
}
// WillRetry returns if the request's can be retried.
func (r *Request) WillRetry() bool {
if !aws.IsReaderSeekable(r.Body) && r.HTTPRequest.Body != NoBody {
return false
}
return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
}
func fmtAttemptCount(retryCount, maxRetries int) string {
return fmt.Sprintf("attempt %v/%v", retryCount, maxRetries)
}
// ParamsFilled returns if the request's parameters have been populated
// and the parameters are valid. False is returned if no parameters are
// provided or invalid.
func (r *Request) ParamsFilled() bool {
return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid()
}
// DataFilled returns true if the request's data for response deserialization
// target has been set and is a valid. False is returned if data is not
// set, or is invalid.
func (r *Request) DataFilled() bool {
return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid()
}
// SetBufferBody will set the request's body bytes that will be sent to
// the service API.
func (r *Request) SetBufferBody(buf []byte) {
r.SetReaderBody(bytes.NewReader(buf))
}
// SetStringBody sets the body of the request to be backed by a string.
func (r *Request) SetStringBody(s string) {
r.SetReaderBody(strings.NewReader(s))
}
// SetReaderBody will set the request's body reader.
func (r *Request) SetReaderBody(reader io.ReadSeeker) {
r.Body = reader
if aws.IsReaderSeekable(reader) {
var err error
// Get the Bodies current offset so retries will start from the same
// initial position.
r.BodyStart, err = reader.Seek(0, sdkio.SeekCurrent)
if err != nil {
r.Error = awserr.New(ErrCodeSerialization,
"failed to determine start of request body", err)
return
}
}
r.ResetBody()
}
// SetStreamingBody set the reader to be used for the request that will stream
// bytes to the server. Request's Body must not be set to any reader.
func (r *Request) SetStreamingBody(reader io.ReadCloser) {
r.streamingBody = reader
r.SetReaderBody(aws.ReadSeekCloser(reader))
}
// Presign returns the request's signed URL. Error will be returned
// if the signing fails. The expire parameter is only used for presigned Amazon
// S3 API requests. All other AWS services will use a fixed expiration
// time of 15 minutes.
//
// It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
func (r *Request) Presign(expire time.Duration) (string, error) {
r = r.copy()
// Presign requires all headers be hoisted. There is no way to retrieve
// the signed headers not hoisted without this. Making the presigned URL
// useless.
r.NotHoist = false
u, _, err := getPresignedURL(r, expire)
return u, err
}
// PresignRequest behaves just like presign, with the addition of returning a
// set of headers that were signed. The expire parameter is only used for
// presigned Amazon S3 API requests. All other AWS services will use a fixed
// expiration time of 15 minutes.
//
// It is invalid to create a presigned URL with a expire duration 0 or less. An
// error is returned if expire duration is 0 or less.
//
// Returns the URL string for the API operation with signature in the query string,
// and the HTTP headers that were included in the signature. These headers must
// be included in any HTTP request made with the presigned URL.
//
// To prevent hoisting any headers to the query string set NotHoist to true on
// this Request value prior to calling PresignRequest.
func (r *Request) PresignRequest(expire time.Duration) (string, http.Header, error) {
r = r.copy()
return getPresignedURL(r, expire)
}
// IsPresigned returns true if the request represents a presigned API url.
func (r *Request) IsPresigned() bool {
return r.ExpireTime != 0
}
func getPresignedURL(r *Request, expire time.Duration) (string, http.Header, error) {
if expire <= 0 {
return "", nil, awserr.New(
ErrCodeInvalidPresignExpire,
"presigned URL requires an expire duration greater than 0",
nil,
)
}
r.ExpireTime = expire
if r.Operation.BeforePresignFn != nil {
if err := r.Operation.BeforePresignFn(r); err != nil {
return "", nil, err
}
}
if err := r.Sign(); err != nil {
return "", nil, err
}
return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil
}
const (
notRetrying = "not retrying"
)
func debugLogReqError(r *Request, stage, retryStr string, err error) {
if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
return
}
r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err))
}
// Build will build the request's object so it can be signed and sent
// to the service. Build will also validate all the request's parameters.
// Any additional build Handlers set on this request will be run
// in the order they were set.
//
// The request will only be built once. Multiple calls to build will have
// no effect.
//
// If any Validate or Build errors occur the build will stop and the error
// which occurred will be returned.
func (r *Request) Build() error {
if !r.built {
r.Handlers.Validate.Run(r)
if r.Error != nil {
debugLogReqError(r, "Validate Request", notRetrying, r.Error)
return r.Error
}
r.Handlers.Build.Run(r)
if r.Error != nil {
debugLogReqError(r, "Build Request", notRetrying, r.Error)
return r.Error
}
r.built = true
}
return r.Error
}
// Sign will sign the request, returning error if errors are encountered.
//
// Sign will build the request prior to signing. All Sign Handlers will
// be executed in the order they were set.
func (r *Request) Sign() error {
r.Build()
if r.Error != nil {
debugLogReqError(r, "Build Request", notRetrying, r.Error)
return r.Error
}
SanitizeHostForHeader(r.HTTPRequest)
r.Handlers.Sign.Run(r)
return r.Error
}
func (r *Request) getNextRequestBody() (body io.ReadCloser, err error) {
if r.streamingBody != nil {
return r.streamingBody, nil
}
if r.safeBody != nil {
r.safeBody.Close()
}
r.safeBody, err = newOffsetReader(r.Body, r.BodyStart)
if err != nil {
return nil, awserr.New(ErrCodeSerialization,
"failed to get next request body reader", err)
}
// Go 1.8 tightened and clarified the rules code needs to use when building
// requests with the http package. Go 1.8 removed the automatic detection
// of if the Request.Body was empty, or actually had bytes in it. The SDK
// always sets the Request.Body even if it is empty and should not actually
// be sent. This is incorrect.
//
// Go 1.8 did add a http.NoBody value that the SDK can use to tell the http
// client that the request really should be sent without a body. The
// Request.Body cannot be set to nil, which is preferable, because the
// field is exported and could introduce nil pointer dereferences for users
// of the SDK if they used that field.
//
// Related golang/go#18257
l, err := aws.SeekerLen(r.Body)
if err != nil {
return nil, awserr.New(ErrCodeSerialization,
"failed to compute request body size", err)
}
if l == 0 {
body = NoBody
} else if l > 0 {
body = r.safeBody
} else {
// Hack to prevent sending bodies for methods where the body
// should be ignored by the server. Sending bodies on these
// methods without an associated ContentLength will cause the
// request to socket timeout because the server does not handle
// Transfer-Encoding: chunked bodies for these methods.
//
// This would only happen if a aws.ReaderSeekerCloser was used with
// a io.Reader that was not also an io.Seeker, or did not implement
// Len() method.
switch r.Operation.HTTPMethod {
case "GET", "HEAD", "DELETE":
body = NoBody
default:
body = r.safeBody
}
}
return body, nil
}
// GetBody will return an io.ReadSeeker of the Request's underlying
// input body with a concurrency safe wrapper.
func (r *Request) GetBody() io.ReadSeeker {
return r.safeBody
}
// Send will send the request, returning error if errors are encountered.
//
// Send will sign the request prior to sending. All Send Handlers will
// be executed in the order they were set.
//
// Canceling a request is non-deterministic. If a request has been canceled,
// then the transport will choose, randomly, one of the state channels during
// reads or getting the connection.
//
// readLoop() and getConn(req *Request, cm connectMethod)
// https://github.com/golang/go/blob/master/src/net/http/transport.go
//
// Send will not close the request.Request's body.
func (r *Request) Send() error {
defer func() {
// Ensure a non-nil HTTPResponse parameter is set to ensure handlers
// checking for HTTPResponse values, don't fail.
if r.HTTPResponse == nil {
r.HTTPResponse = &http.Response{
Header: http.Header{},
Body: ioutil.NopCloser(&bytes.Buffer{}),
}
}
// Regardless of success or failure of the request trigger the Complete
// request handlers.
r.Handlers.Complete.Run(r)
}()
if err := r.Error; err != nil {
return err
}
for {
r.Error = nil
r.AttemptTime = time.Now()
if err := r.Sign(); err != nil {
debugLogReqError(r, "Sign Request", notRetrying, err)
return err
}
if err := r.sendRequest(); err == nil {
return nil
}
r.Handlers.Retry.Run(r)
r.Handlers.AfterRetry.Run(r)
if r.Error != nil || !aws.BoolValue(r.Retryable) {
return r.Error
}
if err := r.prepareRetry(); err != nil {
r.Error = err
return err
}
}
}
func (r *Request) prepareRetry() error {
if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
}
// The previous http.Request will have a reference to the r.Body
// and the HTTP Client's Transport may still be reading from
// the request's body even though the Client's Do returned.
r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
r.ResetBody()
if err := r.Error; err != nil {
return awserr.New(ErrCodeSerialization,
"failed to prepare body for retry", err)
}
// Closing response body to ensure that no response body is leaked
// between retry attempts.
if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
r.HTTPResponse.Body.Close()
}
return nil
}
func (r *Request) sendRequest() (sendErr error) {
defer r.Handlers.CompleteAttempt.Run(r)
r.Retryable = nil
r.Handlers.Send.Run(r)
if r.Error != nil {
debugLogReqError(r, "Send Request",
fmtAttemptCount(r.RetryCount, r.MaxRetries()),
r.Error)
return r.Error
}
r.Handlers.UnmarshalMeta.Run(r)
r.Handlers.ValidateResponse.Run(r)
if r.Error != nil {
r.Handlers.UnmarshalError.Run(r)
debugLogReqError(r, "Validate Response",
fmtAttemptCount(r.RetryCount, r.MaxRetries()),
r.Error)
return r.Error
}
r.Handlers.Unmarshal.Run(r)
if r.Error != nil {
debugLogReqError(r, "Unmarshal Response",
fmtAttemptCount(r.RetryCount, r.MaxRetries()),
r.Error)
return r.Error
}
return nil
}
// copy will copy a request which will allow for local manipulation of the
// request.
func (r *Request) copy() *Request {
req := &Request{}
*req = *r
req.Handlers = r.Handlers.Copy()
op := *r.Operation
req.Operation = &op
return req
}
// AddToUserAgent adds the string to the end of the request's current user agent.
func AddToUserAgent(r *Request, s string) {
curUA := r.HTTPRequest.Header.Get("User-Agent")
if len(curUA) > 0 {
s = curUA + " " + s
}
r.HTTPRequest.Header.Set("User-Agent", s)
}
// SanitizeHostForHeader removes default port from host and updates request.Host
func SanitizeHostForHeader(r *http.Request) {
host := getHost(r)
port := portOnly(host)
if port != "" && isDefaultPort(r.URL.Scheme, port) {
r.Host = stripPort(host)
}
}
// Returns host from request
func getHost(r *http.Request) string {
if r.Host != "" {
return r.Host
}
if r.URL == nil {
return ""
}
return r.URL.Host
}
// Hostname returns u.Host, without any port number.
//
// If Host is an IPv6 literal with a port number, Hostname returns the
// IPv6 literal without the square brackets. IPv6 literals may include
// a zone identifier.
//
// Copied from the Go 1.8 standard library (net/url)
func stripPort(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return hostport
}
if i := strings.IndexByte(hostport, ']'); i != -1 {
return strings.TrimPrefix(hostport[:i], "[")
}
return hostport[:colon]
}
// Port returns the port part of u.Host, without the leading colon.
// If u.Host doesn't contain a port, Port returns an empty string.
//
// Copied from the Go 1.8 standard library (net/url)
func portOnly(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return ""
}
if i := strings.Index(hostport, "]:"); i != -1 {
return hostport[i+len("]:"):]
}
if strings.Contains(hostport, "]") {
return ""
}
return hostport[colon+len(":"):]
}
// Returns true if the specified URI is using the standard port
// (i.e. port 80 for HTTP URIs or 443 for HTTPS URIs)
func isDefaultPort(scheme, port string) bool {
if port == "" {
return true
}
lowerCaseScheme := strings.ToLower(scheme)
if (lowerCaseScheme == "http" && port == "80") || (lowerCaseScheme == "https" && port == "443") {
return true
}
return false
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
================================================
//go:build !go1.8
// +build !go1.8
package request
import "io"
// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
// and Close always returns nil. It can be used in an outgoing client
// request to explicitly signal that a request has zero bytes.
// An alternative, however, is to simply set Request.Body to nil.
//
// Copy of Go 1.8 NoBody type from net/http/http.go
type noBody struct{}
func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
func (noBody) Close() error { return nil }
func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
// NoBody is an empty reader that will trigger the Go HTTP client to not include
// and body in the HTTP request.
var NoBody = noBody{}
// ResetBody rewinds the request body back to its starting position, and
// sets the HTTP Request body reference. When the body is read prior
// to being sent in the HTTP request it will need to be rewound.
//
// ResetBody will automatically be called by the SDK's build handler, but if
// the request is being used directly ResetBody must be called before the request
// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically
// call ResetBody.
func (r *Request) ResetBody() {
body, err := r.getNextRequestBody()
if err != nil {
r.Error = err
return
}
r.HTTPRequest.Body = body
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
================================================
//go:build go1.8
// +build go1.8
package request
import (
"net/http"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// NoBody is a http.NoBody reader instructing Go HTTP client to not include
// and body in the HTTP request.
var NoBody = http.NoBody
// ResetBody rewinds the request body back to its starting position, and
// sets the HTTP Request body reference. When the body is read prior
// to being sent in the HTTP request it will need to be rewound.
//
// ResetBody will automatically be called by the SDK's build handler, but if
// the request is being used directly ResetBody must be called before the request
// is Sent. SetStringBody, SetBufferBody, and SetReaderBody will automatically
// call ResetBody.
//
// Will also set the Go 1.8's http.Request.GetBody member to allow retrying
// PUT/POST redirects.
func (r *Request) ResetBody() {
body, err := r.getNextRequestBody()
if err != nil {
r.Error = awserr.New(ErrCodeSerialization,
"failed to reset request body", err)
return
}
r.HTTPRequest.Body = body
r.HTTPRequest.GetBody = r.getNextRequestBody
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
================================================
//go:build go1.7
// +build go1.7
package request
import "github.com/aws/aws-sdk-go/aws"
// setContext updates the Request to use the passed in context for cancellation.
// Context will also be used for request retry delay.
//
// Creates shallow copy of the http.Request with the WithContext method.
func setRequestContext(r *Request, ctx aws.Context) {
r.context = ctx
r.HTTPRequest = r.HTTPRequest.WithContext(ctx)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go
================================================
//go:build !go1.7
// +build !go1.7
package request
import "github.com/aws/aws-sdk-go/aws"
// setContext updates the Request to use the passed in context for cancellation.
// Context will also be used for request retry delay.
//
// Creates shallow copy of the http.Request with the WithContext method.
func setRequestContext(r *Request, ctx aws.Context) {
r.context = ctx
r.HTTPRequest.Cancel = ctx.Done()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
================================================
package request
import (
"reflect"
"sync/atomic"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
// A Pagination provides paginating of SDK API operations which are paginatable.
// Generally you should not use this type directly, but use the "Pages" API
// operations method to automatically perform pagination for you. Such as,
// "S3.ListObjectsPages", and "S3.ListObjectsPagesWithContext" methods.
//
// Pagination differs from a Paginator type in that pagination is the type that
// does the pagination between API operations, and Paginator defines the
// configuration that will be used per page request.
//
// for p.Next() {
// data := p.Page().(*s3.ListObjectsOutput)
// // process the page's data
// // ...
// // break out of loop to stop fetching additional pages
// }
//
// return p.Err()
//
// See service client API operation Pages methods for examples how the SDK will
// use the Pagination type.
type Pagination struct {
// Function to return a Request value for each pagination request.
// Any configuration or handlers that need to be applied to the request
// prior to getting the next page should be done here before the request
// returned.
//
// NewRequest should always be built from the same API operations. It is
// undefined if different API operations are returned on subsequent calls.
NewRequest func() (*Request, error)
// EndPageOnSameToken, when enabled, will allow the paginator to stop on
// token that are the same as its previous tokens.
EndPageOnSameToken bool
started bool
prevTokens []interface{}
nextTokens []interface{}
err error
curPage interface{}
}
// HasNextPage will return true if Pagination is able to determine that the API
// operation has additional pages. False will be returned if there are no more
// pages remaining.
//
// Will always return true if Next has not been called yet.
func (p *Pagination) HasNextPage() bool {
if !p.started {
return true
}
hasNextPage := len(p.nextTokens) != 0
if p.EndPageOnSameToken {
return hasNextPage && !awsutil.DeepEqual(p.nextTokens, p.prevTokens)
}
return hasNextPage
}
// Err returns the error Pagination encountered when retrieving the next page.
func (p *Pagination) Err() error {
return p.err
}
// Page returns the current page. Page should only be called after a successful
// call to Next. It is undefined what Page will return if Page is called after
// Next returns false.
func (p *Pagination) Page() interface{} {
return p.curPage
}
// Next will attempt to retrieve the next page for the API operation. When a page
// is retrieved true will be returned. If the page cannot be retrieved, or there
// are no more pages false will be returned.
//
// Use the Page method to retrieve the current page data. The data will need
// to be cast to the API operation's output type.
//
// Use the Err method to determine if an error occurred if Page returns false.
func (p *Pagination) Next() bool {
if !p.HasNextPage() {
return false
}
req, err := p.NewRequest()
if err != nil {
p.err = err
return false
}
if p.started {
for i, intok := range req.Operation.InputTokens {
awsutil.SetValueAtPath(req.Params, intok, p.nextTokens[i])
}
}
p.started = true
err = req.Send()
if err != nil {
p.err = err
return false
}
p.prevTokens = p.nextTokens
p.nextTokens = req.nextPageTokens()
p.curPage = req.Data
return true
}
// A Paginator is the configuration data that defines how an API operation
// should be paginated. This type is used by the API service models to define
// the generated pagination config for service APIs.
//
// The Pagination type is what provides iterating between pages of an API. It
// is only used to store the token metadata the SDK should use for performing
// pagination.
type Paginator struct {
InputTokens []string
OutputTokens []string
LimitToken string
TruncationToken string
}
// nextPageTokens returns the tokens to use when asking for the next page of data.
func (r *Request) nextPageTokens() []interface{} {
if r.Operation.Paginator == nil {
return nil
}
if r.Operation.TruncationToken != "" {
tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken)
if len(tr) == 0 {
return nil
}
switch v := tr[0].(type) {
case *bool:
if !aws.BoolValue(v) {
return nil
}
case bool:
if !v {
return nil
}
}
}
tokens := []interface{}{}
tokenAdded := false
for _, outToken := range r.Operation.OutputTokens {
vs, _ := awsutil.ValuesAtPath(r.Data, outToken)
if len(vs) == 0 {
tokens = append(tokens, nil)
continue
}
v := vs[0]
switch tv := v.(type) {
case *string:
if len(aws.StringValue(tv)) == 0 {
tokens = append(tokens, nil)
continue
}
case string:
if len(tv) == 0 {
tokens = append(tokens, nil)
continue
}
}
tokenAdded = true
tokens = append(tokens, v)
}
if !tokenAdded {
return nil
}
return tokens
}
// Ensure a deprecated item is only logged once instead of each time its used.
func logDeprecatedf(logger aws.Logger, flag *int32, msg string) {
if logger == nil {
return
}
if atomic.CompareAndSwapInt32(flag, 0, 1) {
logger.Log(msg)
}
}
var (
logDeprecatedHasNextPage int32
logDeprecatedNextPage int32
logDeprecatedEachPage int32
)
// HasNextPage returns true if this request has more pages of data available.
//
// Deprecated Use Pagination type for configurable pagination of API operations
func (r *Request) HasNextPage() bool {
logDeprecatedf(r.Config.Logger, &logDeprecatedHasNextPage,
"Request.HasNextPage deprecated. Use Pagination type for configurable pagination of API operations")
return len(r.nextPageTokens()) > 0
}
// NextPage returns a new Request that can be executed to return the next
// page of result data. Call .Send() on this request to execute it.
//
// Deprecated Use Pagination type for configurable pagination of API operations
func (r *Request) NextPage() *Request {
logDeprecatedf(r.Config.Logger, &logDeprecatedNextPage,
"Request.NextPage deprecated. Use Pagination type for configurable pagination of API operations")
tokens := r.nextPageTokens()
if len(tokens) == 0 {
return nil
}
data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
for i, intok := range nr.Operation.InputTokens {
awsutil.SetValueAtPath(nr.Params, intok, tokens[i])
}
return nr
}
// EachPage iterates over each page of a paginated request object. The fn
// parameter should be a function with the following sample signature:
//
// func(page *T, lastPage bool) bool {
// return true // return false to stop iterating
// }
//
// Where "T" is the structure type matching the output structure of the given
// operation. For example, a request object generated by
// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
// as the structure "T". The lastPage value represents whether the page is
// the last page of data or not. The return value of this function should
// return true to keep iterating or false to stop.
//
// Deprecated Use Pagination type for configurable pagination of API operations
func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
logDeprecatedf(r.Config.Logger, &logDeprecatedEachPage,
"Request.EachPage deprecated. Use Pagination type for configurable pagination of API operations")
for page := r; page != nil; page = page.NextPage() {
if err := page.Send(); err != nil {
return err
}
if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage {
return page.Error
}
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
================================================
package request
import (
"net"
"net/url"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// Retryer provides the interface drive the SDK's request retry behavior. The
// Retryer implementation is responsible for implementing exponential backoff,
// and determine if a request API error should be retried.
//
// client.DefaultRetryer is the SDK's default implementation of the Retryer. It
// uses the Request.IsErrorRetryable and Request.IsErrorThrottle methods to
// determine if the request is retried.
type Retryer interface {
// RetryRules return the retry delay that should be used by the SDK before
// making another request attempt for the failed request.
RetryRules(*Request) time.Duration
// ShouldRetry returns if the failed request is retryable.
//
// Implementations may consider request attempt count when determining if a
// request is retryable, but the SDK will use MaxRetries to limit the
// number of attempts a request are made.
ShouldRetry(*Request) bool
// MaxRetries is the number of times a request may be retried before
// failing.
MaxRetries() int
}
// WithRetryer sets a Retryer value to the given Config returning the Config
// value for chaining. The value must not be nil.
func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
if retryer == nil {
if cfg.Logger != nil {
cfg.Logger.Log("ERROR: Request.WithRetryer called with nil retryer. Replacing with retry disabled Retryer.")
}
retryer = noOpRetryer{}
}
cfg.Retryer = retryer
return cfg
}
// noOpRetryer is a internal no op retryer used when a request is created
// without a retryer.
//
// Provides a retryer that performs no retries.
// It should be used when we do not want retries to be performed.
type noOpRetryer struct{}
// MaxRetries returns the number of maximum returns the service will use to make
// an individual API; For NoOpRetryer the MaxRetries will always be zero.
func (d noOpRetryer) MaxRetries() int {
return 0
}
// ShouldRetry will always return false for NoOpRetryer, as it should never retry.
func (d noOpRetryer) ShouldRetry(_ *Request) bool {
return false
}
// RetryRules returns the delay duration before retrying this request again;
// since NoOpRetryer does not retry, RetryRules always returns 0.
func (d noOpRetryer) RetryRules(_ *Request) time.Duration {
return 0
}
// retryableCodes is a collection of service response codes which are retry-able
// without any further action.
var retryableCodes = map[string]struct{}{
ErrCodeRequestError: {},
"RequestTimeout": {},
ErrCodeResponseTimeout: {},
"RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout
}
var throttleCodes = map[string]struct{}{
"ProvisionedThroughputExceededException": {},
"ThrottledException": {}, // SNS, XRay, ResourceGroupsTagging API
"Throttling": {},
"ThrottlingException": {},
"RequestLimitExceeded": {},
"RequestThrottled": {},
"RequestThrottledException": {},
"TooManyRequestsException": {}, // Lambda functions
"PriorRequestNotComplete": {}, // Route53
"TransactionInProgressException": {},
"EC2ThrottledException": {}, // EC2
}
// credsExpiredCodes is a collection of error codes which signify the credentials
// need to be refreshed. Expired tokens require refreshing of credentials, and
// resigning before the request can be retried.
var credsExpiredCodes = map[string]struct{}{
"ExpiredToken": {},
"ExpiredTokenException": {},
"RequestExpired": {}, // EC2 Only
}
func isCodeThrottle(code string) bool {
_, ok := throttleCodes[code]
return ok
}
func isCodeRetryable(code string) bool {
if _, ok := retryableCodes[code]; ok {
return true
}
return isCodeExpiredCreds(code)
}
func isCodeExpiredCreds(code string) bool {
_, ok := credsExpiredCodes[code]
return ok
}
var validParentCodes = map[string]struct{}{
ErrCodeSerialization: {},
ErrCodeRead: {},
}
func isNestedErrorRetryable(parentErr awserr.Error) bool {
if parentErr == nil {
return false
}
if _, ok := validParentCodes[parentErr.Code()]; !ok {
return false
}
err := parentErr.OrigErr()
if err == nil {
return false
}
if aerr, ok := err.(awserr.Error); ok {
return isCodeRetryable(aerr.Code())
}
if t, ok := err.(temporary); ok {
return t.Temporary() || isErrConnectionReset(err)
}
return isErrConnectionReset(err)
}
// IsErrorRetryable returns whether the error is retryable, based on its Code.
// Returns false if error is nil.
func IsErrorRetryable(err error) bool {
if err == nil {
return false
}
return shouldRetryError(err)
}
type temporary interface {
Temporary() bool
}
func shouldRetryError(origErr error) bool {
switch err := origErr.(type) {
case awserr.Error:
if err.Code() == CanceledErrorCode {
return false
}
if isNestedErrorRetryable(err) {
return true
}
origErr := err.OrigErr()
var shouldRetry bool
if origErr != nil {
shouldRetry = shouldRetryError(origErr)
if err.Code() == ErrCodeRequestError && !shouldRetry {
return false
}
}
if isCodeRetryable(err.Code()) {
return true
}
return shouldRetry
case *url.Error:
if strings.Contains(err.Error(), "connection refused") {
// Refused connections should be retried as the service may not yet
// be running on the port. Go TCP dial considers refused
// connections as not temporary.
return true
}
// *url.Error only implements Temporary after golang 1.6 but since
// url.Error only wraps the error:
return shouldRetryError(err.Err)
case temporary:
if netErr, ok := err.(*net.OpError); ok && netErr.Op == "dial" {
return true
}
// If the error is temporary, we want to allow continuation of the
// retry process
return err.Temporary() || isErrConnectionReset(origErr)
case nil:
// `awserr.Error.OrigErr()` can be nil, meaning there was an error but
// because we don't know the cause, it is marked as retryable. See
// TestRequest4xxUnretryable for an example.
return true
default:
switch err.Error() {
case "net/http: request canceled",
"net/http: request canceled while waiting for connection":
// known 1.5 error case when an http request is cancelled
return false
}
// here we don't know the error; so we allow a retry.
return true
}
}
// IsErrorThrottle returns whether the error is to be throttled based on its code.
// Returns false if error is nil.
func IsErrorThrottle(err error) bool {
if aerr, ok := err.(awserr.Error); ok && aerr != nil {
return isCodeThrottle(aerr.Code())
}
return false
}
// IsErrorExpiredCreds returns whether the error code is a credential expiry
// error. Returns false if error is nil.
func IsErrorExpiredCreds(err error) bool {
if aerr, ok := err.(awserr.Error); ok && aerr != nil {
return isCodeExpiredCreds(aerr.Code())
}
return false
}
// IsErrorRetryable returns whether the error is retryable, based on its Code.
// Returns false if the request has no Error set.
//
// Alias for the utility function IsErrorRetryable
func (r *Request) IsErrorRetryable() bool {
if isErrCode(r.Error, r.RetryErrorCodes) {
return true
}
// HTTP response status code 501 should not be retried.
// 501 represents Not Implemented which means the request method is not
// supported by the server and cannot be handled.
if r.HTTPResponse != nil {
// HTTP response status code 500 represents internal server error and
// should be retried without any throttle.
if r.HTTPResponse.StatusCode == 500 {
return true
}
}
return IsErrorRetryable(r.Error)
}
// IsErrorThrottle returns whether the error is to be throttled based on its
// code. Returns false if the request has no Error set.
//
// Alias for the utility function IsErrorThrottle
func (r *Request) IsErrorThrottle() bool {
if isErrCode(r.Error, r.ThrottleErrorCodes) {
return true
}
if r.HTTPResponse != nil {
switch r.HTTPResponse.StatusCode {
case
429, // error caused due to too many requests
502, // Bad Gateway error should be throttled
503, // caused when service is unavailable
504: // error occurred due to gateway timeout
return true
}
}
return IsErrorThrottle(r.Error)
}
func isErrCode(err error, codes []string) bool {
if aerr, ok := err.(awserr.Error); ok && aerr != nil {
for _, code := range codes {
if code == aerr.Code() {
return true
}
}
}
return false
}
// IsErrorExpired returns whether the error code is a credential expiry error.
// Returns false if the request has no Error set.
//
// Alias for the utility function IsErrorExpiredCreds
func (r *Request) IsErrorExpired() bool {
return IsErrorExpiredCreds(r.Error)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go
================================================
package request
import (
"io"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
)
var timeoutErr = awserr.New(
ErrCodeResponseTimeout,
"read on body has reached the timeout limit",
nil,
)
type readResult struct {
n int
err error
}
// timeoutReadCloser will handle body reads that take too long.
// We will return a ErrReadTimeout error if a timeout occurs.
type timeoutReadCloser struct {
reader io.ReadCloser
duration time.Duration
}
// Read will spin off a goroutine to call the reader's Read method. We will
// select on the timer's channel or the read's channel. Whoever completes first
// will be returned.
func (r *timeoutReadCloser) Read(b []byte) (int, error) {
timer := time.NewTimer(r.duration)
c := make(chan readResult, 1)
go func() {
n, err := r.reader.Read(b)
timer.Stop()
c <- readResult{n: n, err: err}
}()
select {
case data := <-c:
return data.n, data.err
case <-timer.C:
return 0, timeoutErr
}
}
func (r *timeoutReadCloser) Close() error {
return r.reader.Close()
}
const (
// HandlerResponseTimeout is what we use to signify the name of the
// response timeout handler.
HandlerResponseTimeout = "ResponseTimeoutHandler"
)
// adaptToResponseTimeoutError is a handler that will replace any top level error
// to a ErrCodeResponseTimeout, if its child is that.
func adaptToResponseTimeoutError(req *Request) {
if err, ok := req.Error.(awserr.Error); ok {
aerr, ok := err.OrigErr().(awserr.Error)
if ok && aerr.Code() == ErrCodeResponseTimeout {
req.Error = aerr
}
}
}
// WithResponseReadTimeout is a request option that will wrap the body in a timeout read closer.
// This will allow for per read timeouts. If a timeout occurred, we will return the
// ErrCodeResponseTimeout.
//
// svc.PutObjectWithContext(ctx, params, request.WithTimeoutReadCloser(30 * time.Second)
func WithResponseReadTimeout(duration time.Duration) Option {
return func(r *Request) {
var timeoutHandler = NamedHandler{
HandlerResponseTimeout,
func(req *Request) {
req.HTTPResponse.Body = &timeoutReadCloser{
reader: req.HTTPResponse.Body,
duration: duration,
}
}}
// remove the handler so we are not stomping over any new durations.
r.Handlers.Send.RemoveByName(HandlerResponseTimeout)
r.Handlers.Send.PushBackNamed(timeoutHandler)
r.Handlers.Unmarshal.PushBack(adaptToResponseTimeoutError)
r.Handlers.UnmarshalError.PushBack(adaptToResponseTimeoutError)
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
================================================
package request
import (
"bytes"
"fmt"
"github.com/aws/aws-sdk-go/aws/awserr"
)
const (
// InvalidParameterErrCode is the error code for invalid parameters errors
InvalidParameterErrCode = "InvalidParameter"
// ParamRequiredErrCode is the error code for required parameter errors
ParamRequiredErrCode = "ParamRequiredError"
// ParamMinValueErrCode is the error code for fields with too low of a
// number value.
ParamMinValueErrCode = "ParamMinValueError"
// ParamMinLenErrCode is the error code for fields without enough elements.
ParamMinLenErrCode = "ParamMinLenError"
// ParamMaxLenErrCode is the error code for value being too long.
ParamMaxLenErrCode = "ParamMaxLenError"
// ParamFormatErrCode is the error code for a field with invalid
// format or characters.
ParamFormatErrCode = "ParamFormatInvalidError"
)
// Validator provides a way for types to perform validation logic on their
// input values that external code can use to determine if a type's values
// are valid.
type Validator interface {
Validate() error
}
// An ErrInvalidParams provides wrapping of invalid parameter errors found when
// validating API operation input parameters.
type ErrInvalidParams struct {
// Context is the base context of the invalid parameter group.
Context string
errs []ErrInvalidParam
}
// Add adds a new invalid parameter error to the collection of invalid
// parameters. The context of the invalid parameter will be updated to reflect
// this collection.
func (e *ErrInvalidParams) Add(err ErrInvalidParam) {
err.SetContext(e.Context)
e.errs = append(e.errs, err)
}
// AddNested adds the invalid parameter errors from another ErrInvalidParams
// value into this collection. The nested errors will have their nested context
// updated and base context to reflect the merging.
//
// Use for nested validations errors.
func (e *ErrInvalidParams) AddNested(nestedCtx string, nested ErrInvalidParams) {
for _, err := range nested.errs {
err.SetContext(e.Context)
err.AddNestedContext(nestedCtx)
e.errs = append(e.errs, err)
}
}
// Len returns the number of invalid parameter errors
func (e ErrInvalidParams) Len() int {
return len(e.errs)
}
// Code returns the code of the error
func (e ErrInvalidParams) Code() string {
return InvalidParameterErrCode
}
// Message returns the message of the error
func (e ErrInvalidParams) Message() string {
return fmt.Sprintf("%d validation error(s) found.", len(e.errs))
}
// Error returns the string formatted form of the invalid parameters.
func (e ErrInvalidParams) Error() string {
w := &bytes.Buffer{}
fmt.Fprintf(w, "%s: %s\n", e.Code(), e.Message())
for _, err := range e.errs {
fmt.Fprintf(w, "- %s\n", err.Message())
}
return w.String()
}
// OrigErr returns the invalid parameters as a awserr.BatchedErrors value
func (e ErrInvalidParams) OrigErr() error {
return awserr.NewBatchError(
InvalidParameterErrCode, e.Message(), e.OrigErrs())
}
// OrigErrs returns a slice of the invalid parameters
func (e ErrInvalidParams) OrigErrs() []error {
errs := make([]error, len(e.errs))
for i := 0; i < len(errs); i++ {
errs[i] = e.errs[i]
}
return errs
}
// An ErrInvalidParam represents an invalid parameter error type.
type ErrInvalidParam interface {
awserr.Error
// Field name the error occurred on.
Field() string
// SetContext updates the context of the error.
SetContext(string)
// AddNestedContext updates the error's context to include a nested level.
AddNestedContext(string)
}
type errInvalidParam struct {
context string
nestedContext string
field string
code string
msg string
}
// Code returns the error code for the type of invalid parameter.
func (e *errInvalidParam) Code() string {
return e.code
}
// Message returns the reason the parameter was invalid, and its context.
func (e *errInvalidParam) Message() string {
return fmt.Sprintf("%s, %s.", e.msg, e.Field())
}
// Error returns the string version of the invalid parameter error.
func (e *errInvalidParam) Error() string {
return fmt.Sprintf("%s: %s", e.code, e.Message())
}
// OrigErr returns nil, Implemented for awserr.Error interface.
func (e *errInvalidParam) OrigErr() error {
return nil
}
// Field Returns the field and context the error occurred.
func (e *errInvalidParam) Field() string {
field := e.context
if len(field) > 0 {
field += "."
}
if len(e.nestedContext) > 0 {
field += fmt.Sprintf("%s.", e.nestedContext)
}
field += e.field
return field
}
// SetContext updates the base context of the error.
func (e *errInvalidParam) SetContext(ctx string) {
e.context = ctx
}
// AddNestedContext prepends a context to the field's path.
func (e *errInvalidParam) AddNestedContext(ctx string) {
if len(e.nestedContext) == 0 {
e.nestedContext = ctx
} else {
e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext)
}
}
// An ErrParamRequired represents an required parameter error.
type ErrParamRequired struct {
errInvalidParam
}
// NewErrParamRequired creates a new required parameter error.
func NewErrParamRequired(field string) *ErrParamRequired {
return &ErrParamRequired{
errInvalidParam{
code: ParamRequiredErrCode,
field: field,
msg: fmt.Sprintf("missing required field"),
},
}
}
// An ErrParamMinValue represents a minimum value parameter error.
type ErrParamMinValue struct {
errInvalidParam
min float64
}
// NewErrParamMinValue creates a new minimum value parameter error.
func NewErrParamMinValue(field string, min float64) *ErrParamMinValue {
return &ErrParamMinValue{
errInvalidParam: errInvalidParam{
code: ParamMinValueErrCode,
field: field,
msg: fmt.Sprintf("minimum field value of %v", min),
},
min: min,
}
}
// MinValue returns the field's require minimum value.
//
// float64 is returned for both int and float min values.
func (e *ErrParamMinValue) MinValue() float64 {
return e.min
}
// An ErrParamMinLen represents a minimum length parameter error.
type ErrParamMinLen struct {
errInvalidParam
min int
}
// NewErrParamMinLen creates a new minimum length parameter error.
func NewErrParamMinLen(field string, min int) *ErrParamMinLen {
return &ErrParamMinLen{
errInvalidParam: errInvalidParam{
code: ParamMinLenErrCode,
field: field,
msg: fmt.Sprintf("minimum field size of %v", min),
},
min: min,
}
}
// MinLen returns the field's required minimum length.
func (e *ErrParamMinLen) MinLen() int {
return e.min
}
// An ErrParamMaxLen represents a maximum length parameter error.
type ErrParamMaxLen struct {
errInvalidParam
max int
}
// NewErrParamMaxLen creates a new maximum length parameter error.
func NewErrParamMaxLen(field string, max int, value string) *ErrParamMaxLen {
return &ErrParamMaxLen{
errInvalidParam: errInvalidParam{
code: ParamMaxLenErrCode,
field: field,
msg: fmt.Sprintf("maximum size of %v, %v", max, value),
},
max: max,
}
}
// MaxLen returns the field's required minimum length.
func (e *ErrParamMaxLen) MaxLen() int {
return e.max
}
// An ErrParamFormat represents a invalid format parameter error.
type ErrParamFormat struct {
errInvalidParam
format string
}
// NewErrParamFormat creates a new invalid format parameter error.
func NewErrParamFormat(field string, format, value string) *ErrParamFormat {
return &ErrParamFormat{
errInvalidParam: errInvalidParam{
code: ParamFormatErrCode,
field: field,
msg: fmt.Sprintf("format %v, %v", format, value),
},
format: format,
}
}
// Format returns the field's required format.
func (e *ErrParamFormat) Format() string {
return e.format
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
================================================
package request
import (
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/awsutil"
)
// WaiterResourceNotReadyErrorCode is the error code returned by a waiter when
// the waiter's max attempts have been exhausted.
const WaiterResourceNotReadyErrorCode = "ResourceNotReady"
// A WaiterOption is a function that will update the Waiter value's fields to
// configure the waiter.
type WaiterOption func(*Waiter)
// WithWaiterMaxAttempts returns the maximum number of times the waiter should
// attempt to check the resource for the target state.
func WithWaiterMaxAttempts(max int) WaiterOption {
return func(w *Waiter) {
w.MaxAttempts = max
}
}
// WaiterDelay will return a delay the waiter should pause between attempts to
// check the resource state. The passed in attempt is the number of times the
// Waiter has checked the resource state.
//
// Attempt is the number of attempts the Waiter has made checking the resource
// state.
type WaiterDelay func(attempt int) time.Duration
// ConstantWaiterDelay returns a WaiterDelay that will always return a constant
// delay the waiter should use between attempts. It ignores the number of
// attempts made.
func ConstantWaiterDelay(delay time.Duration) WaiterDelay {
return func(attempt int) time.Duration {
return delay
}
}
// WithWaiterDelay will set the Waiter to use the WaiterDelay passed in.
func WithWaiterDelay(delayer WaiterDelay) WaiterOption {
return func(w *Waiter) {
w.Delay = delayer
}
}
// WithWaiterLogger returns a waiter option to set the logger a waiter
// should use to log warnings and errors to.
func WithWaiterLogger(logger aws.Logger) WaiterOption {
return func(w *Waiter) {
w.Logger = logger
}
}
// WithWaiterRequestOptions returns a waiter option setting the request
// options for each request the waiter makes. Appends to waiter's request
// options already set.
func WithWaiterRequestOptions(opts ...Option) WaiterOption {
return func(w *Waiter) {
w.RequestOptions = append(w.RequestOptions, opts...)
}
}
// A Waiter provides the functionality to perform a blocking call which will
// wait for a resource state to be satisfied by a service.
//
// This type should not be used directly. The API operations provided in the
// service packages prefixed with "WaitUntil" should be used instead.
type Waiter struct {
Name string
Acceptors []WaiterAcceptor
Logger aws.Logger
MaxAttempts int
Delay WaiterDelay
RequestOptions []Option
NewRequest func([]Option) (*Request, error)
SleepWithContext func(aws.Context, time.Duration) error
}
// ApplyOptions updates the waiter with the list of waiter options provided.
func (w *Waiter) ApplyOptions(opts ...WaiterOption) {
for _, fn := range opts {
fn(w)
}
}
// WaiterState are states the waiter uses based on WaiterAcceptor definitions
// to identify if the resource state the waiter is waiting on has occurred.
type WaiterState int
// String returns the string representation of the waiter state.
func (s WaiterState) String() string {
switch s {
case SuccessWaiterState:
return "success"
case FailureWaiterState:
return "failure"
case RetryWaiterState:
return "retry"
default:
return "unknown waiter state"
}
}
// States the waiter acceptors will use to identify target resource states.
const (
SuccessWaiterState WaiterState = iota // waiter successful
FailureWaiterState // waiter failed
RetryWaiterState // waiter needs to be retried
)
// WaiterMatchMode is the mode that the waiter will use to match the WaiterAcceptor
// definition's Expected attribute.
type WaiterMatchMode int
// Modes the waiter will use when inspecting API response to identify target
// resource states.
const (
PathAllWaiterMatch WaiterMatchMode = iota // match on all paths
PathWaiterMatch // match on specific path
PathAnyWaiterMatch // match on any path
PathListWaiterMatch // match on list of paths
StatusWaiterMatch // match on status code
ErrorWaiterMatch // match on error
)
// String returns the string representation of the waiter match mode.
func (m WaiterMatchMode) String() string {
switch m {
case PathAllWaiterMatch:
return "pathAll"
case PathWaiterMatch:
return "path"
case PathAnyWaiterMatch:
return "pathAny"
case PathListWaiterMatch:
return "pathList"
case StatusWaiterMatch:
return "status"
case ErrorWaiterMatch:
return "error"
default:
return "unknown waiter match mode"
}
}
// WaitWithContext will make requests for the API operation using NewRequest to
// build API requests. The request's response will be compared against the
// Waiter's Acceptors to determine the successful state of the resource the
// waiter is inspecting.
//
// The passed in context must not be nil. If it is nil a panic will occur. The
// Context will be used to cancel the waiter's pending requests and retry delays.
// Use aws.BackgroundContext if no context is available.
//
// The waiter will continue until the target state defined by the Acceptors,
// or the max attempts expires.
//
// Will return the WaiterResourceNotReadyErrorCode error code if the waiter's
// retryer ShouldRetry returns false. This normally will happen when the max
// wait attempts expires.
func (w Waiter) WaitWithContext(ctx aws.Context) error {
for attempt := 1; ; attempt++ {
req, err := w.NewRequest(w.RequestOptions)
if err != nil {
waiterLogf(w.Logger, "unable to create request %v", err)
return err
}
req.Handlers.Build.PushBack(MakeAddToUserAgentFreeFormHandler("Waiter"))
err = req.Send()
// See if any of the acceptors match the request's response, or error
for _, a := range w.Acceptors {
if matched, matchErr := a.match(w.Name, w.Logger, req, err); matched {
return matchErr
}
}
// The Waiter should only check the resource state MaxAttempts times
// This is here instead of in the for loop above to prevent delaying
// unnecessary when the waiter will not retry.
if attempt == w.MaxAttempts {
break
}
// Delay to wait before inspecting the resource again
delay := w.Delay(attempt)
if sleepFn := req.Config.SleepDelay; sleepFn != nil {
// Support SleepDelay for backwards compatibility and testing
sleepFn(delay)
} else {
sleepCtxFn := w.SleepWithContext
if sleepCtxFn == nil {
sleepCtxFn = aws.SleepWithContext
}
if err := sleepCtxFn(ctx, delay); err != nil {
return awserr.New(CanceledErrorCode, "waiter context canceled", err)
}
}
}
return awserr.New(WaiterResourceNotReadyErrorCode, "exceeded wait attempts", nil)
}
// A WaiterAcceptor provides the information needed to wait for an API operation
// to complete.
type WaiterAcceptor struct {
State WaiterState
Matcher WaiterMatchMode
Argument string
Expected interface{}
}
// match returns if the acceptor found a match with the passed in request
// or error. True is returned if the acceptor made a match, error is returned
// if there was an error attempting to perform the match.
func (a *WaiterAcceptor) match(name string, l aws.Logger, req *Request, err error) (bool, error) {
result := false
var vals []interface{}
switch a.Matcher {
case PathAllWaiterMatch, PathWaiterMatch:
// Require all matches to be equal for result to match
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
if len(vals) == 0 {
break
}
result = true
for _, val := range vals {
if !awsutil.DeepEqual(val, a.Expected) {
result = false
break
}
}
case PathAnyWaiterMatch:
// Only a single match needs to equal for the result to match
vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
for _, val := range vals {
if awsutil.DeepEqual(val, a.Expected) {
result = true
break
}
}
case PathListWaiterMatch:
// ignored matcher
case StatusWaiterMatch:
s := a.Expected.(int)
result = s == req.HTTPResponse.StatusCode
case ErrorWaiterMatch:
if aerr, ok := err.(awserr.Error); ok {
result = aerr.Code() == a.Expected.(string)
}
default:
waiterLogf(l, "WARNING: Waiter %s encountered unexpected matcher: %s",
name, a.Matcher)
}
if !result {
// If there was no matching result found there is nothing more to do
// for this response, retry the request.
return false, nil
}
switch a.State {
case SuccessWaiterState:
// waiter completed
return true, nil
case FailureWaiterState:
// Waiter failure state triggered
return true, awserr.New(WaiterResourceNotReadyErrorCode,
"failed waiting for successful resource state", err)
case RetryWaiterState:
// clear the error and retry the operation
return false, nil
default:
waiterLogf(l, "WARNING: Waiter %s encountered unexpected state: %s",
name, a.State)
return false, nil
}
}
func waiterLogf(logger aws.Logger, msg string, args ...interface{}) {
if logger != nil {
logger.Log(fmt.Sprintf(msg, args...))
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/credentials.go
================================================
package session
import (
"fmt"
"os"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/processcreds"
"github.com/aws/aws-sdk-go/aws/credentials/ssocreds"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/shareddefaults"
"github.com/aws/aws-sdk-go/service/sts"
)
// CredentialsProviderOptions specifies additional options for configuring
// credentials providers.
type CredentialsProviderOptions struct {
// WebIdentityRoleProviderOptions configures a WebIdentityRoleProvider,
// such as setting its ExpiryWindow.
WebIdentityRoleProviderOptions func(*stscreds.WebIdentityRoleProvider)
}
func resolveCredentials(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (*credentials.Credentials, error) {
switch {
case len(sessOpts.Profile) != 0:
// User explicitly provided an Profile in the session's configuration
// so load that profile from shared config first.
// Github(aws/aws-sdk-go#2727)
return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
case envCfg.Creds.HasKeys():
// Environment credentials
return credentials.NewStaticCredentialsFromCreds(envCfg.Creds), nil
case len(envCfg.WebIdentityTokenFilePath) != 0:
// Web identity token from environment, RoleARN required to also be
// set.
return assumeWebIdentity(cfg, handlers,
envCfg.WebIdentityTokenFilePath,
envCfg.RoleARN,
envCfg.RoleSessionName,
sessOpts.CredentialsProviderOptions,
)
default:
// Fallback to the "default" credential resolution chain.
return resolveCredsFromProfile(cfg, envCfg, sharedCfg, handlers, sessOpts)
}
}
// WebIdentityEmptyRoleARNErr will occur if 'AWS_WEB_IDENTITY_TOKEN_FILE' was set but
// 'AWS_ROLE_ARN' was not set.
var WebIdentityEmptyRoleARNErr = awserr.New(stscreds.ErrCodeWebIdentity, "role ARN is not set", nil)
// WebIdentityEmptyTokenFilePathErr will occur if 'AWS_ROLE_ARN' was set but
// 'AWS_WEB_IDENTITY_TOKEN_FILE' was not set.
var WebIdentityEmptyTokenFilePathErr = awserr.New(stscreds.ErrCodeWebIdentity, "token file path is not set", nil)
func assumeWebIdentity(cfg *aws.Config, handlers request.Handlers,
filepath string,
roleARN, sessionName string,
credOptions *CredentialsProviderOptions,
) (*credentials.Credentials, error) {
if len(filepath) == 0 {
return nil, WebIdentityEmptyTokenFilePathErr
}
if len(roleARN) == 0 {
return nil, WebIdentityEmptyRoleARNErr
}
svc := sts.New(&Session{
Config: cfg,
Handlers: handlers.Copy(),
})
var optFns []func(*stscreds.WebIdentityRoleProvider)
if credOptions != nil && credOptions.WebIdentityRoleProviderOptions != nil {
optFns = append(optFns, credOptions.WebIdentityRoleProviderOptions)
}
p := stscreds.NewWebIdentityRoleProviderWithOptions(svc, roleARN, sessionName, stscreds.FetchTokenPath(filepath), optFns...)
return credentials.NewCredentials(p), nil
}
func resolveCredsFromProfile(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (creds *credentials.Credentials, err error) {
switch {
case sharedCfg.SourceProfile != nil:
// Assume IAM role with credentials source from a different profile.
creds, err = resolveCredsFromProfile(cfg, envCfg,
*sharedCfg.SourceProfile, handlers, sessOpts,
)
case sharedCfg.Creds.HasKeys():
// Static Credentials from Shared Config/Credentials file.
creds = credentials.NewStaticCredentialsFromCreds(
sharedCfg.Creds,
)
case len(sharedCfg.CredentialSource) != 0:
creds, err = resolveCredsFromSource(cfg, envCfg,
sharedCfg, handlers, sessOpts,
)
case len(sharedCfg.WebIdentityTokenFile) != 0:
// Credentials from Assume Web Identity token require an IAM Role, and
// that roll will be assumed. May be wrapped with another assume role
// via SourceProfile.
return assumeWebIdentity(cfg, handlers,
sharedCfg.WebIdentityTokenFile,
sharedCfg.RoleARN,
sharedCfg.RoleSessionName,
sessOpts.CredentialsProviderOptions,
)
case sharedCfg.hasSSOConfiguration():
creds, err = resolveSSOCredentials(cfg, sharedCfg, handlers)
case len(sharedCfg.CredentialProcess) != 0:
// Get credentials from CredentialProcess
creds = processcreds.NewCredentials(sharedCfg.CredentialProcess)
default:
// Fallback to default credentials provider, include mock errors for
// the credential chain so user can identify why credentials failed to
// be retrieved.
creds = credentials.NewCredentials(&credentials.ChainProvider{
VerboseErrors: aws.BoolValue(cfg.CredentialsChainVerboseErrors),
Providers: []credentials.Provider{
&credProviderError{
Err: awserr.New("EnvAccessKeyNotFound",
"failed to find credentials in the environment.", nil),
},
&credProviderError{
Err: awserr.New("SharedCredsLoad",
fmt.Sprintf("failed to load profile, %s.", envCfg.Profile), nil),
},
defaults.RemoteCredProvider(*cfg, handlers),
},
})
}
if err != nil {
return nil, err
}
if len(sharedCfg.RoleARN) > 0 {
cfgCp := *cfg
cfgCp.Credentials = creds
return credsFromAssumeRole(cfgCp, handlers, sharedCfg, sessOpts)
}
return creds, nil
}
func resolveSSOCredentials(cfg *aws.Config, sharedCfg sharedConfig, handlers request.Handlers) (*credentials.Credentials, error) {
if err := sharedCfg.validateSSOConfiguration(); err != nil {
return nil, err
}
cfgCopy := cfg.Copy()
cfgCopy.Region = &sharedCfg.SSORegion
return ssocreds.NewCredentials(
&Session{
Config: cfgCopy,
Handlers: handlers.Copy(),
},
sharedCfg.SSOAccountID,
sharedCfg.SSORoleName,
sharedCfg.SSOStartURL,
), nil
}
// valid credential source values
const (
credSourceEc2Metadata = "Ec2InstanceMetadata"
credSourceEnvironment = "Environment"
credSourceECSContainer = "EcsContainer"
)
func resolveCredsFromSource(cfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) (creds *credentials.Credentials, err error) {
switch sharedCfg.CredentialSource {
case credSourceEc2Metadata:
p := defaults.RemoteCredProvider(*cfg, handlers)
creds = credentials.NewCredentials(p)
case credSourceEnvironment:
creds = credentials.NewStaticCredentialsFromCreds(envCfg.Creds)
case credSourceECSContainer:
if len(os.Getenv(shareddefaults.ECSCredsProviderEnvVar)) == 0 {
return nil, ErrSharedConfigECSContainerEnvVarEmpty
}
p := defaults.RemoteCredProvider(*cfg, handlers)
creds = credentials.NewCredentials(p)
default:
return nil, ErrSharedConfigInvalidCredSource
}
return creds, nil
}
func credsFromAssumeRole(cfg aws.Config,
handlers request.Handlers,
sharedCfg sharedConfig,
sessOpts Options,
) (*credentials.Credentials, error) {
if len(sharedCfg.MFASerial) != 0 && sessOpts.AssumeRoleTokenProvider == nil {
// AssumeRole Token provider is required if doing Assume Role
// with MFA.
return nil, AssumeRoleTokenProviderNotSetError{}
}
return stscreds.NewCredentials(
&Session{
Config: &cfg,
Handlers: handlers.Copy(),
},
sharedCfg.RoleARN,
func(opt *stscreds.AssumeRoleProvider) {
opt.RoleSessionName = sharedCfg.RoleSessionName
if sessOpts.AssumeRoleDuration == 0 &&
sharedCfg.AssumeRoleDuration != nil &&
*sharedCfg.AssumeRoleDuration/time.Minute > 15 {
opt.Duration = *sharedCfg.AssumeRoleDuration
} else if sessOpts.AssumeRoleDuration != 0 {
opt.Duration = sessOpts.AssumeRoleDuration
}
// Assume role with external ID
if len(sharedCfg.ExternalID) > 0 {
opt.ExternalID = aws.String(sharedCfg.ExternalID)
}
// Assume role with MFA
if len(sharedCfg.MFASerial) > 0 {
opt.SerialNumber = aws.String(sharedCfg.MFASerial)
opt.TokenProvider = sessOpts.AssumeRoleTokenProvider
}
},
), nil
}
// AssumeRoleTokenProviderNotSetError is an error returned when creating a
// session when the MFAToken option is not set when shared config is configured
// load assume a role with an MFA token.
type AssumeRoleTokenProviderNotSetError struct{}
// Code is the short id of the error.
func (e AssumeRoleTokenProviderNotSetError) Code() string {
return "AssumeRoleTokenProviderNotSetError"
}
// Message is the description of the error
func (e AssumeRoleTokenProviderNotSetError) Message() string {
return fmt.Sprintf("assume role with MFA enabled, but AssumeRoleTokenProvider session option not set.")
}
// OrigErr is the underlying error that caused the failure.
func (e AssumeRoleTokenProviderNotSetError) OrigErr() error {
return nil
}
// Error satisfies the error interface.
func (e AssumeRoleTokenProviderNotSetError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", nil)
}
type credProviderError struct {
Err error
}
func (c credProviderError) Retrieve() (credentials.Value, error) {
return credentials.Value{}, c.Err
}
func (c credProviderError) IsExpired() bool {
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/custom_transport.go
================================================
//go:build go1.13
// +build go1.13
package session
import (
"net"
"net/http"
"time"
)
// Transport that should be used when a custom CA bundle is specified with the
// SDK.
func getCustomTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/custom_transport_go1.12.go
================================================
//go:build !go1.13 && go1.7
// +build !go1.13,go1.7
package session
import (
"net"
"net/http"
"time"
)
// Transport that should be used when a custom CA bundle is specified with the
// SDK.
func getCustomTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/custom_transport_go1.5.go
================================================
//go:build !go1.6 && go1.5
// +build !go1.6,go1.5
package session
import (
"net"
"net/http"
"time"
)
// Transport that should be used when a custom CA bundle is specified with the
// SDK.
func getCustomTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/custom_transport_go1.6.go
================================================
//go:build !go1.7 && go1.6
// +build !go1.7,go1.6
package session
import (
"net"
"net/http"
"time"
)
// Transport that should be used when a custom CA bundle is specified with the
// SDK.
func getCustomTransport() *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/doc.go
================================================
/*
Package session provides configuration for the SDK's service clients. Sessions
can be shared across service clients that share the same base configuration.
Sessions are safe to use concurrently as long as the Session is not being
modified. Sessions should be cached when possible, because creating a new
Session will load all configuration values from the environment, and config
files each time the Session is created. Sharing the Session value across all of
your service clients will ensure the configuration is loaded the fewest number
of times possible.
Sessions options from Shared Config
By default NewSession will only load credentials from the shared credentials
file (~/.aws/credentials). If the AWS_SDK_LOAD_CONFIG environment variable is
set to a truthy value the Session will be created from the configuration
values from the shared config (~/.aws/config) and shared credentials
(~/.aws/credentials) files. Using the NewSessionWithOptions with
SharedConfigState set to SharedConfigEnable will create the session as if the
AWS_SDK_LOAD_CONFIG environment variable was set.
Credential and config loading order
The Session will attempt to load configuration and credentials from the
environment, configuration files, and other credential sources. The order
configuration is loaded in is:
* Environment Variables
* Shared Credentials file
* Shared Configuration file (if SharedConfig is enabled)
* EC2 Instance Metadata (credentials only)
The Environment variables for credentials will have precedence over shared
config even if SharedConfig is enabled. To override this behavior, and use
shared config credentials instead specify the session.Options.Profile, (e.g.
when using credential_source=Environment to assume a role).
sess, err := session.NewSessionWithOptions(session.Options{
Profile: "myProfile",
})
Creating Sessions
Creating a Session without additional options will load credentials region, and
profile loaded from the environment and shared config automatically. See,
"Environment Variables" section for information on environment variables used
by Session.
// Create Session
sess, err := session.NewSession()
When creating Sessions optional aws.Config values can be passed in that will
override the default, or loaded, config values the Session is being created
with. This allows you to provide additional, or case based, configuration
as needed.
// Create a Session with a custom region
sess, err := session.NewSession(&aws.Config{
Region: aws.String("us-west-2"),
})
Use NewSessionWithOptions to provide additional configuration driving how the
Session's configuration will be loaded. Such as, specifying shared config
profile, or override the shared config state, (AWS_SDK_LOAD_CONFIG).
// Equivalent to session.NewSession()
sess, err := session.NewSessionWithOptions(session.Options{
// Options
})
sess, err := session.NewSessionWithOptions(session.Options{
// Specify profile to load for the session's config
Profile: "profile_name",
// Provide SDK Config options, such as Region.
Config: aws.Config{
Region: aws.String("us-west-2"),
},
// Force enable Shared Config support
SharedConfigState: session.SharedConfigEnable,
})
Adding Handlers
You can add handlers to a session to decorate API operation, (e.g. adding HTTP
headers). All clients that use the Session receive a copy of the Session's
handlers. For example, the following request handler added to the Session logs
every requests made.
// Create a session, and add additional handlers for all service
// clients created with the Session to inherit. Adds logging handler.
sess := session.Must(session.NewSession())
sess.Handlers.Send.PushFront(func(r *request.Request) {
// Log every request made and its payload
logger.Printf("Request: %s/%s, Params: %s",
r.ClientInfo.ServiceName, r.Operation, r.Params)
})
Shared Config Fields
By default the SDK will only load the shared credentials file's
(~/.aws/credentials) credentials values, and all other config is provided by
the environment variables, SDK defaults, and user provided aws.Config values.
If the AWS_SDK_LOAD_CONFIG environment variable is set, or SharedConfigEnable
option is used to create the Session the full shared config values will be
loaded. This includes credentials, region, and support for assume role. In
addition the Session will load its configuration from both the shared config
file (~/.aws/config) and shared credentials file (~/.aws/credentials). Both
files have the same format.
If both config files are present the configuration from both files will be
read. The Session will be created from configuration values from the shared
credentials file (~/.aws/credentials) over those in the shared config file
(~/.aws/config).
Credentials are the values the SDK uses to authenticating requests with AWS
Services. When specified in a file, both aws_access_key_id and
aws_secret_access_key must be provided together in the same file to be
considered valid. They will be ignored if both are not present.
aws_session_token is an optional field that can be provided in addition to the
other two fields.
aws_access_key_id = AKID
aws_secret_access_key = SECRET
aws_session_token = TOKEN
; region only supported if SharedConfigEnabled.
region = us-east-1
Assume Role configuration
The role_arn field allows you to configure the SDK to assume an IAM role using
a set of credentials from another source. Such as when paired with static
credentials, "profile_source", "credential_process", or "credential_source"
fields. If "role_arn" is provided, a source of credentials must also be
specified, such as "source_profile", "credential_source", or
"credential_process".
role_arn = arn:aws:iam:::role/
source_profile = profile_with_creds
external_id = 1234
mfa_serial =
role_session_name = session_name
The SDK supports assuming a role with MFA token. If "mfa_serial" is set, you
must also set the Session Option.AssumeRoleTokenProvider. The Session will fail
to load if the AssumeRoleTokenProvider is not specified.
sess := session.Must(session.NewSessionWithOptions(session.Options{
AssumeRoleTokenProvider: stscreds.StdinTokenProvider,
}))
To setup Assume Role outside of a session see the stscreds.AssumeRoleProvider
documentation.
Environment Variables
When a Session is created several environment variables can be set to adjust
how the SDK functions, and what configuration data it loads when creating
Sessions. All environment values are optional, but some values like credentials
require multiple of the values to set or the partial values will be ignored.
All environment variable values are strings unless otherwise noted.
Environment configuration values. If set both Access Key ID and Secret Access
Key must be provided. Session Token and optionally also be provided, but is
not required.
# Access Key ID
AWS_ACCESS_KEY_ID=AKID
AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
# Secret Access Key
AWS_SECRET_ACCESS_KEY=SECRET
AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
# Session Token
AWS_SESSION_TOKEN=TOKEN
Region value will instruct the SDK where to make service API requests to. If is
not provided in the environment the region must be provided before a service
client request is made.
AWS_REGION=us-east-1
# AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
# and AWS_REGION is not also set.
AWS_DEFAULT_REGION=us-east-1
Profile name the SDK should load use when loading shared config from the
configuration files. If not provided "default" will be used as the profile name.
AWS_PROFILE=my_profile
# AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
# and AWS_PROFILE is not also set.
AWS_DEFAULT_PROFILE=my_profile
SDK load config instructs the SDK to load the shared config in addition to
shared credentials. This also expands the configuration loaded so the shared
credentials will have parity with the shared config file. This also enables
Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
env values as well.
AWS_SDK_LOAD_CONFIG=1
Custom Shared Config and Credential Files
Shared credentials file path can be set to instruct the SDK to use an alternative
file for the shared credentials. If not set the file will be loaded from
$HOME/.aws/credentials on Linux/Unix based systems, and
%USERPROFILE%\.aws\credentials on Windows.
AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
Shared config file path can be set to instruct the SDK to use an alternative
file for the shared config. If not set the file will be loaded from
$HOME/.aws/config on Linux/Unix based systems, and
%USERPROFILE%\.aws\config on Windows.
AWS_CONFIG_FILE=$HOME/my_shared_config
Custom CA Bundle
Path to a custom Credentials Authority (CA) bundle PEM file that the SDK
will use instead of the default system's root CA bundle. Use this only
if you want to replace the CA bundle the SDK uses for TLS requests.
AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
Enabling this option will attempt to merge the Transport into the SDK's HTTP
client. If the client's Transport is not a http.Transport an error will be
returned. If the Transport's TLS config is set this option will cause the SDK
to overwrite the Transport's TLS config's RootCAs value. If the CA bundle file
contains multiple certificates all of them will be loaded.
The Session option CustomCABundle is also available when creating sessions
to also enable this feature. CustomCABundle session option field has priority
over the AWS_CA_BUNDLE environment variable, and will be used if both are set.
Setting a custom HTTPClient in the aws.Config options will override this setting.
To use this option and custom HTTP client, the HTTP client needs to be provided
when creating the session. Not the service client.
Custom Client TLS Certificate
The SDK supports the environment and session option being configured with
Client TLS certificates that are sent as a part of the client's TLS handshake
for client authentication. If used, both Cert and Key values are required. If
one is missing, or either fail to load the contents of the file an error will
be returned.
HTTP Client's Transport concrete implementation must be a http.Transport
or creating the session will fail.
AWS_SDK_GO_CLIENT_TLS_KEY=$HOME/my_client_key
AWS_SDK_GO_CLIENT_TLS_CERT=$HOME/my_client_cert
This can also be configured via the session.Options ClientTLSCert and ClientTLSKey.
sess, err := session.NewSessionWithOptions(session.Options{
ClientTLSCert: myCertFile,
ClientTLSKey: myKeyFile,
})
Custom EC2 IMDS Endpoint
The endpoint of the EC2 IMDS client can be configured via the environment
variable, AWS_EC2_METADATA_SERVICE_ENDPOINT when creating the client with a
Session. See Options.EC2IMDSEndpoint for more details.
AWS_EC2_METADATA_SERVICE_ENDPOINT=http://169.254.169.254
If using an URL with an IPv6 address literal, the IPv6 address
component must be enclosed in square brackets.
AWS_EC2_METADATA_SERVICE_ENDPOINT=http://[::1]
The custom EC2 IMDS endpoint can also be specified via the Session options.
sess, err := session.NewSessionWithOptions(session.Options{
EC2MetadataEndpoint: "http://[::1]",
})
FIPS and DualStack Endpoints
The SDK can be configured to resolve an endpoint with certain capabilities such as FIPS and DualStack.
You can configure a FIPS endpoint using an environment variable, shared config ($HOME/.aws/config),
or programmatically.
To configure a FIPS endpoint set the environment variable set the AWS_USE_FIPS_ENDPOINT to true or false to enable
or disable FIPS endpoint resolution.
AWS_USE_FIPS_ENDPOINT=true
To configure a FIPS endpoint using shared config, set use_fips_endpoint to true or false to enable
or disable FIPS endpoint resolution.
[profile myprofile]
region=us-west-2
use_fips_endpoint=true
To configure a FIPS endpoint programmatically
// Option 1: Configure it on a session for all clients
sess, err := session.NewSessionWithOptions(session.Options{
UseFIPSEndpoint: endpoints.FIPSEndpointStateEnabled,
})
if err != nil {
// handle error
}
client := s3.New(sess)
// Option 2: Configure it per client
sess, err := session.NewSession()
if err != nil {
// handle error
}
client := s3.New(sess, &aws.Config{
UseFIPSEndpoint: endpoints.FIPSEndpointStateEnabled,
})
You can configure a DualStack endpoint using an environment variable, shared config ($HOME/.aws/config),
or programmatically.
To configure a DualStack endpoint set the environment variable set the AWS_USE_DUALSTACK_ENDPOINT to true or false to
enable or disable DualStack endpoint resolution.
AWS_USE_DUALSTACK_ENDPOINT=true
To configure a DualStack endpoint using shared config, set use_dualstack_endpoint to true or false to enable
or disable DualStack endpoint resolution.
[profile myprofile]
region=us-west-2
use_dualstack_endpoint=true
To configure a DualStack endpoint programmatically
// Option 1: Configure it on a session for all clients
sess, err := session.NewSessionWithOptions(session.Options{
UseDualStackEndpoint: endpoints.DualStackEndpointStateEnabled,
})
if err != nil {
// handle error
}
client := s3.New(sess)
// Option 2: Configure it per client
sess, err := session.NewSession()
if err != nil {
// handle error
}
client := s3.New(sess, &aws.Config{
UseDualStackEndpoint: endpoints.DualStackEndpointStateEnabled,
})
*/
package session
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/env_config.go
================================================
package session
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/endpoints"
)
// EnvProviderName provides a name of the provider when config is loaded from environment.
const EnvProviderName = "EnvConfigCredentials"
// envConfig is a collection of environment values the SDK will read
// setup config from. All environment values are optional. But some values
// such as credentials require multiple values to be complete or the values
// will be ignored.
type envConfig struct {
// Environment configuration values. If set both Access Key ID and Secret Access
// Key must be provided. Session Token and optionally also be provided, but is
// not required.
//
// # Access Key ID
// AWS_ACCESS_KEY_ID=AKID
// AWS_ACCESS_KEY=AKID # only read if AWS_ACCESS_KEY_ID is not set.
//
// # Secret Access Key
// AWS_SECRET_ACCESS_KEY=SECRET
// AWS_SECRET_KEY=SECRET=SECRET # only read if AWS_SECRET_ACCESS_KEY is not set.
//
// # Session Token
// AWS_SESSION_TOKEN=TOKEN
Creds credentials.Value
// Region value will instruct the SDK where to make service API requests to. If is
// not provided in the environment the region must be provided before a service
// client request is made.
//
// AWS_REGION=us-east-1
//
// # AWS_DEFAULT_REGION is only read if AWS_SDK_LOAD_CONFIG is also set,
// # and AWS_REGION is not also set.
// AWS_DEFAULT_REGION=us-east-1
Region string
// Profile name the SDK should load use when loading shared configuration from the
// shared configuration files. If not provided "default" will be used as the
// profile name.
//
// AWS_PROFILE=my_profile
//
// # AWS_DEFAULT_PROFILE is only read if AWS_SDK_LOAD_CONFIG is also set,
// # and AWS_PROFILE is not also set.
// AWS_DEFAULT_PROFILE=my_profile
Profile string
// SDK load config instructs the SDK to load the shared config in addition to
// shared credentials. This also expands the configuration loaded from the shared
// credentials to have parity with the shared config file. This also enables
// Region and Profile support for the AWS_DEFAULT_REGION and AWS_DEFAULT_PROFILE
// env values as well.
//
// AWS_SDK_LOAD_CONFIG=1
EnableSharedConfig bool
// Shared credentials file path can be set to instruct the SDK to use an alternate
// file for the shared credentials. If not set the file will be loaded from
// $HOME/.aws/credentials on Linux/Unix based systems, and
// %USERPROFILE%\.aws\credentials on Windows.
//
// AWS_SHARED_CREDENTIALS_FILE=$HOME/my_shared_credentials
SharedCredentialsFile string
// Shared config file path can be set to instruct the SDK to use an alternate
// file for the shared config. If not set the file will be loaded from
// $HOME/.aws/config on Linux/Unix based systems, and
// %USERPROFILE%\.aws\config on Windows.
//
// AWS_CONFIG_FILE=$HOME/my_shared_config
SharedConfigFile string
// Sets the path to a custom Credentials Authority (CA) Bundle PEM file
// that the SDK will use instead of the system's root CA bundle.
// Only use this if you want to configure the SDK to use a custom set
// of CAs.
//
// Enabling this option will attempt to merge the Transport
// into the SDK's HTTP client. If the client's Transport is
// not a http.Transport an error will be returned. If the
// Transport's TLS config is set this option will cause the
// SDK to overwrite the Transport's TLS config's RootCAs value.
//
// Setting a custom HTTPClient in the aws.Config options will override this setting.
// To use this option and custom HTTP client, the HTTP client needs to be provided
// when creating the session. Not the service client.
//
// AWS_CA_BUNDLE=$HOME/my_custom_ca_bundle
CustomCABundle string
// Sets the TLC client certificate that should be used by the SDK's HTTP transport
// when making requests. The certificate must be paired with a TLS client key file.
//
// AWS_SDK_GO_CLIENT_TLS_CERT=$HOME/my_client_cert
ClientTLSCert string
// Sets the TLC client key that should be used by the SDK's HTTP transport
// when making requests. The key must be paired with a TLS client certificate file.
//
// AWS_SDK_GO_CLIENT_TLS_KEY=$HOME/my_client_key
ClientTLSKey string
csmEnabled string
CSMEnabled *bool
CSMPort string
CSMHost string
CSMClientID string
// Enables endpoint discovery via environment variables.
//
// AWS_ENABLE_ENDPOINT_DISCOVERY=true
EnableEndpointDiscovery *bool
enableEndpointDiscovery string
// Specifies the WebIdentity token the SDK should use to assume a role
// with.
//
// AWS_WEB_IDENTITY_TOKEN_FILE=file_path
WebIdentityTokenFilePath string
// Specifies the IAM role arn to use when assuming an role.
//
// AWS_ROLE_ARN=role_arn
RoleARN string
// Specifies the IAM role session name to use when assuming a role.
//
// AWS_ROLE_SESSION_NAME=session_name
RoleSessionName string
// Specifies the STS Regional Endpoint flag for the SDK to resolve the endpoint
// for a service.
//
// AWS_STS_REGIONAL_ENDPOINTS=regional
// This can take value as `regional` or `legacy`
STSRegionalEndpoint endpoints.STSRegionalEndpoint
// Specifies the S3 Regional Endpoint flag for the SDK to resolve the
// endpoint for a service.
//
// AWS_S3_US_EAST_1_REGIONAL_ENDPOINT=regional
// This can take value as `regional` or `legacy`
S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint
// Specifies if the S3 service should allow ARNs to direct the region
// the client's requests are sent to.
//
// AWS_S3_USE_ARN_REGION=true
S3UseARNRegion bool
// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
//
// AWS_EC2_METADATA_SERVICE_ENDPOINT=http://[::1]
EC2IMDSEndpoint string
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
//
// AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState
// Specifies that SDK clients must resolve a dual-stack endpoint for
// services.
//
// AWS_USE_DUALSTACK_ENDPOINT=true
UseDualStackEndpoint endpoints.DualStackEndpointState
// Specifies that SDK clients must resolve a FIPS endpoint for
// services.
//
// AWS_USE_FIPS_ENDPOINT=true
UseFIPSEndpoint endpoints.FIPSEndpointState
}
var (
csmEnabledEnvKey = []string{
"AWS_CSM_ENABLED",
}
csmHostEnvKey = []string{
"AWS_CSM_HOST",
}
csmPortEnvKey = []string{
"AWS_CSM_PORT",
}
csmClientIDEnvKey = []string{
"AWS_CSM_CLIENT_ID",
}
credAccessEnvKey = []string{
"AWS_ACCESS_KEY_ID",
"AWS_ACCESS_KEY",
}
credSecretEnvKey = []string{
"AWS_SECRET_ACCESS_KEY",
"AWS_SECRET_KEY",
}
credSessionEnvKey = []string{
"AWS_SESSION_TOKEN",
}
enableEndpointDiscoveryEnvKey = []string{
"AWS_ENABLE_ENDPOINT_DISCOVERY",
}
regionEnvKeys = []string{
"AWS_REGION",
"AWS_DEFAULT_REGION", // Only read if AWS_SDK_LOAD_CONFIG is also set
}
profileEnvKeys = []string{
"AWS_PROFILE",
"AWS_DEFAULT_PROFILE", // Only read if AWS_SDK_LOAD_CONFIG is also set
}
sharedCredsFileEnvKey = []string{
"AWS_SHARED_CREDENTIALS_FILE",
}
sharedConfigFileEnvKey = []string{
"AWS_CONFIG_FILE",
}
webIdentityTokenFilePathEnvKey = []string{
"AWS_WEB_IDENTITY_TOKEN_FILE",
}
roleARNEnvKey = []string{
"AWS_ROLE_ARN",
}
roleSessionNameEnvKey = []string{
"AWS_ROLE_SESSION_NAME",
}
stsRegionalEndpointKey = []string{
"AWS_STS_REGIONAL_ENDPOINTS",
}
s3UsEast1RegionalEndpoint = []string{
"AWS_S3_US_EAST_1_REGIONAL_ENDPOINT",
}
s3UseARNRegionEnvKey = []string{
"AWS_S3_USE_ARN_REGION",
}
ec2IMDSEndpointEnvKey = []string{
"AWS_EC2_METADATA_SERVICE_ENDPOINT",
}
ec2IMDSEndpointModeEnvKey = []string{
"AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE",
}
useCABundleKey = []string{
"AWS_CA_BUNDLE",
}
useClientTLSCert = []string{
"AWS_SDK_GO_CLIENT_TLS_CERT",
}
useClientTLSKey = []string{
"AWS_SDK_GO_CLIENT_TLS_KEY",
}
awsUseDualStackEndpoint = []string{
"AWS_USE_DUALSTACK_ENDPOINT",
}
awsUseFIPSEndpoint = []string{
"AWS_USE_FIPS_ENDPOINT",
}
)
// loadEnvConfig retrieves the SDK's environment configuration.
// See `envConfig` for the values that will be retrieved.
//
// If the environment variable `AWS_SDK_LOAD_CONFIG` is set to a truthy value
// the shared SDK config will be loaded in addition to the SDK's specific
// configuration values.
func loadEnvConfig() (envConfig, error) {
enableSharedConfig, _ := strconv.ParseBool(os.Getenv("AWS_SDK_LOAD_CONFIG"))
return envConfigLoad(enableSharedConfig)
}
// loadEnvSharedConfig retrieves the SDK's environment configuration, and the
// SDK shared config. See `envConfig` for the values that will be retrieved.
//
// Loads the shared configuration in addition to the SDK's specific configuration.
// This will load the same values as `loadEnvConfig` if the `AWS_SDK_LOAD_CONFIG`
// environment variable is set.
func loadSharedEnvConfig() (envConfig, error) {
return envConfigLoad(true)
}
func envConfigLoad(enableSharedConfig bool) (envConfig, error) {
cfg := envConfig{}
cfg.EnableSharedConfig = enableSharedConfig
// Static environment credentials
var creds credentials.Value
setFromEnvVal(&creds.AccessKeyID, credAccessEnvKey)
setFromEnvVal(&creds.SecretAccessKey, credSecretEnvKey)
setFromEnvVal(&creds.SessionToken, credSessionEnvKey)
if creds.HasKeys() {
// Require logical grouping of credentials
creds.ProviderName = EnvProviderName
cfg.Creds = creds
}
// Role Metadata
setFromEnvVal(&cfg.RoleARN, roleARNEnvKey)
setFromEnvVal(&cfg.RoleSessionName, roleSessionNameEnvKey)
// Web identity environment variables
setFromEnvVal(&cfg.WebIdentityTokenFilePath, webIdentityTokenFilePathEnvKey)
// CSM environment variables
setFromEnvVal(&cfg.csmEnabled, csmEnabledEnvKey)
setFromEnvVal(&cfg.CSMHost, csmHostEnvKey)
setFromEnvVal(&cfg.CSMPort, csmPortEnvKey)
setFromEnvVal(&cfg.CSMClientID, csmClientIDEnvKey)
if len(cfg.csmEnabled) != 0 {
v, _ := strconv.ParseBool(cfg.csmEnabled)
cfg.CSMEnabled = &v
}
regionKeys := regionEnvKeys
profileKeys := profileEnvKeys
if !cfg.EnableSharedConfig {
regionKeys = regionKeys[:1]
profileKeys = profileKeys[:1]
}
setFromEnvVal(&cfg.Region, regionKeys)
setFromEnvVal(&cfg.Profile, profileKeys)
// endpoint discovery is in reference to it being enabled.
setFromEnvVal(&cfg.enableEndpointDiscovery, enableEndpointDiscoveryEnvKey)
if len(cfg.enableEndpointDiscovery) > 0 {
cfg.EnableEndpointDiscovery = aws.Bool(cfg.enableEndpointDiscovery != "false")
}
setFromEnvVal(&cfg.SharedCredentialsFile, sharedCredsFileEnvKey)
setFromEnvVal(&cfg.SharedConfigFile, sharedConfigFileEnvKey)
if len(cfg.SharedCredentialsFile) == 0 {
cfg.SharedCredentialsFile = defaults.SharedCredentialsFilename()
}
if len(cfg.SharedConfigFile) == 0 {
cfg.SharedConfigFile = defaults.SharedConfigFilename()
}
setFromEnvVal(&cfg.CustomCABundle, useCABundleKey)
setFromEnvVal(&cfg.ClientTLSCert, useClientTLSCert)
setFromEnvVal(&cfg.ClientTLSKey, useClientTLSKey)
var err error
// STS Regional Endpoint variable
for _, k := range stsRegionalEndpointKey {
if v := os.Getenv(k); len(v) != 0 {
cfg.STSRegionalEndpoint, err = endpoints.GetSTSRegionalEndpoint(v)
if err != nil {
return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err)
}
}
}
// S3 Regional Endpoint variable
for _, k := range s3UsEast1RegionalEndpoint {
if v := os.Getenv(k); len(v) != 0 {
cfg.S3UsEast1RegionalEndpoint, err = endpoints.GetS3UsEast1RegionalEndpoint(v)
if err != nil {
return cfg, fmt.Errorf("failed to load, %v from env config, %v", k, err)
}
}
}
var s3UseARNRegion string
setFromEnvVal(&s3UseARNRegion, s3UseARNRegionEnvKey)
if len(s3UseARNRegion) != 0 {
switch {
case strings.EqualFold(s3UseARNRegion, "false"):
cfg.S3UseARNRegion = false
case strings.EqualFold(s3UseARNRegion, "true"):
cfg.S3UseARNRegion = true
default:
return envConfig{}, fmt.Errorf(
"invalid value for environment variable, %s=%s, need true or false",
s3UseARNRegionEnvKey[0], s3UseARNRegion)
}
}
setFromEnvVal(&cfg.EC2IMDSEndpoint, ec2IMDSEndpointEnvKey)
if err := setEC2IMDSEndpointMode(&cfg.EC2IMDSEndpointMode, ec2IMDSEndpointModeEnvKey); err != nil {
return envConfig{}, err
}
if err := setUseDualStackEndpointFromEnvVal(&cfg.UseDualStackEndpoint, awsUseDualStackEndpoint); err != nil {
return cfg, err
}
if err := setUseFIPSEndpointFromEnvVal(&cfg.UseFIPSEndpoint, awsUseFIPSEndpoint); err != nil {
return cfg, err
}
return cfg, nil
}
func setFromEnvVal(dst *string, keys []string) {
for _, k := range keys {
if v := os.Getenv(k); len(v) != 0 {
*dst = v
break
}
}
}
func setEC2IMDSEndpointMode(mode *endpoints.EC2IMDSEndpointModeState, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
if len(value) == 0 {
continue
}
if err := mode.SetFromString(value); err != nil {
return fmt.Errorf("invalid value for environment variable, %s=%s, %v", k, value, err)
}
return nil
}
return nil
}
func setUseDualStackEndpointFromEnvVal(dst *endpoints.DualStackEndpointState, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
if len(value) == 0 {
continue // skip if empty
}
switch {
case strings.EqualFold(value, "true"):
*dst = endpoints.DualStackEndpointStateEnabled
case strings.EqualFold(value, "false"):
*dst = endpoints.DualStackEndpointStateDisabled
default:
return fmt.Errorf(
"invalid value for environment variable, %s=%s, need true, false",
k, value)
}
}
return nil
}
func setUseFIPSEndpointFromEnvVal(dst *endpoints.FIPSEndpointState, keys []string) error {
for _, k := range keys {
value := os.Getenv(k)
if len(value) == 0 {
continue // skip if empty
}
switch {
case strings.EqualFold(value, "true"):
*dst = endpoints.FIPSEndpointStateEnabled
case strings.EqualFold(value, "false"):
*dst = endpoints.FIPSEndpointStateDisabled
default:
return fmt.Errorf(
"invalid value for environment variable, %s=%s, need true, false",
k, value)
}
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/session.go
================================================
package session
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/csm"
"github.com/aws/aws-sdk-go/aws/defaults"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/request"
)
const (
// ErrCodeSharedConfig represents an error that occurs in the shared
// configuration logic
ErrCodeSharedConfig = "SharedConfigErr"
// ErrCodeLoadCustomCABundle error code for unable to load custom CA bundle.
ErrCodeLoadCustomCABundle = "LoadCustomCABundleError"
// ErrCodeLoadClientTLSCert error code for unable to load client TLS
// certificate or key
ErrCodeLoadClientTLSCert = "LoadClientTLSCertError"
)
// ErrSharedConfigSourceCollision will be returned if a section contains both
// source_profile and credential_source
var ErrSharedConfigSourceCollision = awserr.New(ErrCodeSharedConfig, "only one credential type may be specified per profile: source profile, credential source, credential process, web identity token, or sso", nil)
// ErrSharedConfigECSContainerEnvVarEmpty will be returned if the environment
// variables are empty and Environment was set as the credential source
var ErrSharedConfigECSContainerEnvVarEmpty = awserr.New(ErrCodeSharedConfig, "EcsContainer was specified as the credential_source, but 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' was not set", nil)
// ErrSharedConfigInvalidCredSource will be returned if an invalid credential source was provided
var ErrSharedConfigInvalidCredSource = awserr.New(ErrCodeSharedConfig, "credential source values must be EcsContainer, Ec2InstanceMetadata, or Environment", nil)
// A Session provides a central location to create service clients from and
// store configurations and request handlers for those services.
//
// Sessions are safe to create service clients concurrently, but it is not safe
// to mutate the Session concurrently.
//
// The Session satisfies the service client's client.ConfigProvider.
type Session struct {
Config *aws.Config
Handlers request.Handlers
options Options
}
// New creates a new instance of the handlers merging in the provided configs
// on top of the SDK's default configurations. Once the Session is created it
// can be mutated to modify the Config or Handlers. The Session is safe to be
// read concurrently, but it should not be written to concurrently.
//
// If the AWS_SDK_LOAD_CONFIG environment is set to a truthy value, the New
// method could now encounter an error when loading the configuration. When
// The environment variable is set, and an error occurs, New will return a
// session that will fail all requests reporting the error that occurred while
// loading the session. Use NewSession to get the error when creating the
// session.
//
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
// the shared config file (~/.aws/config) will also be loaded, in addition to
// the shared credentials file (~/.aws/credentials). Values set in both the
// shared config, and shared credentials will be taken from the shared
// credentials file.
//
// Deprecated: Use NewSession functions to create sessions instead. NewSession
// has the same functionality as New except an error can be returned when the
// func is called instead of waiting to receive an error until a request is made.
func New(cfgs ...*aws.Config) *Session {
// load initial config from environment
envCfg, envErr := loadEnvConfig()
if envCfg.EnableSharedConfig {
var cfg aws.Config
cfg.MergeIn(cfgs...)
s, err := NewSessionWithOptions(Options{
Config: cfg,
SharedConfigState: SharedConfigEnable,
})
if err != nil {
// Old session.New expected all errors to be discovered when
// a request is made, and would report the errors then. This
// needs to be replicated if an error occurs while creating
// the session.
msg := "failed to create session with AWS_SDK_LOAD_CONFIG enabled. " +
"Use session.NewSession to handle errors occurring during session creation."
// Session creation failed, need to report the error and prevent
// any requests from succeeding.
s = &Session{Config: defaults.Config()}
s.logDeprecatedNewSessionError(msg, err, cfgs)
}
return s
}
s := deprecatedNewSession(envCfg, cfgs...)
if envErr != nil {
msg := "failed to load env config"
s.logDeprecatedNewSessionError(msg, envErr, cfgs)
}
if csmCfg, err := loadCSMConfig(envCfg, []string{}); err != nil {
if l := s.Config.Logger; l != nil {
l.Log(fmt.Sprintf("ERROR: failed to load CSM configuration, %v", err))
}
} else if csmCfg.Enabled {
err := enableCSM(&s.Handlers, csmCfg, s.Config.Logger)
if err != nil {
msg := "failed to enable CSM"
s.logDeprecatedNewSessionError(msg, err, cfgs)
}
}
return s
}
// NewSession returns a new Session created from SDK defaults, config files,
// environment, and user provided config files. Once the Session is created
// it can be mutated to modify the Config or Handlers. The Session is safe to
// be read concurrently, but it should not be written to concurrently.
//
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
// the shared config file (~/.aws/config) will also be loaded in addition to
// the shared credentials file (~/.aws/credentials). Values set in both the
// shared config, and shared credentials will be taken from the shared
// credentials file. Enabling the Shared Config will also allow the Session
// to be built with retrieving credentials with AssumeRole set in the config.
//
// See the NewSessionWithOptions func for information on how to override or
// control through code how the Session will be created, such as specifying the
// config profile, and controlling if shared config is enabled or not.
func NewSession(cfgs ...*aws.Config) (*Session, error) {
opts := Options{}
opts.Config.MergeIn(cfgs...)
return NewSessionWithOptions(opts)
}
// SharedConfigState provides the ability to optionally override the state
// of the session's creation based on the shared config being enabled or
// disabled.
type SharedConfigState int
const (
// SharedConfigStateFromEnv does not override any state of the
// AWS_SDK_LOAD_CONFIG env var. It is the default value of the
// SharedConfigState type.
SharedConfigStateFromEnv SharedConfigState = iota
// SharedConfigDisable overrides the AWS_SDK_LOAD_CONFIG env var value
// and disables the shared config functionality.
SharedConfigDisable
// SharedConfigEnable overrides the AWS_SDK_LOAD_CONFIG env var value
// and enables the shared config functionality.
SharedConfigEnable
)
// Options provides the means to control how a Session is created and what
// configuration values will be loaded.
//
type Options struct {
// Provides config values for the SDK to use when creating service clients
// and making API requests to services. Any value set in with this field
// will override the associated value provided by the SDK defaults,
// environment or config files where relevant.
//
// If not set, configuration values from from SDK defaults, environment,
// config will be used.
Config aws.Config
// Overrides the config profile the Session should be created from. If not
// set the value of the environment variable will be loaded (AWS_PROFILE,
// or AWS_DEFAULT_PROFILE if the Shared Config is enabled).
//
// If not set and environment variables are not set the "default"
// (DefaultSharedConfigProfile) will be used as the profile to load the
// session config from.
Profile string
// Instructs how the Session will be created based on the AWS_SDK_LOAD_CONFIG
// environment variable. By default a Session will be created using the
// value provided by the AWS_SDK_LOAD_CONFIG environment variable.
//
// Setting this value to SharedConfigEnable or SharedConfigDisable
// will allow you to override the AWS_SDK_LOAD_CONFIG environment variable
// and enable or disable the shared config functionality.
SharedConfigState SharedConfigState
// Ordered list of files the session will load configuration from.
// It will override environment variable AWS_SHARED_CREDENTIALS_FILE, AWS_CONFIG_FILE.
SharedConfigFiles []string
// When the SDK's shared config is configured to assume a role with MFA
// this option is required in order to provide the mechanism that will
// retrieve the MFA token. There is no default value for this field. If
// it is not set an error will be returned when creating the session.
//
// This token provider will be called when ever the assumed role's
// credentials need to be refreshed. Within the context of service clients
// all sharing the same session the SDK will ensure calls to the token
// provider are atomic. When sharing a token provider across multiple
// sessions additional synchronization logic is needed to ensure the
// token providers do not introduce race conditions. It is recommend to
// share the session where possible.
//
// stscreds.StdinTokenProvider is a basic implementation that will prompt
// from stdin for the MFA token code.
//
// This field is only used if the shared configuration is enabled, and
// the config enables assume role wit MFA via the mfa_serial field.
AssumeRoleTokenProvider func() (string, error)
// When the SDK's shared config is configured to assume a role this option
// may be provided to set the expiry duration of the STS credentials.
// Defaults to 15 minutes if not set as documented in the
// stscreds.AssumeRoleProvider.
AssumeRoleDuration time.Duration
// Reader for a custom Credentials Authority (CA) bundle in PEM format that
// the SDK will use instead of the default system's root CA bundle. Use this
// only if you want to replace the CA bundle the SDK uses for TLS requests.
//
// HTTP Client's Transport concrete implementation must be a http.Transport
// or creating the session will fail.
//
// If the Transport's TLS config is set this option will cause the SDK
// to overwrite the Transport's TLS config's RootCAs value. If the CA
// bundle reader contains multiple certificates all of them will be loaded.
//
// Can also be specified via the environment variable:
//
// AWS_CA_BUNDLE=$HOME/ca_bundle
//
// Can also be specified via the shared config field:
//
// ca_bundle = $HOME/ca_bundle
CustomCABundle io.Reader
// Reader for the TLC client certificate that should be used by the SDK's
// HTTP transport when making requests. The certificate must be paired with
// a TLS client key file. Will be ignored if both are not provided.
//
// HTTP Client's Transport concrete implementation must be a http.Transport
// or creating the session will fail.
//
// Can also be specified via the environment variable:
//
// AWS_SDK_GO_CLIENT_TLS_CERT=$HOME/my_client_cert
ClientTLSCert io.Reader
// Reader for the TLC client key that should be used by the SDK's HTTP
// transport when making requests. The key must be paired with a TLS client
// certificate file. Will be ignored if both are not provided.
//
// HTTP Client's Transport concrete implementation must be a http.Transport
// or creating the session will fail.
//
// Can also be specified via the environment variable:
//
// AWS_SDK_GO_CLIENT_TLS_KEY=$HOME/my_client_key
ClientTLSKey io.Reader
// The handlers that the session and all API clients will be created with.
// This must be a complete set of handlers. Use the defaults.Handlers()
// function to initialize this value before changing the handlers to be
// used by the SDK.
Handlers request.Handlers
// Allows specifying a custom endpoint to be used by the EC2 IMDS client
// when making requests to the EC2 IMDS API. The endpoint value should
// include the URI scheme. If the scheme is not present it will be defaulted to http.
//
// If unset, will the EC2 IMDS client will use its default endpoint.
//
// Can also be specified via the environment variable,
// AWS_EC2_METADATA_SERVICE_ENDPOINT.
//
// AWS_EC2_METADATA_SERVICE_ENDPOINT=http://169.254.169.254
//
// If using an URL with an IPv6 address literal, the IPv6 address
// component must be enclosed in square brackets.
//
// AWS_EC2_METADATA_SERVICE_ENDPOINT=http://[::1]
EC2IMDSEndpoint string
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
//
// AWS_EC2_METADATA_SERVICE_ENDPOINT_MODE=IPv6
EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState
// Specifies options for creating credential providers.
// These are only used if the aws.Config does not already
// include credentials.
CredentialsProviderOptions *CredentialsProviderOptions
}
// NewSessionWithOptions returns a new Session created from SDK defaults, config files,
// environment, and user provided config files. This func uses the Options
// values to configure how the Session is created.
//
// If the AWS_SDK_LOAD_CONFIG environment variable is set to a truthy value
// the shared config file (~/.aws/config) will also be loaded in addition to
// the shared credentials file (~/.aws/credentials). Values set in both the
// shared config, and shared credentials will be taken from the shared
// credentials file. Enabling the Shared Config will also allow the Session
// to be built with retrieving credentials with AssumeRole set in the config.
//
// // Equivalent to session.New
// sess := session.Must(session.NewSessionWithOptions(session.Options{}))
//
// // Specify profile to load for the session's config
// sess := session.Must(session.NewSessionWithOptions(session.Options{
// Profile: "profile_name",
// }))
//
// // Specify profile for config and region for requests
// sess := session.Must(session.NewSessionWithOptions(session.Options{
// Config: aws.Config{Region: aws.String("us-east-1")},
// Profile: "profile_name",
// }))
//
// // Force enable Shared Config support
// sess := session.Must(session.NewSessionWithOptions(session.Options{
// SharedConfigState: session.SharedConfigEnable,
// }))
func NewSessionWithOptions(opts Options) (*Session, error) {
var envCfg envConfig
var err error
if opts.SharedConfigState == SharedConfigEnable {
envCfg, err = loadSharedEnvConfig()
if err != nil {
return nil, fmt.Errorf("failed to load shared config, %v", err)
}
} else {
envCfg, err = loadEnvConfig()
if err != nil {
return nil, fmt.Errorf("failed to load environment config, %v", err)
}
}
if len(opts.Profile) != 0 {
envCfg.Profile = opts.Profile
}
switch opts.SharedConfigState {
case SharedConfigDisable:
envCfg.EnableSharedConfig = false
case SharedConfigEnable:
envCfg.EnableSharedConfig = true
}
return newSession(opts, envCfg, &opts.Config)
}
// Must is a helper function to ensure the Session is valid and there was no
// error when calling a NewSession function.
//
// This helper is intended to be used in variable initialization to load the
// Session and configuration at startup. Such as:
//
// var sess = session.Must(session.NewSession())
func Must(sess *Session, err error) *Session {
if err != nil {
panic(err)
}
return sess
}
// Wraps the endpoint resolver with a resolver that will return a custom
// endpoint for EC2 IMDS.
func wrapEC2IMDSEndpoint(resolver endpoints.Resolver, endpoint string, mode endpoints.EC2IMDSEndpointModeState) endpoints.Resolver {
return endpoints.ResolverFunc(
func(service, region string, opts ...func(*endpoints.Options)) (
endpoints.ResolvedEndpoint, error,
) {
if service == ec2MetadataServiceID && len(endpoint) > 0 {
return endpoints.ResolvedEndpoint{
URL: endpoint,
SigningName: ec2MetadataServiceID,
SigningRegion: region,
}, nil
} else if service == ec2MetadataServiceID {
opts = append(opts, func(o *endpoints.Options) {
o.EC2MetadataEndpointMode = mode
})
}
return resolver.EndpointFor(service, region, opts...)
})
}
func deprecatedNewSession(envCfg envConfig, cfgs ...*aws.Config) *Session {
cfg := defaults.Config()
handlers := defaults.Handlers()
// Apply the passed in configs so the configuration can be applied to the
// default credential chain
cfg.MergeIn(cfgs...)
if cfg.EndpointResolver == nil {
// An endpoint resolver is required for a session to be able to provide
// endpoints for service client configurations.
cfg.EndpointResolver = endpoints.DefaultResolver()
}
if !(len(envCfg.EC2IMDSEndpoint) == 0 && envCfg.EC2IMDSEndpointMode == endpoints.EC2IMDSEndpointModeStateUnset) {
cfg.EndpointResolver = wrapEC2IMDSEndpoint(cfg.EndpointResolver, envCfg.EC2IMDSEndpoint, envCfg.EC2IMDSEndpointMode)
}
cfg.Credentials = defaults.CredChain(cfg, handlers)
// Reapply any passed in configs to override credentials if set
cfg.MergeIn(cfgs...)
s := &Session{
Config: cfg,
Handlers: handlers,
options: Options{
EC2IMDSEndpoint: envCfg.EC2IMDSEndpoint,
},
}
initHandlers(s)
return s
}
func enableCSM(handlers *request.Handlers, cfg csmConfig, logger aws.Logger) error {
if logger != nil {
logger.Log("Enabling CSM")
}
r, err := csm.Start(cfg.ClientID, csm.AddressWithDefaults(cfg.Host, cfg.Port))
if err != nil {
return err
}
r.InjectHandlers(handlers)
return nil
}
func newSession(opts Options, envCfg envConfig, cfgs ...*aws.Config) (*Session, error) {
cfg := defaults.Config()
handlers := opts.Handlers
if handlers.IsEmpty() {
handlers = defaults.Handlers()
}
// Get a merged version of the user provided config to determine if
// credentials were.
userCfg := &aws.Config{}
userCfg.MergeIn(cfgs...)
cfg.MergeIn(userCfg)
// Ordered config files will be loaded in with later files overwriting
// previous config file values.
var cfgFiles []string
if opts.SharedConfigFiles != nil {
cfgFiles = opts.SharedConfigFiles
} else {
cfgFiles = []string{envCfg.SharedConfigFile, envCfg.SharedCredentialsFile}
if !envCfg.EnableSharedConfig {
// The shared config file (~/.aws/config) is only loaded if instructed
// to load via the envConfig.EnableSharedConfig (AWS_SDK_LOAD_CONFIG).
cfgFiles = cfgFiles[1:]
}
}
// Load additional config from file(s)
sharedCfg, err := loadSharedConfig(envCfg.Profile, cfgFiles, envCfg.EnableSharedConfig)
if err != nil {
if len(envCfg.Profile) == 0 && !envCfg.EnableSharedConfig && (envCfg.Creds.HasKeys() || userCfg.Credentials != nil) {
// Special case where the user has not explicitly specified an AWS_PROFILE,
// or session.Options.profile, shared config is not enabled, and the
// environment has credentials, allow the shared config file to fail to
// load since the user has already provided credentials, and nothing else
// is required to be read file. Github(aws/aws-sdk-go#2455)
} else if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
return nil, err
}
}
if err := mergeConfigSrcs(cfg, userCfg, envCfg, sharedCfg, handlers, opts); err != nil {
return nil, err
}
if err := setTLSOptions(&opts, cfg, envCfg, sharedCfg); err != nil {
return nil, err
}
s := &Session{
Config: cfg,
Handlers: handlers,
options: opts,
}
initHandlers(s)
if csmCfg, err := loadCSMConfig(envCfg, cfgFiles); err != nil {
if l := s.Config.Logger; l != nil {
l.Log(fmt.Sprintf("ERROR: failed to load CSM configuration, %v", err))
}
} else if csmCfg.Enabled {
err = enableCSM(&s.Handlers, csmCfg, s.Config.Logger)
if err != nil {
return nil, err
}
}
return s, nil
}
type csmConfig struct {
Enabled bool
Host string
Port string
ClientID string
}
var csmProfileName = "aws_csm"
func loadCSMConfig(envCfg envConfig, cfgFiles []string) (csmConfig, error) {
if envCfg.CSMEnabled != nil {
if *envCfg.CSMEnabled {
return csmConfig{
Enabled: true,
ClientID: envCfg.CSMClientID,
Host: envCfg.CSMHost,
Port: envCfg.CSMPort,
}, nil
}
return csmConfig{}, nil
}
sharedCfg, err := loadSharedConfig(csmProfileName, cfgFiles, false)
if err != nil {
if _, ok := err.(SharedConfigProfileNotExistsError); !ok {
return csmConfig{}, err
}
}
if sharedCfg.CSMEnabled != nil && *sharedCfg.CSMEnabled == true {
return csmConfig{
Enabled: true,
ClientID: sharedCfg.CSMClientID,
Host: sharedCfg.CSMHost,
Port: sharedCfg.CSMPort,
}, nil
}
return csmConfig{}, nil
}
func setTLSOptions(opts *Options, cfg *aws.Config, envCfg envConfig, sharedCfg sharedConfig) error {
// CA Bundle can be specified in both environment variable shared config file.
var caBundleFilename = envCfg.CustomCABundle
if len(caBundleFilename) == 0 {
caBundleFilename = sharedCfg.CustomCABundle
}
// Only use environment value if session option is not provided.
customTLSOptions := map[string]struct {
filename string
field *io.Reader
errCode string
}{
"custom CA bundle PEM": {filename: caBundleFilename, field: &opts.CustomCABundle, errCode: ErrCodeLoadCustomCABundle},
"custom client TLS cert": {filename: envCfg.ClientTLSCert, field: &opts.ClientTLSCert, errCode: ErrCodeLoadClientTLSCert},
"custom client TLS key": {filename: envCfg.ClientTLSKey, field: &opts.ClientTLSKey, errCode: ErrCodeLoadClientTLSCert},
}
for name, v := range customTLSOptions {
if len(v.filename) != 0 && *v.field == nil {
f, err := os.Open(v.filename)
if err != nil {
return awserr.New(v.errCode, fmt.Sprintf("failed to open %s file", name), err)
}
defer f.Close()
*v.field = f
}
}
// Setup HTTP client with custom cert bundle if enabled
if opts.CustomCABundle != nil {
if err := loadCustomCABundle(cfg.HTTPClient, opts.CustomCABundle); err != nil {
return err
}
}
// Setup HTTP client TLS certificate and key for client TLS authentication.
if opts.ClientTLSCert != nil && opts.ClientTLSKey != nil {
if err := loadClientTLSCert(cfg.HTTPClient, opts.ClientTLSCert, opts.ClientTLSKey); err != nil {
return err
}
} else if opts.ClientTLSCert == nil && opts.ClientTLSKey == nil {
// Do nothing if neither values are available.
} else {
return awserr.New(ErrCodeLoadClientTLSCert,
fmt.Sprintf("client TLS cert(%t) and key(%t) must both be provided",
opts.ClientTLSCert != nil, opts.ClientTLSKey != nil), nil)
}
return nil
}
func getHTTPTransport(client *http.Client) (*http.Transport, error) {
var t *http.Transport
switch v := client.Transport.(type) {
case *http.Transport:
t = v
default:
if client.Transport != nil {
return nil, fmt.Errorf("unsupported transport, %T", client.Transport)
}
}
if t == nil {
// Nil transport implies `http.DefaultTransport` should be used. Since
// the SDK cannot modify, nor copy the `DefaultTransport` specifying
// the values the next closest behavior.
t = getCustomTransport()
}
return t, nil
}
func loadCustomCABundle(client *http.Client, bundle io.Reader) error {
t, err := getHTTPTransport(client)
if err != nil {
return awserr.New(ErrCodeLoadCustomCABundle,
"unable to load custom CA bundle, HTTPClient's transport unsupported type", err)
}
p, err := loadCertPool(bundle)
if err != nil {
return err
}
if t.TLSClientConfig == nil {
t.TLSClientConfig = &tls.Config{}
}
t.TLSClientConfig.RootCAs = p
client.Transport = t
return nil
}
func loadCertPool(r io.Reader) (*x509.CertPool, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, awserr.New(ErrCodeLoadCustomCABundle,
"failed to read custom CA bundle PEM file", err)
}
p := x509.NewCertPool()
if !p.AppendCertsFromPEM(b) {
return nil, awserr.New(ErrCodeLoadCustomCABundle,
"failed to load custom CA bundle PEM file", err)
}
return p, nil
}
func loadClientTLSCert(client *http.Client, certFile, keyFile io.Reader) error {
t, err := getHTTPTransport(client)
if err != nil {
return awserr.New(ErrCodeLoadClientTLSCert,
"unable to get usable HTTP transport from client", err)
}
cert, err := ioutil.ReadAll(certFile)
if err != nil {
return awserr.New(ErrCodeLoadClientTLSCert,
"unable to get read client TLS cert file", err)
}
key, err := ioutil.ReadAll(keyFile)
if err != nil {
return awserr.New(ErrCodeLoadClientTLSCert,
"unable to get read client TLS key file", err)
}
clientCert, err := tls.X509KeyPair(cert, key)
if err != nil {
return awserr.New(ErrCodeLoadClientTLSCert,
"unable to load x509 key pair from client cert", err)
}
tlsCfg := t.TLSClientConfig
if tlsCfg == nil {
tlsCfg = &tls.Config{}
}
tlsCfg.Certificates = append(tlsCfg.Certificates, clientCert)
t.TLSClientConfig = tlsCfg
client.Transport = t
return nil
}
func mergeConfigSrcs(cfg, userCfg *aws.Config,
envCfg envConfig, sharedCfg sharedConfig,
handlers request.Handlers,
sessOpts Options,
) error {
// Region if not already set by user
if len(aws.StringValue(cfg.Region)) == 0 {
if len(envCfg.Region) > 0 {
cfg.WithRegion(envCfg.Region)
} else if envCfg.EnableSharedConfig && len(sharedCfg.Region) > 0 {
cfg.WithRegion(sharedCfg.Region)
}
}
if cfg.EnableEndpointDiscovery == nil {
if envCfg.EnableEndpointDiscovery != nil {
cfg.WithEndpointDiscovery(*envCfg.EnableEndpointDiscovery)
} else if envCfg.EnableSharedConfig && sharedCfg.EnableEndpointDiscovery != nil {
cfg.WithEndpointDiscovery(*sharedCfg.EnableEndpointDiscovery)
}
}
// Regional Endpoint flag for STS endpoint resolving
mergeSTSRegionalEndpointConfig(cfg, []endpoints.STSRegionalEndpoint{
userCfg.STSRegionalEndpoint,
envCfg.STSRegionalEndpoint,
sharedCfg.STSRegionalEndpoint,
endpoints.LegacySTSEndpoint,
})
// Regional Endpoint flag for S3 endpoint resolving
mergeS3UsEast1RegionalEndpointConfig(cfg, []endpoints.S3UsEast1RegionalEndpoint{
userCfg.S3UsEast1RegionalEndpoint,
envCfg.S3UsEast1RegionalEndpoint,
sharedCfg.S3UsEast1RegionalEndpoint,
endpoints.LegacyS3UsEast1Endpoint,
})
var ec2IMDSEndpoint string
for _, v := range []string{
sessOpts.EC2IMDSEndpoint,
envCfg.EC2IMDSEndpoint,
sharedCfg.EC2IMDSEndpoint,
} {
if len(v) != 0 {
ec2IMDSEndpoint = v
break
}
}
var endpointMode endpoints.EC2IMDSEndpointModeState
for _, v := range []endpoints.EC2IMDSEndpointModeState{
sessOpts.EC2IMDSEndpointMode,
envCfg.EC2IMDSEndpointMode,
sharedCfg.EC2IMDSEndpointMode,
} {
if v != endpoints.EC2IMDSEndpointModeStateUnset {
endpointMode = v
break
}
}
if len(ec2IMDSEndpoint) != 0 || endpointMode != endpoints.EC2IMDSEndpointModeStateUnset {
cfg.EndpointResolver = wrapEC2IMDSEndpoint(cfg.EndpointResolver, ec2IMDSEndpoint, endpointMode)
}
// Configure credentials if not already set by the user when creating the
// Session.
if cfg.Credentials == credentials.AnonymousCredentials && userCfg.Credentials == nil {
creds, err := resolveCredentials(cfg, envCfg, sharedCfg, handlers, sessOpts)
if err != nil {
return err
}
cfg.Credentials = creds
}
cfg.S3UseARNRegion = userCfg.S3UseARNRegion
if cfg.S3UseARNRegion == nil {
cfg.S3UseARNRegion = &envCfg.S3UseARNRegion
}
if cfg.S3UseARNRegion == nil {
cfg.S3UseARNRegion = &sharedCfg.S3UseARNRegion
}
for _, v := range []endpoints.DualStackEndpointState{userCfg.UseDualStackEndpoint, envCfg.UseDualStackEndpoint, sharedCfg.UseDualStackEndpoint} {
if v != endpoints.DualStackEndpointStateUnset {
cfg.UseDualStackEndpoint = v
break
}
}
for _, v := range []endpoints.FIPSEndpointState{userCfg.UseFIPSEndpoint, envCfg.UseFIPSEndpoint, sharedCfg.UseFIPSEndpoint} {
if v != endpoints.FIPSEndpointStateUnset {
cfg.UseFIPSEndpoint = v
break
}
}
return nil
}
func mergeSTSRegionalEndpointConfig(cfg *aws.Config, values []endpoints.STSRegionalEndpoint) {
for _, v := range values {
if v != endpoints.UnsetSTSEndpoint {
cfg.STSRegionalEndpoint = v
break
}
}
}
func mergeS3UsEast1RegionalEndpointConfig(cfg *aws.Config, values []endpoints.S3UsEast1RegionalEndpoint) {
for _, v := range values {
if v != endpoints.UnsetS3UsEast1Endpoint {
cfg.S3UsEast1RegionalEndpoint = v
break
}
}
}
func initHandlers(s *Session) {
// Add the Validate parameter handler if it is not disabled.
s.Handlers.Validate.Remove(corehandlers.ValidateParametersHandler)
if !aws.BoolValue(s.Config.DisableParamValidation) {
s.Handlers.Validate.PushBackNamed(corehandlers.ValidateParametersHandler)
}
}
// Copy creates and returns a copy of the current Session, copying the config
// and handlers. If any additional configs are provided they will be merged
// on top of the Session's copied config.
//
// // Create a copy of the current Session, configured for the us-west-2 region.
// sess.Copy(&aws.Config{Region: aws.String("us-west-2")})
func (s *Session) Copy(cfgs ...*aws.Config) *Session {
newSession := &Session{
Config: s.Config.Copy(cfgs...),
Handlers: s.Handlers.Copy(),
options: s.options,
}
initHandlers(newSession)
return newSession
}
// ClientConfig satisfies the client.ConfigProvider interface and is used to
// configure the service client instances. Passing the Session to the service
// client's constructor (New) will use this method to configure the client.
func (s *Session) ClientConfig(service string, cfgs ...*aws.Config) client.Config {
s = s.Copy(cfgs...)
resolvedRegion := normalizeRegion(s.Config)
region := aws.StringValue(s.Config.Region)
resolved, err := s.resolveEndpoint(service, region, resolvedRegion, s.Config)
if err != nil {
s.Handlers.Validate.PushBack(func(r *request.Request) {
if len(r.ClientInfo.Endpoint) != 0 {
// Error occurred while resolving endpoint, but the request
// being invoked has had an endpoint specified after the client
// was created.
return
}
r.Error = err
})
}
return client.Config{
Config: s.Config,
Handlers: s.Handlers,
PartitionID: resolved.PartitionID,
Endpoint: resolved.URL,
SigningRegion: resolved.SigningRegion,
SigningNameDerived: resolved.SigningNameDerived,
SigningName: resolved.SigningName,
ResolvedRegion: resolvedRegion,
}
}
const ec2MetadataServiceID = "ec2metadata"
func (s *Session) resolveEndpoint(service, region, resolvedRegion string, cfg *aws.Config) (endpoints.ResolvedEndpoint, error) {
if ep := aws.StringValue(cfg.Endpoint); len(ep) != 0 {
return endpoints.ResolvedEndpoint{
URL: endpoints.AddScheme(ep, aws.BoolValue(cfg.DisableSSL)),
SigningRegion: region,
}, nil
}
resolved, err := cfg.EndpointResolver.EndpointFor(service, region,
func(opt *endpoints.Options) {
opt.DisableSSL = aws.BoolValue(cfg.DisableSSL)
opt.UseDualStack = aws.BoolValue(cfg.UseDualStack)
opt.UseDualStackEndpoint = cfg.UseDualStackEndpoint
opt.UseFIPSEndpoint = cfg.UseFIPSEndpoint
// Support for STSRegionalEndpoint where the STSRegionalEndpoint is
// provided in envConfig or sharedConfig with envConfig getting
// precedence.
opt.STSRegionalEndpoint = cfg.STSRegionalEndpoint
// Support for S3UsEast1RegionalEndpoint where the S3UsEast1RegionalEndpoint is
// provided in envConfig or sharedConfig with envConfig getting
// precedence.
opt.S3UsEast1RegionalEndpoint = cfg.S3UsEast1RegionalEndpoint
// Support the condition where the service is modeled but its
// endpoint metadata is not available.
opt.ResolveUnknownService = true
opt.ResolvedRegion = resolvedRegion
opt.Logger = cfg.Logger
opt.LogDeprecated = cfg.LogLevel.Matches(aws.LogDebugWithDeprecated)
},
)
if err != nil {
return endpoints.ResolvedEndpoint{}, err
}
return resolved, nil
}
// ClientConfigNoResolveEndpoint is the same as ClientConfig with the exception
// that the EndpointResolver will not be used to resolve the endpoint. The only
// endpoint set must come from the aws.Config.Endpoint field.
func (s *Session) ClientConfigNoResolveEndpoint(cfgs ...*aws.Config) client.Config {
s = s.Copy(cfgs...)
resolvedRegion := normalizeRegion(s.Config)
var resolved endpoints.ResolvedEndpoint
if ep := aws.StringValue(s.Config.Endpoint); len(ep) > 0 {
resolved.URL = endpoints.AddScheme(ep, aws.BoolValue(s.Config.DisableSSL))
resolved.SigningRegion = aws.StringValue(s.Config.Region)
}
return client.Config{
Config: s.Config,
Handlers: s.Handlers,
Endpoint: resolved.URL,
SigningRegion: resolved.SigningRegion,
SigningNameDerived: resolved.SigningNameDerived,
SigningName: resolved.SigningName,
ResolvedRegion: resolvedRegion,
}
}
// logDeprecatedNewSessionError function enables error handling for session
func (s *Session) logDeprecatedNewSessionError(msg string, err error, cfgs []*aws.Config) {
// Session creation failed, need to report the error and prevent
// any requests from succeeding.
s.Config.MergeIn(cfgs...)
s.Config.Logger.Log("ERROR:", msg, "Error:", err)
s.Handlers.Validate.PushBack(func(r *request.Request) {
r.Error = err
})
}
// normalizeRegion resolves / normalizes the configured region (converts pseudo fips regions), and modifies the provided
// config to have the equivalent options for resolution and returns the resolved region name.
func normalizeRegion(cfg *aws.Config) (resolved string) {
const fipsInfix = "-fips-"
const fipsPrefix = "-fips"
const fipsSuffix = "fips-"
region := aws.StringValue(cfg.Region)
if strings.Contains(region, fipsInfix) ||
strings.Contains(region, fipsPrefix) ||
strings.Contains(region, fipsSuffix) {
resolved = strings.Replace(strings.Replace(strings.Replace(
region, fipsInfix, "-", -1), fipsPrefix, "", -1), fipsSuffix, "", -1)
cfg.UseFIPSEndpoint = endpoints.FIPSEndpointStateEnabled
}
return resolved
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/session/shared_config.go
================================================
package session
import (
"fmt"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/internal/ini"
)
const (
// Static Credentials group
accessKeyIDKey = `aws_access_key_id` // group required
secretAccessKey = `aws_secret_access_key` // group required
sessionTokenKey = `aws_session_token` // optional
// Assume Role Credentials group
roleArnKey = `role_arn` // group required
sourceProfileKey = `source_profile` // group required (or credential_source)
credentialSourceKey = `credential_source` // group required (or source_profile)
externalIDKey = `external_id` // optional
mfaSerialKey = `mfa_serial` // optional
roleSessionNameKey = `role_session_name` // optional
roleDurationSecondsKey = "duration_seconds" // optional
// AWS Single Sign-On (AWS SSO) group
ssoAccountIDKey = "sso_account_id"
ssoRegionKey = "sso_region"
ssoRoleNameKey = "sso_role_name"
ssoStartURL = "sso_start_url"
// CSM options
csmEnabledKey = `csm_enabled`
csmHostKey = `csm_host`
csmPortKey = `csm_port`
csmClientIDKey = `csm_client_id`
// Additional Config fields
regionKey = `region`
// custom CA Bundle filename
customCABundleKey = `ca_bundle`
// endpoint discovery group
enableEndpointDiscoveryKey = `endpoint_discovery_enabled` // optional
// External Credential Process
credentialProcessKey = `credential_process` // optional
// Web Identity Token File
webIdentityTokenFileKey = `web_identity_token_file` // optional
// Additional config fields for regional or legacy endpoints
stsRegionalEndpointSharedKey = `sts_regional_endpoints`
// Additional config fields for regional or legacy endpoints
s3UsEast1RegionalSharedKey = `s3_us_east_1_regional_endpoint`
// DefaultSharedConfigProfile is the default profile to be used when
// loading configuration from the config files if another profile name
// is not provided.
DefaultSharedConfigProfile = `default`
// S3 ARN Region Usage
s3UseARNRegionKey = "s3_use_arn_region"
// EC2 IMDS Endpoint Mode
ec2MetadataServiceEndpointModeKey = "ec2_metadata_service_endpoint_mode"
// EC2 IMDS Endpoint
ec2MetadataServiceEndpointKey = "ec2_metadata_service_endpoint"
// Use DualStack Endpoint Resolution
useDualStackEndpoint = "use_dualstack_endpoint"
// Use FIPS Endpoint Resolution
useFIPSEndpointKey = "use_fips_endpoint"
)
// sharedConfig represents the configuration fields of the SDK config files.
type sharedConfig struct {
Profile string
// Credentials values from the config file. Both aws_access_key_id and
// aws_secret_access_key must be provided together in the same file to be
// considered valid. The values will be ignored if not a complete group.
// aws_session_token is an optional field that can be provided if both of
// the other two fields are also provided.
//
// aws_access_key_id
// aws_secret_access_key
// aws_session_token
Creds credentials.Value
CredentialSource string
CredentialProcess string
WebIdentityTokenFile string
SSOAccountID string
SSORegion string
SSORoleName string
SSOStartURL string
RoleARN string
RoleSessionName string
ExternalID string
MFASerial string
AssumeRoleDuration *time.Duration
SourceProfileName string
SourceProfile *sharedConfig
// Region is the region the SDK should use for looking up AWS service
// endpoints and signing requests.
//
// region
Region string
// CustomCABundle is the file path to a PEM file the SDK will read and
// use to configure the HTTP transport with additional CA certs that are
// not present in the platforms default CA store.
//
// This value will be ignored if the file does not exist.
//
// ca_bundle
CustomCABundle string
// EnableEndpointDiscovery can be enabled in the shared config by setting
// endpoint_discovery_enabled to true
//
// endpoint_discovery_enabled = true
EnableEndpointDiscovery *bool
// CSM Options
CSMEnabled *bool
CSMHost string
CSMPort string
CSMClientID string
// Specifies the Regional Endpoint flag for the SDK to resolve the endpoint for a service
//
// sts_regional_endpoints = regional
// This can take value as `LegacySTSEndpoint` or `RegionalSTSEndpoint`
STSRegionalEndpoint endpoints.STSRegionalEndpoint
// Specifies the Regional Endpoint flag for the SDK to resolve the endpoint for a service
//
// s3_us_east_1_regional_endpoint = regional
// This can take value as `LegacyS3UsEast1Endpoint` or `RegionalS3UsEast1Endpoint`
S3UsEast1RegionalEndpoint endpoints.S3UsEast1RegionalEndpoint
// Specifies if the S3 service should allow ARNs to direct the region
// the client's requests are sent to.
//
// s3_use_arn_region=true
S3UseARNRegion bool
// Specifies the EC2 Instance Metadata Service default endpoint selection mode (IPv4 or IPv6)
//
// ec2_metadata_service_endpoint_mode=IPv6
EC2IMDSEndpointMode endpoints.EC2IMDSEndpointModeState
// Specifies the EC2 Instance Metadata Service endpoint to use. If specified it overrides EC2IMDSEndpointMode.
//
// ec2_metadata_service_endpoint=http://fd00:ec2::254
EC2IMDSEndpoint string
// Specifies that SDK clients must resolve a dual-stack endpoint for
// services.
//
// use_dualstack_endpoint=true
UseDualStackEndpoint endpoints.DualStackEndpointState
// Specifies that SDK clients must resolve a FIPS endpoint for
// services.
//
// use_fips_endpoint=true
UseFIPSEndpoint endpoints.FIPSEndpointState
}
type sharedConfigFile struct {
Filename string
IniData ini.Sections
}
// loadSharedConfig retrieves the configuration from the list of files using
// the profile provided. The order the files are listed will determine
// precedence. Values in subsequent files will overwrite values defined in
// earlier files.
//
// For example, given two files A and B. Both define credentials. If the order
// of the files are A then B, B's credential values will be used instead of
// A's.
//
// See sharedConfig.setFromFile for information how the config files
// will be loaded.
func loadSharedConfig(profile string, filenames []string, exOpts bool) (sharedConfig, error) {
if len(profile) == 0 {
profile = DefaultSharedConfigProfile
}
files, err := loadSharedConfigIniFiles(filenames)
if err != nil {
return sharedConfig{}, err
}
cfg := sharedConfig{}
profiles := map[string]struct{}{}
if err = cfg.setFromIniFiles(profiles, profile, files, exOpts); err != nil {
return sharedConfig{}, err
}
return cfg, nil
}
func loadSharedConfigIniFiles(filenames []string) ([]sharedConfigFile, error) {
files := make([]sharedConfigFile, 0, len(filenames))
for _, filename := range filenames {
sections, err := ini.OpenFile(filename)
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == ini.ErrCodeUnableToReadFile {
// Skip files which can't be opened and read for whatever reason
continue
} else if err != nil {
return nil, SharedConfigLoadError{Filename: filename, Err: err}
}
files = append(files, sharedConfigFile{
Filename: filename, IniData: sections,
})
}
return files, nil
}
func (cfg *sharedConfig) setFromIniFiles(profiles map[string]struct{}, profile string, files []sharedConfigFile, exOpts bool) error {
cfg.Profile = profile
// Trim files from the list that don't exist.
var skippedFiles int
var profileNotFoundErr error
for _, f := range files {
if err := cfg.setFromIniFile(profile, f, exOpts); err != nil {
if _, ok := err.(SharedConfigProfileNotExistsError); ok {
// Ignore profiles not defined in individual files.
profileNotFoundErr = err
skippedFiles++
continue
}
return err
}
}
if skippedFiles == len(files) {
// If all files were skipped because the profile is not found, return
// the original profile not found error.
return profileNotFoundErr
}
if _, ok := profiles[profile]; ok {
// if this is the second instance of the profile the Assume Role
// options must be cleared because they are only valid for the
// first reference of a profile. The self linked instance of the
// profile only have credential provider options.
cfg.clearAssumeRoleOptions()
} else {
// First time a profile has been seen, It must either be a assume role
// credentials, or SSO. Assert if the credential type requires a role ARN,
// the ARN is also set, or validate that the SSO configuration is complete.
if err := cfg.validateCredentialsConfig(profile); err != nil {
return err
}
}
profiles[profile] = struct{}{}
if err := cfg.validateCredentialType(); err != nil {
return err
}
// Link source profiles for assume roles
if len(cfg.SourceProfileName) != 0 {
// Linked profile via source_profile ignore credential provider
// options, the source profile must provide the credentials.
cfg.clearCredentialOptions()
srcCfg := &sharedConfig{}
err := srcCfg.setFromIniFiles(profiles, cfg.SourceProfileName, files, exOpts)
if err != nil {
// SourceProfile that doesn't exist is an error in configuration.
if _, ok := err.(SharedConfigProfileNotExistsError); ok {
err = SharedConfigAssumeRoleError{
RoleARN: cfg.RoleARN,
SourceProfile: cfg.SourceProfileName,
}
}
return err
}
if !srcCfg.hasCredentials() {
return SharedConfigAssumeRoleError{
RoleARN: cfg.RoleARN,
SourceProfile: cfg.SourceProfileName,
}
}
cfg.SourceProfile = srcCfg
}
return nil
}
// setFromFile loads the configuration from the file using the profile
// provided. A sharedConfig pointer type value is used so that multiple config
// file loadings can be chained.
//
// Only loads complete logically grouped values, and will not set fields in cfg
// for incomplete grouped values in the config. Such as credentials. For
// example if a config file only includes aws_access_key_id but no
// aws_secret_access_key the aws_access_key_id will be ignored.
func (cfg *sharedConfig) setFromIniFile(profile string, file sharedConfigFile, exOpts bool) error {
section, ok := file.IniData.GetSection(profile)
if !ok {
// Fallback to to alternate profile name: profile
section, ok = file.IniData.GetSection(fmt.Sprintf("profile %s", profile))
if !ok {
return SharedConfigProfileNotExistsError{Profile: profile, Err: nil}
}
}
if exOpts {
// Assume Role Parameters
updateString(&cfg.RoleARN, section, roleArnKey)
updateString(&cfg.ExternalID, section, externalIDKey)
updateString(&cfg.MFASerial, section, mfaSerialKey)
updateString(&cfg.RoleSessionName, section, roleSessionNameKey)
updateString(&cfg.SourceProfileName, section, sourceProfileKey)
updateString(&cfg.CredentialSource, section, credentialSourceKey)
updateString(&cfg.Region, section, regionKey)
updateString(&cfg.CustomCABundle, section, customCABundleKey)
if section.Has(roleDurationSecondsKey) {
d := time.Duration(section.Int(roleDurationSecondsKey)) * time.Second
cfg.AssumeRoleDuration = &d
}
if v := section.String(stsRegionalEndpointSharedKey); len(v) != 0 {
sre, err := endpoints.GetSTSRegionalEndpoint(v)
if err != nil {
return fmt.Errorf("failed to load %s from shared config, %s, %v",
stsRegionalEndpointSharedKey, file.Filename, err)
}
cfg.STSRegionalEndpoint = sre
}
if v := section.String(s3UsEast1RegionalSharedKey); len(v) != 0 {
sre, err := endpoints.GetS3UsEast1RegionalEndpoint(v)
if err != nil {
return fmt.Errorf("failed to load %s from shared config, %s, %v",
s3UsEast1RegionalSharedKey, file.Filename, err)
}
cfg.S3UsEast1RegionalEndpoint = sre
}
// AWS Single Sign-On (AWS SSO)
updateString(&cfg.SSOAccountID, section, ssoAccountIDKey)
updateString(&cfg.SSORegion, section, ssoRegionKey)
updateString(&cfg.SSORoleName, section, ssoRoleNameKey)
updateString(&cfg.SSOStartURL, section, ssoStartURL)
if err := updateEC2MetadataServiceEndpointMode(&cfg.EC2IMDSEndpointMode, section, ec2MetadataServiceEndpointModeKey); err != nil {
return fmt.Errorf("failed to load %s from shared config, %s, %v",
ec2MetadataServiceEndpointModeKey, file.Filename, err)
}
updateString(&cfg.EC2IMDSEndpoint, section, ec2MetadataServiceEndpointKey)
updateUseDualStackEndpoint(&cfg.UseDualStackEndpoint, section, useDualStackEndpoint)
updateUseFIPSEndpoint(&cfg.UseFIPSEndpoint, section, useFIPSEndpointKey)
}
updateString(&cfg.CredentialProcess, section, credentialProcessKey)
updateString(&cfg.WebIdentityTokenFile, section, webIdentityTokenFileKey)
// Shared Credentials
creds := credentials.Value{
AccessKeyID: section.String(accessKeyIDKey),
SecretAccessKey: section.String(secretAccessKey),
SessionToken: section.String(sessionTokenKey),
ProviderName: fmt.Sprintf("SharedConfigCredentials: %s", file.Filename),
}
if creds.HasKeys() {
cfg.Creds = creds
}
// Endpoint discovery
updateBoolPtr(&cfg.EnableEndpointDiscovery, section, enableEndpointDiscoveryKey)
// CSM options
updateBoolPtr(&cfg.CSMEnabled, section, csmEnabledKey)
updateString(&cfg.CSMHost, section, csmHostKey)
updateString(&cfg.CSMPort, section, csmPortKey)
updateString(&cfg.CSMClientID, section, csmClientIDKey)
updateBool(&cfg.S3UseARNRegion, section, s3UseARNRegionKey)
return nil
}
func updateEC2MetadataServiceEndpointMode(endpointMode *endpoints.EC2IMDSEndpointModeState, section ini.Section, key string) error {
if !section.Has(key) {
return nil
}
value := section.String(key)
return endpointMode.SetFromString(value)
}
func (cfg *sharedConfig) validateCredentialsConfig(profile string) error {
if err := cfg.validateCredentialsRequireARN(profile); err != nil {
return err
}
return nil
}
func (cfg *sharedConfig) validateCredentialsRequireARN(profile string) error {
var credSource string
switch {
case len(cfg.SourceProfileName) != 0:
credSource = sourceProfileKey
case len(cfg.CredentialSource) != 0:
credSource = credentialSourceKey
case len(cfg.WebIdentityTokenFile) != 0:
credSource = webIdentityTokenFileKey
}
if len(credSource) != 0 && len(cfg.RoleARN) == 0 {
return CredentialRequiresARNError{
Type: credSource,
Profile: profile,
}
}
return nil
}
func (cfg *sharedConfig) validateCredentialType() error {
// Only one or no credential type can be defined.
if !oneOrNone(
len(cfg.SourceProfileName) != 0,
len(cfg.CredentialSource) != 0,
len(cfg.CredentialProcess) != 0,
len(cfg.WebIdentityTokenFile) != 0,
) {
return ErrSharedConfigSourceCollision
}
return nil
}
func (cfg *sharedConfig) validateSSOConfiguration() error {
if !cfg.hasSSOConfiguration() {
return nil
}
var missing []string
if len(cfg.SSOAccountID) == 0 {
missing = append(missing, ssoAccountIDKey)
}
if len(cfg.SSORegion) == 0 {
missing = append(missing, ssoRegionKey)
}
if len(cfg.SSORoleName) == 0 {
missing = append(missing, ssoRoleNameKey)
}
if len(cfg.SSOStartURL) == 0 {
missing = append(missing, ssoStartURL)
}
if len(missing) > 0 {
return fmt.Errorf("profile %q is configured to use SSO but is missing required configuration: %s",
cfg.Profile, strings.Join(missing, ", "))
}
return nil
}
func (cfg *sharedConfig) hasCredentials() bool {
switch {
case len(cfg.SourceProfileName) != 0:
case len(cfg.CredentialSource) != 0:
case len(cfg.CredentialProcess) != 0:
case len(cfg.WebIdentityTokenFile) != 0:
case cfg.hasSSOConfiguration():
case cfg.Creds.HasKeys():
default:
return false
}
return true
}
func (cfg *sharedConfig) clearCredentialOptions() {
cfg.CredentialSource = ""
cfg.CredentialProcess = ""
cfg.WebIdentityTokenFile = ""
cfg.Creds = credentials.Value{}
cfg.SSOAccountID = ""
cfg.SSORegion = ""
cfg.SSORoleName = ""
cfg.SSOStartURL = ""
}
func (cfg *sharedConfig) clearAssumeRoleOptions() {
cfg.RoleARN = ""
cfg.ExternalID = ""
cfg.MFASerial = ""
cfg.RoleSessionName = ""
cfg.SourceProfileName = ""
}
func (cfg *sharedConfig) hasSSOConfiguration() bool {
switch {
case len(cfg.SSOAccountID) != 0:
case len(cfg.SSORegion) != 0:
case len(cfg.SSORoleName) != 0:
case len(cfg.SSOStartURL) != 0:
default:
return false
}
return true
}
func oneOrNone(bs ...bool) bool {
var count int
for _, b := range bs {
if b {
count++
if count > 1 {
return false
}
}
}
return true
}
// updateString will only update the dst with the value in the section key, key
// is present in the section.
func updateString(dst *string, section ini.Section, key string) {
if !section.Has(key) {
return
}
*dst = section.String(key)
}
// updateBool will only update the dst with the value in the section key, key
// is present in the section.
func updateBool(dst *bool, section ini.Section, key string) {
if !section.Has(key) {
return
}
*dst = section.Bool(key)
}
// updateBoolPtr will only update the dst with the value in the section key,
// key is present in the section.
func updateBoolPtr(dst **bool, section ini.Section, key string) {
if !section.Has(key) {
return
}
*dst = new(bool)
**dst = section.Bool(key)
}
// SharedConfigLoadError is an error for the shared config file failed to load.
type SharedConfigLoadError struct {
Filename string
Err error
}
// Code is the short id of the error.
func (e SharedConfigLoadError) Code() string {
return "SharedConfigLoadError"
}
// Message is the description of the error
func (e SharedConfigLoadError) Message() string {
return fmt.Sprintf("failed to load config file, %s", e.Filename)
}
// OrigErr is the underlying error that caused the failure.
func (e SharedConfigLoadError) OrigErr() error {
return e.Err
}
// Error satisfies the error interface.
func (e SharedConfigLoadError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
}
// SharedConfigProfileNotExistsError is an error for the shared config when
// the profile was not find in the config file.
type SharedConfigProfileNotExistsError struct {
Profile string
Err error
}
// Code is the short id of the error.
func (e SharedConfigProfileNotExistsError) Code() string {
return "SharedConfigProfileNotExistsError"
}
// Message is the description of the error
func (e SharedConfigProfileNotExistsError) Message() string {
return fmt.Sprintf("failed to get profile, %s", e.Profile)
}
// OrigErr is the underlying error that caused the failure.
func (e SharedConfigProfileNotExistsError) OrigErr() error {
return e.Err
}
// Error satisfies the error interface.
func (e SharedConfigProfileNotExistsError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", e.Err)
}
// SharedConfigAssumeRoleError is an error for the shared config when the
// profile contains assume role information, but that information is invalid
// or not complete.
type SharedConfigAssumeRoleError struct {
RoleARN string
SourceProfile string
}
// Code is the short id of the error.
func (e SharedConfigAssumeRoleError) Code() string {
return "SharedConfigAssumeRoleError"
}
// Message is the description of the error
func (e SharedConfigAssumeRoleError) Message() string {
return fmt.Sprintf(
"failed to load assume role for %s, source profile %s has no shared credentials",
e.RoleARN, e.SourceProfile,
)
}
// OrigErr is the underlying error that caused the failure.
func (e SharedConfigAssumeRoleError) OrigErr() error {
return nil
}
// Error satisfies the error interface.
func (e SharedConfigAssumeRoleError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", nil)
}
// CredentialRequiresARNError provides the error for shared config credentials
// that are incorrectly configured in the shared config or credentials file.
type CredentialRequiresARNError struct {
// type of credentials that were configured.
Type string
// Profile name the credentials were in.
Profile string
}
// Code is the short id of the error.
func (e CredentialRequiresARNError) Code() string {
return "CredentialRequiresARNError"
}
// Message is the description of the error
func (e CredentialRequiresARNError) Message() string {
return fmt.Sprintf(
"credential type %s requires role_arn, profile %s",
e.Type, e.Profile,
)
}
// OrigErr is the underlying error that caused the failure.
func (e CredentialRequiresARNError) OrigErr() error {
return nil
}
// Error satisfies the error interface.
func (e CredentialRequiresARNError) Error() string {
return awserr.SprintError(e.Code(), e.Message(), "", nil)
}
// updateEndpointDiscoveryType will only update the dst with the value in the section, if
// a valid key and corresponding EndpointDiscoveryType is found.
func updateUseDualStackEndpoint(dst *endpoints.DualStackEndpointState, section ini.Section, key string) {
if !section.Has(key) {
return
}
if section.Bool(key) {
*dst = endpoints.DualStackEndpointStateEnabled
} else {
*dst = endpoints.DualStackEndpointStateDisabled
}
return
}
// updateEndpointDiscoveryType will only update the dst with the value in the section, if
// a valid key and corresponding EndpointDiscoveryType is found.
func updateUseFIPSEndpoint(dst *endpoints.FIPSEndpointState, section ini.Section, key string) {
if !section.Has(key) {
return
}
if section.Bool(key) {
*dst = endpoints.FIPSEndpointStateEnabled
} else {
*dst = endpoints.FIPSEndpointStateDisabled
}
return
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/header_rules.go
================================================
package v4
import (
"github.com/aws/aws-sdk-go/internal/strings"
)
// validator houses a set of rule needed for validation of a
// string value
type rules []rule
// rule interface allows for more flexible rules and just simply
// checks whether or not a value adheres to that rule
type rule interface {
IsValid(value string) bool
}
// IsValid will iterate through all rules and see if any rules
// apply to the value and supports nested rules
func (r rules) IsValid(value string) bool {
for _, rule := range r {
if rule.IsValid(value) {
return true
}
}
return false
}
// mapRule generic rule for maps
type mapRule map[string]struct{}
// IsValid for the map rule satisfies whether it exists in the map
func (m mapRule) IsValid(value string) bool {
_, ok := m[value]
return ok
}
// allowList is a generic rule for allow listing
type allowList struct {
rule
}
// IsValid for allow list checks if the value is within the allow list
func (w allowList) IsValid(value string) bool {
return w.rule.IsValid(value)
}
// excludeList is a generic rule for exclude listing
type excludeList struct {
rule
}
// IsValid for exclude list checks if the value is within the exclude list
func (b excludeList) IsValid(value string) bool {
return !b.rule.IsValid(value)
}
type patterns []string
// IsValid for patterns checks each pattern and returns if a match has
// been found
func (p patterns) IsValid(value string) bool {
for _, pattern := range p {
if strings.HasPrefixFold(value, pattern) {
return true
}
}
return false
}
// inclusiveRules rules allow for rules to depend on one another
type inclusiveRules []rule
// IsValid will return true if all rules are true
func (r inclusiveRules) IsValid(value string) bool {
for _, rule := range r {
if !rule.IsValid(value) {
return false
}
}
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/options.go
================================================
package v4
// WithUnsignedPayload will enable and set the UnsignedPayload field to
// true of the signer.
func WithUnsignedPayload(v4 *Signer) {
v4.UnsignedPayload = true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/request_context_go1.5.go
================================================
//go:build !go1.7
// +build !go1.7
package v4
import (
"net/http"
"github.com/aws/aws-sdk-go/aws"
)
func requestContext(r *http.Request) aws.Context {
return aws.BackgroundContext()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/request_context_go1.7.go
================================================
//go:build go1.7
// +build go1.7
package v4
import (
"net/http"
"github.com/aws/aws-sdk-go/aws"
)
func requestContext(r *http.Request) aws.Context {
return r.Context()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/stream.go
================================================
package v4
import (
"encoding/hex"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/credentials"
)
type credentialValueProvider interface {
Get() (credentials.Value, error)
}
// StreamSigner implements signing of event stream encoded payloads
type StreamSigner struct {
region string
service string
credentials credentialValueProvider
prevSig []byte
}
// NewStreamSigner creates a SigV4 signer used to sign Event Stream encoded messages
func NewStreamSigner(region, service string, seedSignature []byte, credentials *credentials.Credentials) *StreamSigner {
return &StreamSigner{
region: region,
service: service,
credentials: credentials,
prevSig: seedSignature,
}
}
// GetSignature takes an event stream encoded headers and payload and returns a signature
func (s *StreamSigner) GetSignature(headers, payload []byte, date time.Time) ([]byte, error) {
credValue, err := s.credentials.Get()
if err != nil {
return nil, err
}
sigKey := deriveSigningKey(s.region, s.service, credValue.SecretAccessKey, date)
keyPath := buildSigningScope(s.region, s.service, date)
stringToSign := buildEventStreamStringToSign(headers, payload, s.prevSig, keyPath, date)
signature := hmacSHA256(sigKey, []byte(stringToSign))
s.prevSig = signature
return signature, nil
}
func buildEventStreamStringToSign(headers, payload, prevSig []byte, scope string, date time.Time) string {
return strings.Join([]string{
"AWS4-HMAC-SHA256-PAYLOAD",
formatTime(date),
scope,
hex.EncodeToString(prevSig),
hex.EncodeToString(hashSHA256(headers)),
hex.EncodeToString(hashSHA256(payload)),
}, "\n")
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/uri_path.go
================================================
//go:build go1.5
// +build go1.5
package v4
import (
"net/url"
"strings"
)
func getURIPath(u *url.URL) string {
var uri string
if len(u.Opaque) > 0 {
uri = "/" + strings.Join(strings.Split(u.Opaque, "/")[3:], "/")
} else {
uri = u.EscapedPath()
}
if len(uri) == 0 {
uri = "/"
}
return uri
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/signer/v4/v4.go
================================================
// Package v4 implements signing for AWS V4 signer
//
// Provides request signing for request that need to be signed with
// AWS V4 Signatures.
//
// Standalone Signer
//
// Generally using the signer outside of the SDK should not require any additional
// logic when using Go v1.5 or higher. The signer does this by taking advantage
// of the URL.EscapedPath method. If your request URI requires additional escaping
// you many need to use the URL.Opaque to define what the raw URI should be sent
// to the service as.
//
// The signer will first check the URL.Opaque field, and use its value if set.
// The signer does require the URL.Opaque field to be set in the form of:
//
// "///"
//
// // e.g.
// "//example.com/some/path"
//
// The leading "//" and hostname are required or the URL.Opaque escaping will
// not work correctly.
//
// If URL.Opaque is not set the signer will fallback to the URL.EscapedPath()
// method and using the returned value. If you're using Go v1.4 you must set
// URL.Opaque if the URI path needs escaping. If URL.Opaque is not set with
// Go v1.5 the signer will fallback to URL.Path.
//
// AWS v4 signature validation requires that the canonical string's URI path
// element must be the URI escaped form of the HTTP request's path.
// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
//
// The Go HTTP client will perform escaping automatically on the request. Some
// of these escaping may cause signature validation errors because the HTTP
// request differs from the URI path or query that the signature was generated.
// https://golang.org/pkg/net/url/#URL.EscapedPath
//
// Because of this, it is recommended that when using the signer outside of the
// SDK that explicitly escaping the request prior to being signed is preferable,
// and will help prevent signature validation errors. This can be done by setting
// the URL.Opaque or URL.RawPath. The SDK will use URL.Opaque first and then
// call URL.EscapedPath() if Opaque is not set.
//
// If signing a request intended for HTTP2 server, and you're using Go 1.6.2
// through 1.7.4 you should use the URL.RawPath as the pre-escaped form of the
// request URL. https://github.com/golang/go/issues/16847 points to a bug in
// Go pre 1.8 that fails to make HTTP2 requests using absolute URL in the HTTP
// message. URL.Opaque generally will force Go to make requests with absolute URL.
// URL.RawPath does not do this, but RawPath must be a valid escaping of Path
// or url.EscapedPath will ignore the RawPath escaping.
//
// Test `TestStandaloneSign` provides a complete example of using the signer
// outside of the SDK and pre-escaping the URI path.
package v4
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"sort"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/internal/sdkio"
"github.com/aws/aws-sdk-go/private/protocol/rest"
)
const (
authorizationHeader = "Authorization"
authHeaderSignatureElem = "Signature="
signatureQueryKey = "X-Amz-Signature"
authHeaderPrefix = "AWS4-HMAC-SHA256"
timeFormat = "20060102T150405Z"
shortTimeFormat = "20060102"
awsV4Request = "aws4_request"
// emptyStringSHA256 is a SHA256 of an empty string
emptyStringSHA256 = `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`
)
var ignoredHeaders = rules{
excludeList{
mapRule{
authorizationHeader: struct{}{},
"User-Agent": struct{}{},
"X-Amzn-Trace-Id": struct{}{},
},
},
}
// requiredSignedHeaders is a allow list for build canonical headers.
var requiredSignedHeaders = rules{
allowList{
mapRule{
"Cache-Control": struct{}{},
"Content-Disposition": struct{}{},
"Content-Encoding": struct{}{},
"Content-Language": struct{}{},
"Content-Md5": struct{}{},
"Content-Type": struct{}{},
"Expires": struct{}{},
"If-Match": struct{}{},
"If-Modified-Since": struct{}{},
"If-None-Match": struct{}{},
"If-Unmodified-Since": struct{}{},
"Range": struct{}{},
"X-Amz-Acl": struct{}{},
"X-Amz-Copy-Source": struct{}{},
"X-Amz-Copy-Source-If-Match": struct{}{},
"X-Amz-Copy-Source-If-Modified-Since": struct{}{},
"X-Amz-Copy-Source-If-None-Match": struct{}{},
"X-Amz-Copy-Source-If-Unmodified-Since": struct{}{},
"X-Amz-Copy-Source-Range": struct{}{},
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Algorithm": struct{}{},
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key": struct{}{},
"X-Amz-Copy-Source-Server-Side-Encryption-Customer-Key-Md5": struct{}{},
"X-Amz-Grant-Full-control": struct{}{},
"X-Amz-Grant-Read": struct{}{},
"X-Amz-Grant-Read-Acp": struct{}{},
"X-Amz-Grant-Write": struct{}{},
"X-Amz-Grant-Write-Acp": struct{}{},
"X-Amz-Metadata-Directive": struct{}{},
"X-Amz-Mfa": struct{}{},
"X-Amz-Request-Payer": struct{}{},
"X-Amz-Server-Side-Encryption": struct{}{},
"X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": struct{}{},
"X-Amz-Server-Side-Encryption-Customer-Algorithm": struct{}{},
"X-Amz-Server-Side-Encryption-Customer-Key": struct{}{},
"X-Amz-Server-Side-Encryption-Customer-Key-Md5": struct{}{},
"X-Amz-Storage-Class": struct{}{},
"X-Amz-Tagging": struct{}{},
"X-Amz-Website-Redirect-Location": struct{}{},
"X-Amz-Content-Sha256": struct{}{},
},
},
patterns{"X-Amz-Meta-"},
patterns{"X-Amz-Object-Lock-"},
}
// allowedHoisting is a allow list for build query headers. The boolean value
// represents whether or not it is a pattern.
var allowedQueryHoisting = inclusiveRules{
excludeList{requiredSignedHeaders},
patterns{"X-Amz-"},
}
// Signer applies AWS v4 signing to given request. Use this to sign requests
// that need to be signed with AWS V4 Signatures.
type Signer struct {
// The authentication credentials the request will be signed against.
// This value must be set to sign requests.
Credentials *credentials.Credentials
// Sets the log level the signer should use when reporting information to
// the logger. If the logger is nil nothing will be logged. See
// aws.LogLevelType for more information on available logging levels
//
// By default nothing will be logged.
Debug aws.LogLevelType
// The logger loging information will be written to. If there the logger
// is nil, nothing will be logged.
Logger aws.Logger
// Disables the Signer's moving HTTP header key/value pairs from the HTTP
// request header to the request's query string. This is most commonly used
// with pre-signed requests preventing headers from being added to the
// request's query string.
DisableHeaderHoisting bool
// Disables the automatic escaping of the URI path of the request for the
// siganture's canonical string's path. For services that do not need additional
// escaping then use this to disable the signer escaping the path.
//
// S3 is an example of a service that does not need additional escaping.
//
// http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
DisableURIPathEscaping bool
// Disables the automatical setting of the HTTP request's Body field with the
// io.ReadSeeker passed in to the signer. This is useful if you're using a
// custom wrapper around the body for the io.ReadSeeker and want to preserve
// the Body value on the Request.Body.
//
// This does run the risk of signing a request with a body that will not be
// sent in the request. Need to ensure that the underlying data of the Body
// values are the same.
DisableRequestBodyOverwrite bool
// currentTimeFn returns the time value which represents the current time.
// This value should only be used for testing. If it is nil the default
// time.Now will be used.
currentTimeFn func() time.Time
// UnsignedPayload will prevent signing of the payload. This will only
// work for services that have support for this.
UnsignedPayload bool
}
// NewSigner returns a Signer pointer configured with the credentials and optional
// option values provided. If not options are provided the Signer will use its
// default configuration.
func NewSigner(credentials *credentials.Credentials, options ...func(*Signer)) *Signer {
v4 := &Signer{
Credentials: credentials,
}
for _, option := range options {
option(v4)
}
return v4
}
type signingCtx struct {
ServiceName string
Region string
Request *http.Request
Body io.ReadSeeker
Query url.Values
Time time.Time
ExpireTime time.Duration
SignedHeaderVals http.Header
DisableURIPathEscaping bool
credValues credentials.Value
isPresign bool
unsignedPayload bool
bodyDigest string
signedHeaders string
canonicalHeaders string
canonicalString string
credentialString string
stringToSign string
signature string
authorization string
}
// Sign signs AWS v4 requests with the provided body, service name, region the
// request is made to, and time the request is signed at. The signTime allows
// you to specify that a request is signed for the future, and cannot be
// used until then.
//
// Returns a list of HTTP headers that were included in the signature or an
// error if signing the request failed. Generally for signed requests this value
// is not needed as the full request context will be captured by the http.Request
// value. It is included for reference though.
//
// Sign will set the request's Body to be the `body` parameter passed in. If
// the body is not already an io.ReadCloser, it will be wrapped within one. If
// a `nil` body parameter passed to Sign, the request's Body field will be
// also set to nil. Its important to note that this functionality will not
// change the request's ContentLength of the request.
//
// Sign differs from Presign in that it will sign the request using HTTP
// header values. This type of signing is intended for http.Request values that
// will not be shared, or are shared in a way the header values on the request
// will not be lost.
//
// The requests body is an io.ReadSeeker so the SHA256 of the body can be
// generated. To bypass the signer computing the hash you can set the
// "X-Amz-Content-Sha256" header with a precomputed value. The signer will
// only compute the hash if the request header value is empty.
func (v4 Signer) Sign(r *http.Request, body io.ReadSeeker, service, region string, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, 0, false, signTime)
}
// Presign signs AWS v4 requests with the provided body, service name, region
// the request is made to, and time the request is signed at. The signTime
// allows you to specify that a request is signed for the future, and cannot
// be used until then.
//
// Returns a list of HTTP headers that were included in the signature or an
// error if signing the request failed. For presigned requests these headers
// and their values must be included on the HTTP request when it is made. This
// is helpful to know what header values need to be shared with the party the
// presigned request will be distributed to.
//
// Presign differs from Sign in that it will sign the request using query string
// instead of header values. This allows you to share the Presigned Request's
// URL with third parties, or distribute it throughout your system with minimal
// dependencies.
//
// Presign also takes an exp value which is the duration the
// signed request will be valid after the signing time. This is allows you to
// set when the request will expire.
//
// The requests body is an io.ReadSeeker so the SHA256 of the body can be
// generated. To bypass the signer computing the hash you can set the
// "X-Amz-Content-Sha256" header with a precomputed value. The signer will
// only compute the hash if the request header value is empty.
//
// Presigning a S3 request will not compute the body's SHA256 hash by default.
// This is done due to the general use case for S3 presigned URLs is to share
// PUT/GET capabilities. If you would like to include the body's SHA256 in the
// presigned request's signature you can set the "X-Amz-Content-Sha256"
// HTTP header and that will be included in the request's signature.
func (v4 Signer) Presign(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, signTime time.Time) (http.Header, error) {
return v4.signWithBody(r, body, service, region, exp, true, signTime)
}
func (v4 Signer) signWithBody(r *http.Request, body io.ReadSeeker, service, region string, exp time.Duration, isPresign bool, signTime time.Time) (http.Header, error) {
currentTimeFn := v4.currentTimeFn
if currentTimeFn == nil {
currentTimeFn = time.Now
}
ctx := &signingCtx{
Request: r,
Body: body,
Query: r.URL.Query(),
Time: signTime,
ExpireTime: exp,
isPresign: isPresign,
ServiceName: service,
Region: region,
DisableURIPathEscaping: v4.DisableURIPathEscaping,
unsignedPayload: v4.UnsignedPayload,
}
for key := range ctx.Query {
sort.Strings(ctx.Query[key])
}
if ctx.isRequestSigned() {
ctx.Time = currentTimeFn()
ctx.handlePresignRemoval()
}
var err error
ctx.credValues, err = v4.Credentials.GetWithContext(requestContext(r))
if err != nil {
return http.Header{}, err
}
ctx.sanitizeHostForHeader()
ctx.assignAmzQueryValues()
if err := ctx.build(v4.DisableHeaderHoisting); err != nil {
return nil, err
}
// If the request is not presigned the body should be attached to it. This
// prevents the confusion of wanting to send a signed request without
// the body the request was signed for attached.
if !(v4.DisableRequestBodyOverwrite || ctx.isPresign) {
var reader io.ReadCloser
if body != nil {
var ok bool
if reader, ok = body.(io.ReadCloser); !ok {
reader = ioutil.NopCloser(body)
}
}
r.Body = reader
}
if v4.Debug.Matches(aws.LogDebugWithSigning) {
v4.logSigningInfo(ctx)
}
return ctx.SignedHeaderVals, nil
}
func (ctx *signingCtx) sanitizeHostForHeader() {
request.SanitizeHostForHeader(ctx.Request)
}
func (ctx *signingCtx) handlePresignRemoval() {
if !ctx.isPresign {
return
}
// The credentials have expired for this request. The current signing
// is invalid, and needs to be request because the request will fail.
ctx.removePresign()
// Update the request's query string to ensure the values stays in
// sync in the case retrieving the new credentials fails.
ctx.Request.URL.RawQuery = ctx.Query.Encode()
}
func (ctx *signingCtx) assignAmzQueryValues() {
if ctx.isPresign {
ctx.Query.Set("X-Amz-Algorithm", authHeaderPrefix)
if ctx.credValues.SessionToken != "" {
ctx.Query.Set("X-Amz-Security-Token", ctx.credValues.SessionToken)
} else {
ctx.Query.Del("X-Amz-Security-Token")
}
return
}
if ctx.credValues.SessionToken != "" {
ctx.Request.Header.Set("X-Amz-Security-Token", ctx.credValues.SessionToken)
}
}
// SignRequestHandler is a named request handler the SDK will use to sign
// service client request with using the V4 signature.
var SignRequestHandler = request.NamedHandler{
Name: "v4.SignRequestHandler", Fn: SignSDKRequest,
}
// SignSDKRequest signs an AWS request with the V4 signature. This
// request handler should only be used with the SDK's built in service client's
// API operation requests.
//
// This function should not be used on its own, but in conjunction with
// an AWS service client's API operation call. To sign a standalone request
// not created by a service client's API operation method use the "Sign" or
// "Presign" functions of the "Signer" type.
//
// If the credentials of the request's config are set to
// credentials.AnonymousCredentials the request will not be signed.
func SignSDKRequest(req *request.Request) {
SignSDKRequestWithCurrentTime(req, time.Now)
}
// BuildNamedHandler will build a generic handler for signing.
func BuildNamedHandler(name string, opts ...func(*Signer)) request.NamedHandler {
return request.NamedHandler{
Name: name,
Fn: func(req *request.Request) {
SignSDKRequestWithCurrentTime(req, time.Now, opts...)
},
}
}
// SignSDKRequestWithCurrentTime will sign the SDK's request using the time
// function passed in. Behaves the same as SignSDKRequest with the exception
// the request is signed with the value returned by the current time function.
func SignSDKRequestWithCurrentTime(req *request.Request, curTimeFn func() time.Time, opts ...func(*Signer)) {
// If the request does not need to be signed ignore the signing of the
// request if the AnonymousCredentials object is used.
if req.Config.Credentials == credentials.AnonymousCredentials {
return
}
region := req.ClientInfo.SigningRegion
if region == "" {
region = aws.StringValue(req.Config.Region)
}
name := req.ClientInfo.SigningName
if name == "" {
name = req.ClientInfo.ServiceName
}
v4 := NewSigner(req.Config.Credentials, func(v4 *Signer) {
v4.Debug = req.Config.LogLevel.Value()
v4.Logger = req.Config.Logger
v4.DisableHeaderHoisting = req.NotHoist
v4.currentTimeFn = curTimeFn
if name == "s3" {
// S3 service should not have any escaping applied
v4.DisableURIPathEscaping = true
}
// Prevents setting the HTTPRequest's Body. Since the Body could be
// wrapped in a custom io.Closer that we do not want to be stompped
// on top of by the signer.
v4.DisableRequestBodyOverwrite = true
})
for _, opt := range opts {
opt(v4)
}
curTime := curTimeFn()
signedHeaders, err := v4.signWithBody(req.HTTPRequest, req.GetBody(),
name, region, req.ExpireTime, req.ExpireTime > 0, curTime,
)
if err != nil {
req.Error = err
req.SignedHeaderVals = nil
return
}
req.SignedHeaderVals = signedHeaders
req.LastSignedAt = curTime
}
const logSignInfoMsg = `DEBUG: Request Signature:
---[ CANONICAL STRING ]-----------------------------
%s
---[ STRING TO SIGN ]--------------------------------
%s%s
-----------------------------------------------------`
const logSignedURLMsg = `
---[ SIGNED URL ]------------------------------------
%s`
func (v4 *Signer) logSigningInfo(ctx *signingCtx) {
signedURLMsg := ""
if ctx.isPresign {
signedURLMsg = fmt.Sprintf(logSignedURLMsg, ctx.Request.URL.String())
}
msg := fmt.Sprintf(logSignInfoMsg, ctx.canonicalString, ctx.stringToSign, signedURLMsg)
v4.Logger.Log(msg)
}
func (ctx *signingCtx) build(disableHeaderHoisting bool) error {
ctx.buildTime() // no depends
ctx.buildCredentialString() // no depends
if err := ctx.buildBodyDigest(); err != nil {
return err
}
unsignedHeaders := ctx.Request.Header
if ctx.isPresign {
if !disableHeaderHoisting {
urlValues := url.Values{}
urlValues, unsignedHeaders = buildQuery(allowedQueryHoisting, unsignedHeaders) // no depends
for k := range urlValues {
ctx.Query[k] = urlValues[k]
}
}
}
ctx.buildCanonicalHeaders(ignoredHeaders, unsignedHeaders)
ctx.buildCanonicalString() // depends on canon headers / signed headers
ctx.buildStringToSign() // depends on canon string
ctx.buildSignature() // depends on string to sign
if ctx.isPresign {
ctx.Request.URL.RawQuery += "&" + signatureQueryKey + "=" + ctx.signature
} else {
parts := []string{
authHeaderPrefix + " Credential=" + ctx.credValues.AccessKeyID + "/" + ctx.credentialString,
"SignedHeaders=" + ctx.signedHeaders,
authHeaderSignatureElem + ctx.signature,
}
ctx.Request.Header.Set(authorizationHeader, strings.Join(parts, ", "))
}
return nil
}
// GetSignedRequestSignature attempts to extract the signature of the request.
// Returning an error if the request is unsigned, or unable to extract the
// signature.
func GetSignedRequestSignature(r *http.Request) ([]byte, error) {
if auth := r.Header.Get(authorizationHeader); len(auth) != 0 {
ps := strings.Split(auth, ", ")
for _, p := range ps {
if idx := strings.Index(p, authHeaderSignatureElem); idx >= 0 {
sig := p[len(authHeaderSignatureElem):]
if len(sig) == 0 {
return nil, fmt.Errorf("invalid request signature authorization header")
}
return hex.DecodeString(sig)
}
}
}
if sig := r.URL.Query().Get("X-Amz-Signature"); len(sig) != 0 {
return hex.DecodeString(sig)
}
return nil, fmt.Errorf("request not signed")
}
func (ctx *signingCtx) buildTime() {
if ctx.isPresign {
duration := int64(ctx.ExpireTime / time.Second)
ctx.Query.Set("X-Amz-Date", formatTime(ctx.Time))
ctx.Query.Set("X-Amz-Expires", strconv.FormatInt(duration, 10))
} else {
ctx.Request.Header.Set("X-Amz-Date", formatTime(ctx.Time))
}
}
func (ctx *signingCtx) buildCredentialString() {
ctx.credentialString = buildSigningScope(ctx.Region, ctx.ServiceName, ctx.Time)
if ctx.isPresign {
ctx.Query.Set("X-Amz-Credential", ctx.credValues.AccessKeyID+"/"+ctx.credentialString)
}
}
func buildQuery(r rule, header http.Header) (url.Values, http.Header) {
query := url.Values{}
unsignedHeaders := http.Header{}
for k, h := range header {
if r.IsValid(k) {
query[k] = h
} else {
unsignedHeaders[k] = h
}
}
return query, unsignedHeaders
}
func (ctx *signingCtx) buildCanonicalHeaders(r rule, header http.Header) {
var headers []string
headers = append(headers, "host")
for k, v := range header {
if !r.IsValid(k) {
continue // ignored header
}
if ctx.SignedHeaderVals == nil {
ctx.SignedHeaderVals = make(http.Header)
}
lowerCaseKey := strings.ToLower(k)
if _, ok := ctx.SignedHeaderVals[lowerCaseKey]; ok {
// include additional values
ctx.SignedHeaderVals[lowerCaseKey] = append(ctx.SignedHeaderVals[lowerCaseKey], v...)
continue
}
headers = append(headers, lowerCaseKey)
ctx.SignedHeaderVals[lowerCaseKey] = v
}
sort.Strings(headers)
ctx.signedHeaders = strings.Join(headers, ";")
if ctx.isPresign {
ctx.Query.Set("X-Amz-SignedHeaders", ctx.signedHeaders)
}
headerItems := make([]string, len(headers))
for i, k := range headers {
if k == "host" {
if ctx.Request.Host != "" {
headerItems[i] = "host:" + ctx.Request.Host
} else {
headerItems[i] = "host:" + ctx.Request.URL.Host
}
} else {
headerValues := make([]string, len(ctx.SignedHeaderVals[k]))
for i, v := range ctx.SignedHeaderVals[k] {
headerValues[i] = strings.TrimSpace(v)
}
headerItems[i] = k + ":" +
strings.Join(headerValues, ",")
}
}
stripExcessSpaces(headerItems)
ctx.canonicalHeaders = strings.Join(headerItems, "\n")
}
func (ctx *signingCtx) buildCanonicalString() {
ctx.Request.URL.RawQuery = strings.Replace(ctx.Query.Encode(), "+", "%20", -1)
uri := getURIPath(ctx.Request.URL)
if !ctx.DisableURIPathEscaping {
uri = rest.EscapePath(uri, false)
}
ctx.canonicalString = strings.Join([]string{
ctx.Request.Method,
uri,
ctx.Request.URL.RawQuery,
ctx.canonicalHeaders + "\n",
ctx.signedHeaders,
ctx.bodyDigest,
}, "\n")
}
func (ctx *signingCtx) buildStringToSign() {
ctx.stringToSign = strings.Join([]string{
authHeaderPrefix,
formatTime(ctx.Time),
ctx.credentialString,
hex.EncodeToString(hashSHA256([]byte(ctx.canonicalString))),
}, "\n")
}
func (ctx *signingCtx) buildSignature() {
creds := deriveSigningKey(ctx.Region, ctx.ServiceName, ctx.credValues.SecretAccessKey, ctx.Time)
signature := hmacSHA256(creds, []byte(ctx.stringToSign))
ctx.signature = hex.EncodeToString(signature)
}
func (ctx *signingCtx) buildBodyDigest() error {
hash := ctx.Request.Header.Get("X-Amz-Content-Sha256")
if hash == "" {
includeSHA256Header := ctx.unsignedPayload ||
ctx.ServiceName == "s3" ||
ctx.ServiceName == "s3-object-lambda" ||
ctx.ServiceName == "glacier"
s3Presign := ctx.isPresign &&
(ctx.ServiceName == "s3" ||
ctx.ServiceName == "s3-object-lambda")
if ctx.unsignedPayload || s3Presign {
hash = "UNSIGNED-PAYLOAD"
includeSHA256Header = !s3Presign
} else if ctx.Body == nil {
hash = emptyStringSHA256
} else {
if !aws.IsReaderSeekable(ctx.Body) {
return fmt.Errorf("cannot use unseekable request body %T, for signed request with body", ctx.Body)
}
hashBytes, err := makeSha256Reader(ctx.Body)
if err != nil {
return err
}
hash = hex.EncodeToString(hashBytes)
}
if includeSHA256Header {
ctx.Request.Header.Set("X-Amz-Content-Sha256", hash)
}
}
ctx.bodyDigest = hash
return nil
}
// isRequestSigned returns if the request is currently signed or presigned
func (ctx *signingCtx) isRequestSigned() bool {
if ctx.isPresign && ctx.Query.Get("X-Amz-Signature") != "" {
return true
}
if ctx.Request.Header.Get("Authorization") != "" {
return true
}
return false
}
// unsign removes signing flags for both signed and presigned requests.
func (ctx *signingCtx) removePresign() {
ctx.Query.Del("X-Amz-Algorithm")
ctx.Query.Del("X-Amz-Signature")
ctx.Query.Del("X-Amz-Security-Token")
ctx.Query.Del("X-Amz-Date")
ctx.Query.Del("X-Amz-Expires")
ctx.Query.Del("X-Amz-Credential")
ctx.Query.Del("X-Amz-SignedHeaders")
}
func hmacSHA256(key []byte, data []byte) []byte {
hash := hmac.New(sha256.New, key)
hash.Write(data)
return hash.Sum(nil)
}
func hashSHA256(data []byte) []byte {
hash := sha256.New()
hash.Write(data)
return hash.Sum(nil)
}
func makeSha256Reader(reader io.ReadSeeker) (hashBytes []byte, err error) {
hash := sha256.New()
start, err := reader.Seek(0, sdkio.SeekCurrent)
if err != nil {
return nil, err
}
defer func() {
// ensure error is return if unable to seek back to start of payload.
_, err = reader.Seek(start, sdkio.SeekStart)
}()
// Use CopyN to avoid allocating the 32KB buffer in io.Copy for bodies
// smaller than 32KB. Fall back to io.Copy if we fail to determine the size.
size, err := aws.SeekerLen(reader)
if err != nil {
io.Copy(hash, reader)
} else {
io.CopyN(hash, reader, size)
}
return hash.Sum(nil), nil
}
const doubleSpace = " "
// stripExcessSpaces will rewrite the passed in slice's string values to not
// contain multiple side-by-side spaces.
func stripExcessSpaces(vals []string) {
var j, k, l, m, spaces int
for i, str := range vals {
// Trim trailing spaces
for j = len(str) - 1; j >= 0 && str[j] == ' '; j-- {
}
// Trim leading spaces
for k = 0; k < j && str[k] == ' '; k++ {
}
str = str[k : j+1]
// Strip multiple spaces.
j = strings.Index(str, doubleSpace)
if j < 0 {
vals[i] = str
continue
}
buf := []byte(str)
for k, m, l = j, j, len(buf); k < l; k++ {
if buf[k] == ' ' {
if spaces == 0 {
// First space.
buf[m] = buf[k]
m++
}
spaces++
} else {
// End of multiple spaces.
spaces = 0
buf[m] = buf[k]
m++
}
}
vals[i] = string(buf[:m])
}
}
func buildSigningScope(region, service string, dt time.Time) string {
return strings.Join([]string{
formatShortTime(dt),
region,
service,
awsV4Request,
}, "/")
}
func deriveSigningKey(region, service, secretKey string, dt time.Time) []byte {
kDate := hmacSHA256([]byte("AWS4"+secretKey), []byte(formatShortTime(dt)))
kRegion := hmacSHA256(kDate, []byte(region))
kService := hmacSHA256(kRegion, []byte(service))
signingKey := hmacSHA256(kService, []byte(awsV4Request))
return signingKey
}
func formatShortTime(dt time.Time) string {
return dt.UTC().Format(shortTimeFormat)
}
func formatTime(dt time.Time) string {
return dt.UTC().Format(timeFormat)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/types.go
================================================
package aws
import (
"io"
"strings"
"sync"
"github.com/aws/aws-sdk-go/internal/sdkio"
)
// ReadSeekCloser wraps a io.Reader returning a ReaderSeekerCloser. Allows the
// SDK to accept an io.Reader that is not also an io.Seeker for unsigned
// streaming payload API operations.
//
// A ReadSeekCloser wrapping an nonseekable io.Reader used in an API
// operation's input will prevent that operation being retried in the case of
// network errors, and cause operation requests to fail if the operation
// requires payload signing.
//
// Note: If using With S3 PutObject to stream an object upload The SDK's S3
// Upload manager (s3manager.Uploader) provides support for streaming with the
// ability to retry network errors.
func ReadSeekCloser(r io.Reader) ReaderSeekerCloser {
return ReaderSeekerCloser{r}
}
// ReaderSeekerCloser represents a reader that can also delegate io.Seeker and
// io.Closer interfaces to the underlying object if they are available.
type ReaderSeekerCloser struct {
r io.Reader
}
// IsReaderSeekable returns if the underlying reader type can be seeked. A
// io.Reader might not actually be seekable if it is the ReaderSeekerCloser
// type.
func IsReaderSeekable(r io.Reader) bool {
switch v := r.(type) {
case ReaderSeekerCloser:
return v.IsSeeker()
case *ReaderSeekerCloser:
return v.IsSeeker()
case io.ReadSeeker:
return true
default:
return false
}
}
// Read reads from the reader up to size of p. The number of bytes read, and
// error if it occurred will be returned.
//
// If the reader is not an io.Reader zero bytes read, and nil error will be
// returned.
//
// Performs the same functionality as io.Reader Read
func (r ReaderSeekerCloser) Read(p []byte) (int, error) {
switch t := r.r.(type) {
case io.Reader:
return t.Read(p)
}
return 0, nil
}
// Seek sets the offset for the next Read to offset, interpreted according to
// whence: 0 means relative to the origin of the file, 1 means relative to the
// current offset, and 2 means relative to the end. Seek returns the new offset
// and an error, if any.
//
// If the ReaderSeekerCloser is not an io.Seeker nothing will be done.
func (r ReaderSeekerCloser) Seek(offset int64, whence int) (int64, error) {
switch t := r.r.(type) {
case io.Seeker:
return t.Seek(offset, whence)
}
return int64(0), nil
}
// IsSeeker returns if the underlying reader is also a seeker.
func (r ReaderSeekerCloser) IsSeeker() bool {
_, ok := r.r.(io.Seeker)
return ok
}
// HasLen returns the length of the underlying reader if the value implements
// the Len() int method.
func (r ReaderSeekerCloser) HasLen() (int, bool) {
type lenner interface {
Len() int
}
if lr, ok := r.r.(lenner); ok {
return lr.Len(), true
}
return 0, false
}
// GetLen returns the length of the bytes remaining in the underlying reader.
// Checks first for Len(), then io.Seeker to determine the size of the
// underlying reader.
//
// Will return -1 if the length cannot be determined.
func (r ReaderSeekerCloser) GetLen() (int64, error) {
if l, ok := r.HasLen(); ok {
return int64(l), nil
}
if s, ok := r.r.(io.Seeker); ok {
return seekerLen(s)
}
return -1, nil
}
// SeekerLen attempts to get the number of bytes remaining at the seeker's
// current position. Returns the number of bytes remaining or error.
func SeekerLen(s io.Seeker) (int64, error) {
// Determine if the seeker is actually seekable. ReaderSeekerCloser
// hides the fact that a io.Readers might not actually be seekable.
switch v := s.(type) {
case ReaderSeekerCloser:
return v.GetLen()
case *ReaderSeekerCloser:
return v.GetLen()
}
return seekerLen(s)
}
func seekerLen(s io.Seeker) (int64, error) {
curOffset, err := s.Seek(0, sdkio.SeekCurrent)
if err != nil {
return 0, err
}
endOffset, err := s.Seek(0, sdkio.SeekEnd)
if err != nil {
return 0, err
}
_, err = s.Seek(curOffset, sdkio.SeekStart)
if err != nil {
return 0, err
}
return endOffset - curOffset, nil
}
// Close closes the ReaderSeekerCloser.
//
// If the ReaderSeekerCloser is not an io.Closer nothing will be done.
func (r ReaderSeekerCloser) Close() error {
switch t := r.r.(type) {
case io.Closer:
return t.Close()
}
return nil
}
// A WriteAtBuffer provides a in memory buffer supporting the io.WriterAt interface
// Can be used with the s3manager.Downloader to download content to a buffer
// in memory. Safe to use concurrently.
type WriteAtBuffer struct {
buf []byte
m sync.Mutex
// GrowthCoeff defines the growth rate of the internal buffer. By
// default, the growth rate is 1, where expanding the internal
// buffer will allocate only enough capacity to fit the new expected
// length.
GrowthCoeff float64
}
// NewWriteAtBuffer creates a WriteAtBuffer with an internal buffer
// provided by buf.
func NewWriteAtBuffer(buf []byte) *WriteAtBuffer {
return &WriteAtBuffer{buf: buf}
}
// WriteAt writes a slice of bytes to a buffer starting at the position provided
// The number of bytes written will be returned, or error. Can overwrite previous
// written slices if the write ats overlap.
func (b *WriteAtBuffer) WriteAt(p []byte, pos int64) (n int, err error) {
pLen := len(p)
expLen := pos + int64(pLen)
b.m.Lock()
defer b.m.Unlock()
if int64(len(b.buf)) < expLen {
if int64(cap(b.buf)) < expLen {
if b.GrowthCoeff < 1 {
b.GrowthCoeff = 1
}
newBuf := make([]byte, expLen, int64(b.GrowthCoeff*float64(expLen)))
copy(newBuf, b.buf)
b.buf = newBuf
}
b.buf = b.buf[:expLen]
}
copy(b.buf[pos:], p)
return pLen, nil
}
// Bytes returns a slice of bytes written to the buffer.
func (b *WriteAtBuffer) Bytes() []byte {
b.m.Lock()
defer b.m.Unlock()
return b.buf
}
// MultiCloser is a utility to close multiple io.Closers within a single
// statement.
type MultiCloser []io.Closer
// Close closes all of the io.Closers making up the MultiClosers. Any
// errors that occur while closing will be returned in the order they
// occur.
func (m MultiCloser) Close() error {
var errs errors
for _, c := range m {
err := c.Close()
if err != nil {
errs = append(errs, err)
}
}
if len(errs) != 0 {
return errs
}
return nil
}
type errors []error
func (es errors) Error() string {
var parts []string
for _, e := range es {
parts = append(parts, e.Error())
}
return strings.Join(parts, "\n")
}
// CopySeekableBody copies the seekable body to an io.Writer
func CopySeekableBody(dst io.Writer, src io.ReadSeeker) (int64, error) {
curPos, err := src.Seek(0, sdkio.SeekCurrent)
if err != nil {
return 0, err
}
// copy errors may be assumed to be from the body.
n, err := io.Copy(dst, src)
if err != nil {
return n, err
}
// seek back to the first position after reading to reset
// the body for transmission.
_, err = src.Seek(curPos, sdkio.SeekStart)
if err != nil {
return n, err
}
return n, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/url.go
================================================
//go:build go1.8
// +build go1.8
package aws
import "net/url"
// URLHostname will extract the Hostname without port from the URL value.
//
// Wrapper of net/url#URL.Hostname for backwards Go version compatibility.
func URLHostname(url *url.URL) string {
return url.Hostname()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/url_1_7.go
================================================
//go:build !go1.8
// +build !go1.8
package aws
import (
"net/url"
"strings"
)
// URLHostname will extract the Hostname without port from the URL value.
//
// Copy of Go 1.8's net/url#URL.Hostname functionality.
func URLHostname(url *url.URL) string {
return stripPort(url.Host)
}
// stripPort is copy of Go 1.8 url#URL.Hostname functionality.
// https://golang.org/src/net/url/url.go
func stripPort(hostport string) string {
colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return hostport
}
if i := strings.IndexByte(hostport, ']'); i != -1 {
return strings.TrimPrefix(hostport[:i], "[")
}
return hostport[:colon]
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/aws/version.go
================================================
// Package aws provides core functionality for making requests to AWS services.
package aws
// SDKName is the name of this AWS SDK
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.43.43"
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/context/background_go1.5.go
================================================
//go:build !go1.7
// +build !go1.7
package context
import "time"
// An emptyCtx is a copy of the Go 1.7 context.emptyCtx type. This is copied to
// provide a 1.6 and 1.5 safe version of context that is compatible with Go
// 1.7's Context.
//
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
func (*emptyCtx) Deadline() (deadline time.Time, ok bool) {
return
}
func (*emptyCtx) Done() <-chan struct{} {
return nil
}
func (*emptyCtx) Err() error {
return nil
}
func (*emptyCtx) Value(key interface{}) interface{} {
return nil
}
func (e *emptyCtx) String() string {
switch e {
case BackgroundCtx:
return "aws.BackgroundContext"
}
return "unknown empty Context"
}
// BackgroundCtx is the common base context.
var BackgroundCtx = new(emptyCtx)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/ast.go
================================================
package ini
// ASTKind represents different states in the parse table
// and the type of AST that is being constructed
type ASTKind int
// ASTKind* is used in the parse table to transition between
// the different states
const (
ASTKindNone = ASTKind(iota)
ASTKindStart
ASTKindExpr
ASTKindEqualExpr
ASTKindStatement
ASTKindSkipStatement
ASTKindExprStatement
ASTKindSectionStatement
ASTKindNestedSectionStatement
ASTKindCompletedNestedSectionStatement
ASTKindCommentStatement
ASTKindCompletedSectionStatement
)
func (k ASTKind) String() string {
switch k {
case ASTKindNone:
return "none"
case ASTKindStart:
return "start"
case ASTKindExpr:
return "expr"
case ASTKindStatement:
return "stmt"
case ASTKindSectionStatement:
return "section_stmt"
case ASTKindExprStatement:
return "expr_stmt"
case ASTKindCommentStatement:
return "comment"
case ASTKindNestedSectionStatement:
return "nested_section_stmt"
case ASTKindCompletedSectionStatement:
return "completed_stmt"
case ASTKindSkipStatement:
return "skip"
default:
return ""
}
}
// AST interface allows us to determine what kind of node we
// are on and casting may not need to be necessary.
//
// The root is always the first node in Children
type AST struct {
Kind ASTKind
Root Token
RootToken bool
Children []AST
}
func newAST(kind ASTKind, root AST, children ...AST) AST {
return AST{
Kind: kind,
Children: append([]AST{root}, children...),
}
}
func newASTWithRootToken(kind ASTKind, root Token, children ...AST) AST {
return AST{
Kind: kind,
Root: root,
RootToken: true,
Children: children,
}
}
// AppendChild will append to the list of children an AST has.
func (a *AST) AppendChild(child AST) {
a.Children = append(a.Children, child)
}
// GetRoot will return the root AST which can be the first entry
// in the children list or a token.
func (a *AST) GetRoot() AST {
if a.RootToken {
return *a
}
if len(a.Children) == 0 {
return AST{}
}
return a.Children[0]
}
// GetChildren will return the current AST's list of children
func (a *AST) GetChildren() []AST {
if len(a.Children) == 0 {
return []AST{}
}
if a.RootToken {
return a.Children
}
return a.Children[1:]
}
// SetChildren will set and override all children of the AST.
func (a *AST) SetChildren(children []AST) {
if a.RootToken {
a.Children = children
} else {
a.Children = append(a.Children[:1], children...)
}
}
// Start is used to indicate the starting state of the parse table.
var Start = newAST(ASTKindStart, AST{})
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/comma_token.go
================================================
package ini
var commaRunes = []rune(",")
func isComma(b rune) bool {
return b == ','
}
func newCommaToken() Token {
return newToken(TokenComma, commaRunes, NoneType)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/comment_token.go
================================================
package ini
// isComment will return whether or not the next byte(s) is a
// comment.
func isComment(b []rune) bool {
if len(b) == 0 {
return false
}
switch b[0] {
case ';':
return true
case '#':
return true
}
return false
}
// newCommentToken will create a comment token and
// return how many bytes were read.
func newCommentToken(b []rune) (Token, int, error) {
i := 0
for ; i < len(b); i++ {
if b[i] == '\n' {
break
}
if len(b)-i > 2 && b[i] == '\r' && b[i+1] == '\n' {
break
}
}
return newToken(TokenComment, b[:i], NoneType), i, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/doc.go
================================================
// Package ini is an LL(1) parser for configuration files.
//
// Example:
// sections, err := ini.OpenFile("/path/to/file")
// if err != nil {
// panic(err)
// }
//
// profile := "foo"
// section, ok := sections.GetSection(profile)
// if !ok {
// fmt.Printf("section %q could not be found", profile)
// }
//
// Below is the BNF that describes this parser
// Grammar:
// stmt -> section | stmt'
// stmt' -> epsilon | expr
// expr -> value (stmt)* | equal_expr (stmt)*
// equal_expr -> value ( ':' | '=' ) equal_expr'
// equal_expr' -> number | string | quoted_string
// quoted_string -> " quoted_string'
// quoted_string' -> string quoted_string_end
// quoted_string_end -> "
//
// section -> [ section'
// section' -> section_value section_close
// section_value -> number | string_subset | boolean | quoted_string_subset
// quoted_string_subset -> " quoted_string_subset'
// quoted_string_subset' -> string_subset quoted_string_end
// quoted_string_subset -> "
// section_close -> ]
//
// value -> number | string_subset | boolean
// string -> ? UTF-8 Code-Points except '\n' (U+000A) and '\r\n' (U+000D U+000A) ?
// string_subset -> ? Code-points excepted by grammar except ':' (U+003A), '=' (U+003D), '[' (U+005B), and ']' (U+005D) ?
//
// SkipState will skip (NL WS)+
//
// comment -> # comment' | ; comment'
// comment' -> epsilon | value
package ini
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/empty_token.go
================================================
package ini
// emptyToken is used to satisfy the Token interface
var emptyToken = newToken(TokenNone, []rune{}, NoneType)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/expression.go
================================================
package ini
// newExpression will return an expression AST.
// Expr represents an expression
//
// grammar:
// expr -> string | number
func newExpression(tok Token) AST {
return newASTWithRootToken(ASTKindExpr, tok)
}
func newEqualExpr(left AST, tok Token) AST {
return newASTWithRootToken(ASTKindEqualExpr, tok, left)
}
// EqualExprKey will return a LHS value in the equal expr
func EqualExprKey(ast AST) string {
children := ast.GetChildren()
if len(children) == 0 || ast.Kind != ASTKindEqualExpr {
return ""
}
return string(children[0].Root.Raw())
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/fuzz.go
================================================
//go:build gofuzz
// +build gofuzz
package ini
import (
"bytes"
)
func Fuzz(data []byte) int {
b := bytes.NewReader(data)
if _, err := Parse(b); err != nil {
return 0
}
return 1
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/ini.go
================================================
package ini
import (
"io"
"os"
"github.com/aws/aws-sdk-go/aws/awserr"
)
// OpenFile takes a path to a given file, and will open and parse
// that file.
func OpenFile(path string) (Sections, error) {
f, err := os.Open(path)
if err != nil {
return Sections{}, awserr.New(ErrCodeUnableToReadFile, "unable to open file", err)
}
defer f.Close()
return Parse(f)
}
// Parse will parse the given file using the shared config
// visitor.
func Parse(f io.Reader) (Sections, error) {
tree, err := ParseAST(f)
if err != nil {
return Sections{}, err
}
v := NewDefaultVisitor()
if err = Walk(tree, v); err != nil {
return Sections{}, err
}
return v.Sections, nil
}
// ParseBytes will parse the given bytes and return the parsed sections.
func ParseBytes(b []byte) (Sections, error) {
tree, err := ParseASTBytes(b)
if err != nil {
return Sections{}, err
}
v := NewDefaultVisitor()
if err = Walk(tree, v); err != nil {
return Sections{}, err
}
return v.Sections, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/ini_lexer.go
================================================
package ini
import (
"bytes"
"io"
"io/ioutil"
"github.com/aws/aws-sdk-go/aws/awserr"
)
const (
// ErrCodeUnableToReadFile is used when a file is failed to be
// opened or read from.
ErrCodeUnableToReadFile = "FailedRead"
)
// TokenType represents the various different tokens types
type TokenType int
func (t TokenType) String() string {
switch t {
case TokenNone:
return "none"
case TokenLit:
return "literal"
case TokenSep:
return "sep"
case TokenOp:
return "op"
case TokenWS:
return "ws"
case TokenNL:
return "newline"
case TokenComment:
return "comment"
case TokenComma:
return "comma"
default:
return ""
}
}
// TokenType enums
const (
TokenNone = TokenType(iota)
TokenLit
TokenSep
TokenComma
TokenOp
TokenWS
TokenNL
TokenComment
)
type iniLexer struct{}
// Tokenize will return a list of tokens during lexical analysis of the
// io.Reader.
func (l *iniLexer) Tokenize(r io.Reader) ([]Token, error) {
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, awserr.New(ErrCodeUnableToReadFile, "unable to read file", err)
}
return l.tokenize(b)
}
func (l *iniLexer) tokenize(b []byte) ([]Token, error) {
runes := bytes.Runes(b)
var err error
n := 0
tokenAmount := countTokens(runes)
tokens := make([]Token, tokenAmount)
count := 0
for len(runes) > 0 && count < tokenAmount {
switch {
case isWhitespace(runes[0]):
tokens[count], n, err = newWSToken(runes)
case isComma(runes[0]):
tokens[count], n = newCommaToken(), 1
case isComment(runes):
tokens[count], n, err = newCommentToken(runes)
case isNewline(runes):
tokens[count], n, err = newNewlineToken(runes)
case isSep(runes):
tokens[count], n, err = newSepToken(runes)
case isOp(runes):
tokens[count], n, err = newOpToken(runes)
default:
tokens[count], n, err = newLitToken(runes)
}
if err != nil {
return nil, err
}
count++
runes = runes[n:]
}
return tokens[:count], nil
}
func countTokens(runes []rune) int {
count, n := 0, 0
var err error
for len(runes) > 0 {
switch {
case isWhitespace(runes[0]):
_, n, err = newWSToken(runes)
case isComma(runes[0]):
_, n = newCommaToken(), 1
case isComment(runes):
_, n, err = newCommentToken(runes)
case isNewline(runes):
_, n, err = newNewlineToken(runes)
case isSep(runes):
_, n, err = newSepToken(runes)
case isOp(runes):
_, n, err = newOpToken(runes)
default:
_, n, err = newLitToken(runes)
}
if err != nil {
return 0
}
count++
runes = runes[n:]
}
return count + 1
}
// Token indicates a metadata about a given value.
type Token struct {
t TokenType
ValueType ValueType
base int
raw []rune
}
var emptyValue = Value{}
func newToken(t TokenType, raw []rune, v ValueType) Token {
return Token{
t: t,
raw: raw,
ValueType: v,
}
}
// Raw return the raw runes that were consumed
func (tok Token) Raw() []rune {
return tok.raw
}
// Type returns the token type
func (tok Token) Type() TokenType {
return tok.t
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/ini_parser.go
================================================
package ini
import (
"fmt"
"io"
)
// ParseState represents the current state of the parser.
type ParseState uint
// State enums for the parse table
const (
InvalidState ParseState = iota
// stmt -> value stmt'
StatementState
// stmt' -> MarkComplete | op stmt
StatementPrimeState
// value -> number | string | boolean | quoted_string
ValueState
// section -> [ section'
OpenScopeState
// section' -> value section_close
SectionState
// section_close -> ]
CloseScopeState
// SkipState will skip (NL WS)+
SkipState
// SkipTokenState will skip any token and push the previous
// state onto the stack.
SkipTokenState
// comment -> # comment' | ; comment'
// comment' -> MarkComplete | value
CommentState
// MarkComplete state will complete statements and move that
// to the completed AST list
MarkCompleteState
// TerminalState signifies that the tokens have been fully parsed
TerminalState
)
// parseTable is a state machine to dictate the grammar above.
var parseTable = map[ASTKind]map[TokenType]ParseState{
ASTKindStart: {
TokenLit: StatementState,
TokenSep: OpenScopeState,
TokenWS: SkipTokenState,
TokenNL: SkipTokenState,
TokenComment: CommentState,
TokenNone: TerminalState,
},
ASTKindCommentStatement: {
TokenLit: StatementState,
TokenSep: OpenScopeState,
TokenWS: SkipTokenState,
TokenNL: SkipTokenState,
TokenComment: CommentState,
TokenNone: MarkCompleteState,
},
ASTKindExpr: {
TokenOp: StatementPrimeState,
TokenLit: ValueState,
TokenSep: OpenScopeState,
TokenWS: ValueState,
TokenNL: SkipState,
TokenComment: CommentState,
TokenNone: MarkCompleteState,
},
ASTKindEqualExpr: {
TokenLit: ValueState,
TokenSep: ValueState,
TokenOp: ValueState,
TokenWS: SkipTokenState,
TokenNL: SkipState,
TokenNone: SkipState,
},
ASTKindStatement: {
TokenLit: SectionState,
TokenSep: CloseScopeState,
TokenWS: SkipTokenState,
TokenNL: SkipTokenState,
TokenComment: CommentState,
TokenNone: MarkCompleteState,
},
ASTKindExprStatement: {
TokenLit: ValueState,
TokenSep: ValueState,
TokenOp: ValueState,
TokenWS: ValueState,
TokenNL: MarkCompleteState,
TokenComment: CommentState,
TokenNone: TerminalState,
TokenComma: SkipState,
},
ASTKindSectionStatement: {
TokenLit: SectionState,
TokenOp: SectionState,
TokenSep: CloseScopeState,
TokenWS: SectionState,
TokenNL: SkipTokenState,
},
ASTKindCompletedSectionStatement: {
TokenWS: SkipTokenState,
TokenNL: SkipTokenState,
TokenLit: StatementState,
TokenSep: OpenScopeState,
TokenComment: CommentState,
TokenNone: MarkCompleteState,
},
ASTKindSkipStatement: {
TokenLit: StatementState,
TokenSep: OpenScopeState,
TokenWS: SkipTokenState,
TokenNL: SkipTokenState,
TokenComment: CommentState,
TokenNone: TerminalState,
},
}
// ParseAST will parse input from an io.Reader using
// an LL(1) parser.
func ParseAST(r io.Reader) ([]AST, error) {
lexer := iniLexer{}
tokens, err := lexer.Tokenize(r)
if err != nil {
return []AST{}, err
}
return parse(tokens)
}
// ParseASTBytes will parse input from a byte slice using
// an LL(1) parser.
func ParseASTBytes(b []byte) ([]AST, error) {
lexer := iniLexer{}
tokens, err := lexer.tokenize(b)
if err != nil {
return []AST{}, err
}
return parse(tokens)
}
func parse(tokens []Token) ([]AST, error) {
start := Start
stack := newParseStack(3, len(tokens))
stack.Push(start)
s := newSkipper()
loop:
for stack.Len() > 0 {
k := stack.Pop()
var tok Token
if len(tokens) == 0 {
// this occurs when all the tokens have been processed
// but reduction of what's left on the stack needs to
// occur.
tok = emptyToken
} else {
tok = tokens[0]
}
step := parseTable[k.Kind][tok.Type()]
if s.ShouldSkip(tok) {
// being in a skip state with no tokens will break out of
// the parse loop since there is nothing left to process.
if len(tokens) == 0 {
break loop
}
// if should skip is true, we skip the tokens until should skip is set to false.
step = SkipTokenState
}
switch step {
case TerminalState:
// Finished parsing. Push what should be the last
// statement to the stack. If there is anything left
// on the stack, an error in parsing has occurred.
if k.Kind != ASTKindStart {
stack.MarkComplete(k)
}
break loop
case SkipTokenState:
// When skipping a token, the previous state was popped off the stack.
// To maintain the correct state, the previous state will be pushed
// onto the stack.
stack.Push(k)
case StatementState:
if k.Kind != ASTKindStart {
stack.MarkComplete(k)
}
expr := newExpression(tok)
stack.Push(expr)
case StatementPrimeState:
if tok.Type() != TokenOp {
stack.MarkComplete(k)
continue
}
if k.Kind != ASTKindExpr {
return nil, NewParseError(
fmt.Sprintf("invalid expression: expected Expr type, but found %T type", k),
)
}
k = trimSpaces(k)
expr := newEqualExpr(k, tok)
stack.Push(expr)
case ValueState:
// ValueState requires the previous state to either be an equal expression
// or an expression statement.
switch k.Kind {
case ASTKindEqualExpr:
// assigning a value to some key
k.AppendChild(newExpression(tok))
stack.Push(newExprStatement(k))
case ASTKindExpr:
k.Root.raw = append(k.Root.raw, tok.Raw()...)
stack.Push(k)
case ASTKindExprStatement:
root := k.GetRoot()
children := root.GetChildren()
if len(children) == 0 {
return nil, NewParseError(
fmt.Sprintf("invalid expression: AST contains no children %s", k.Kind),
)
}
rhs := children[len(children)-1]
if rhs.Root.ValueType != QuotedStringType {
rhs.Root.ValueType = StringType
rhs.Root.raw = append(rhs.Root.raw, tok.Raw()...)
}
children[len(children)-1] = rhs
root.SetChildren(children)
stack.Push(k)
}
case OpenScopeState:
if !runeCompare(tok.Raw(), openBrace) {
return nil, NewParseError("expected '['")
}
// If OpenScopeState is not at the start, we must mark the previous ast as complete
//
// for example: if previous ast was a skip statement;
// we should mark it as complete before we create a new statement
if k.Kind != ASTKindStart {
stack.MarkComplete(k)
}
stmt := newStatement()
stack.Push(stmt)
case CloseScopeState:
if !runeCompare(tok.Raw(), closeBrace) {
return nil, NewParseError("expected ']'")
}
k = trimSpaces(k)
stack.Push(newCompletedSectionStatement(k))
case SectionState:
var stmt AST
switch k.Kind {
case ASTKindStatement:
// If there are multiple literals inside of a scope declaration,
// then the current token's raw value will be appended to the Name.
//
// This handles cases like [ profile default ]
//
// k will represent a SectionStatement with the children representing
// the label of the section
stmt = newSectionStatement(tok)
case ASTKindSectionStatement:
k.Root.raw = append(k.Root.raw, tok.Raw()...)
stmt = k
default:
return nil, NewParseError(
fmt.Sprintf("invalid statement: expected statement: %v", k.Kind),
)
}
stack.Push(stmt)
case MarkCompleteState:
if k.Kind != ASTKindStart {
stack.MarkComplete(k)
}
if stack.Len() == 0 {
stack.Push(start)
}
case SkipState:
stack.Push(newSkipStatement(k))
s.Skip()
case CommentState:
if k.Kind == ASTKindStart {
stack.Push(k)
} else {
stack.MarkComplete(k)
}
stmt := newCommentStatement(tok)
stack.Push(stmt)
default:
return nil, NewParseError(
fmt.Sprintf("invalid state with ASTKind %v and TokenType %v",
k, tok.Type()))
}
if len(tokens) > 0 {
tokens = tokens[1:]
}
}
// this occurs when a statement has not been completed
if stack.top > 1 {
return nil, NewParseError(fmt.Sprintf("incomplete ini expression"))
}
// returns a sublist which excludes the start symbol
return stack.List(), nil
}
// trimSpaces will trim spaces on the left and right hand side of
// the literal.
func trimSpaces(k AST) AST {
// trim left hand side of spaces
for i := 0; i < len(k.Root.raw); i++ {
if !isWhitespace(k.Root.raw[i]) {
break
}
k.Root.raw = k.Root.raw[1:]
i--
}
// trim right hand side of spaces
for i := len(k.Root.raw) - 1; i >= 0; i-- {
if !isWhitespace(k.Root.raw[i]) {
break
}
k.Root.raw = k.Root.raw[:len(k.Root.raw)-1]
}
return k
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/literal_tokens.go
================================================
package ini
import (
"fmt"
"strconv"
"strings"
"unicode"
)
var (
runesTrue = []rune("true")
runesFalse = []rune("false")
)
var literalValues = [][]rune{
runesTrue,
runesFalse,
}
func isBoolValue(b []rune) bool {
for _, lv := range literalValues {
if isCaselessLitValue(lv, b) {
return true
}
}
return false
}
func isLitValue(want, have []rune) bool {
if len(have) < len(want) {
return false
}
for i := 0; i < len(want); i++ {
if want[i] != have[i] {
return false
}
}
return true
}
// isCaselessLitValue is a caseless value comparison, assumes want is already lower-cased for efficiency.
func isCaselessLitValue(want, have []rune) bool {
if len(have) < len(want) {
return false
}
for i := 0; i < len(want); i++ {
if want[i] != unicode.ToLower(have[i]) {
return false
}
}
return true
}
// isNumberValue will return whether not the leading characters in
// a byte slice is a number. A number is delimited by whitespace or
// the newline token.
//
// A number is defined to be in a binary, octal, decimal (int | float), hex format,
// or in scientific notation.
func isNumberValue(b []rune) bool {
negativeIndex := 0
helper := numberHelper{}
needDigit := false
for i := 0; i < len(b); i++ {
negativeIndex++
switch b[i] {
case '-':
if helper.IsNegative() || negativeIndex != 1 {
return false
}
helper.Determine(b[i])
needDigit = true
continue
case 'e', 'E':
if err := helper.Determine(b[i]); err != nil {
return false
}
negativeIndex = 0
needDigit = true
continue
case 'b':
if helper.numberFormat == hex {
break
}
fallthrough
case 'o', 'x':
needDigit = true
if i == 0 {
return false
}
fallthrough
case '.':
if err := helper.Determine(b[i]); err != nil {
return false
}
needDigit = true
continue
}
if i > 0 && (isNewline(b[i:]) || isWhitespace(b[i])) {
return !needDigit
}
if !helper.CorrectByte(b[i]) {
return false
}
needDigit = false
}
return !needDigit
}
func isValid(b []rune) (bool, int, error) {
if len(b) == 0 {
// TODO: should probably return an error
return false, 0, nil
}
return isValidRune(b[0]), 1, nil
}
func isValidRune(r rune) bool {
return r != ':' && r != '=' && r != '[' && r != ']' && r != ' ' && r != '\n'
}
// ValueType is an enum that will signify what type
// the Value is
type ValueType int
func (v ValueType) String() string {
switch v {
case NoneType:
return "NONE"
case DecimalType:
return "FLOAT"
case IntegerType:
return "INT"
case StringType:
return "STRING"
case BoolType:
return "BOOL"
}
return ""
}
// ValueType enums
const (
NoneType = ValueType(iota)
DecimalType
IntegerType
StringType
QuotedStringType
BoolType
)
// Value is a union container
type Value struct {
Type ValueType
raw []rune
integer int64
decimal float64
boolean bool
str string
}
func newValue(t ValueType, base int, raw []rune) (Value, error) {
v := Value{
Type: t,
raw: raw,
}
var err error
switch t {
case DecimalType:
v.decimal, err = strconv.ParseFloat(string(raw), 64)
case IntegerType:
if base != 10 {
raw = raw[2:]
}
v.integer, err = strconv.ParseInt(string(raw), base, 64)
case StringType:
v.str = string(raw)
case QuotedStringType:
v.str = string(raw[1 : len(raw)-1])
case BoolType:
v.boolean = isCaselessLitValue(runesTrue, v.raw)
}
// issue 2253
//
// if the value trying to be parsed is too large, then we will use
// the 'StringType' and raw value instead.
if nerr, ok := err.(*strconv.NumError); ok && nerr.Err == strconv.ErrRange {
v.Type = StringType
v.str = string(raw)
err = nil
}
return v, err
}
// Append will append values and change the type to a string
// type.
func (v *Value) Append(tok Token) {
r := tok.Raw()
if v.Type != QuotedStringType {
v.Type = StringType
r = tok.raw[1 : len(tok.raw)-1]
}
if tok.Type() != TokenLit {
v.raw = append(v.raw, tok.Raw()...)
} else {
v.raw = append(v.raw, r...)
}
}
func (v Value) String() string {
switch v.Type {
case DecimalType:
return fmt.Sprintf("decimal: %f", v.decimal)
case IntegerType:
return fmt.Sprintf("integer: %d", v.integer)
case StringType:
return fmt.Sprintf("string: %s", string(v.raw))
case QuotedStringType:
return fmt.Sprintf("quoted string: %s", string(v.raw))
case BoolType:
return fmt.Sprintf("bool: %t", v.boolean)
default:
return "union not set"
}
}
func newLitToken(b []rune) (Token, int, error) {
n := 0
var err error
token := Token{}
if b[0] == '"' {
n, err = getStringValue(b)
if err != nil {
return token, n, err
}
token = newToken(TokenLit, b[:n], QuotedStringType)
} else if isNumberValue(b) {
var base int
base, n, err = getNumericalValue(b)
if err != nil {
return token, 0, err
}
value := b[:n]
vType := IntegerType
if contains(value, '.') || hasExponent(value) {
vType = DecimalType
}
token = newToken(TokenLit, value, vType)
token.base = base
} else if isBoolValue(b) {
n, err = getBoolValue(b)
token = newToken(TokenLit, b[:n], BoolType)
} else {
n, err = getValue(b)
token = newToken(TokenLit, b[:n], StringType)
}
return token, n, err
}
// IntValue returns an integer value
func (v Value) IntValue() int64 {
return v.integer
}
// FloatValue returns a float value
func (v Value) FloatValue() float64 {
return v.decimal
}
// BoolValue returns a bool value
func (v Value) BoolValue() bool {
return v.boolean
}
func isTrimmable(r rune) bool {
switch r {
case '\n', ' ':
return true
}
return false
}
// StringValue returns the string value
func (v Value) StringValue() string {
switch v.Type {
case StringType:
return strings.TrimFunc(string(v.raw), isTrimmable)
case QuotedStringType:
// preserve all characters in the quotes
return string(removeEscapedCharacters(v.raw[1 : len(v.raw)-1]))
default:
return strings.TrimFunc(string(v.raw), isTrimmable)
}
}
func contains(runes []rune, c rune) bool {
for i := 0; i < len(runes); i++ {
if runes[i] == c {
return true
}
}
return false
}
func runeCompare(v1 []rune, v2 []rune) bool {
if len(v1) != len(v2) {
return false
}
for i := 0; i < len(v1); i++ {
if v1[i] != v2[i] {
return false
}
}
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/newline_token.go
================================================
package ini
func isNewline(b []rune) bool {
if len(b) == 0 {
return false
}
if b[0] == '\n' {
return true
}
if len(b) < 2 {
return false
}
return b[0] == '\r' && b[1] == '\n'
}
func newNewlineToken(b []rune) (Token, int, error) {
i := 1
if b[0] == '\r' && isNewline(b[1:]) {
i++
}
if !isNewline([]rune(b[:i])) {
return emptyToken, 0, NewParseError("invalid new line token")
}
return newToken(TokenNL, b[:i], NoneType), i, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/number_helper.go
================================================
package ini
import (
"bytes"
"fmt"
"strconv"
)
const (
none = numberFormat(iota)
binary
octal
decimal
hex
exponent
)
type numberFormat int
// numberHelper is used to dictate what format a number is in
// and what to do for negative values. Since -1e-4 is a valid
// number, we cannot just simply check for duplicate negatives.
type numberHelper struct {
numberFormat numberFormat
negative bool
negativeExponent bool
}
func (b numberHelper) Exists() bool {
return b.numberFormat != none
}
func (b numberHelper) IsNegative() bool {
return b.negative || b.negativeExponent
}
func (b *numberHelper) Determine(c rune) error {
if b.Exists() {
return NewParseError(fmt.Sprintf("multiple number formats: 0%v", string(c)))
}
switch c {
case 'b':
b.numberFormat = binary
case 'o':
b.numberFormat = octal
case 'x':
b.numberFormat = hex
case 'e', 'E':
b.numberFormat = exponent
case '-':
if b.numberFormat != exponent {
b.negative = true
} else {
b.negativeExponent = true
}
case '.':
b.numberFormat = decimal
default:
return NewParseError(fmt.Sprintf("invalid number character: %v", string(c)))
}
return nil
}
func (b numberHelper) CorrectByte(c rune) bool {
switch {
case b.numberFormat == binary:
if !isBinaryByte(c) {
return false
}
case b.numberFormat == octal:
if !isOctalByte(c) {
return false
}
case b.numberFormat == hex:
if !isHexByte(c) {
return false
}
case b.numberFormat == decimal:
if !isDigit(c) {
return false
}
case b.numberFormat == exponent:
if !isDigit(c) {
return false
}
case b.negativeExponent:
if !isDigit(c) {
return false
}
case b.negative:
if !isDigit(c) {
return false
}
default:
if !isDigit(c) {
return false
}
}
return true
}
func (b numberHelper) Base() int {
switch b.numberFormat {
case binary:
return 2
case octal:
return 8
case hex:
return 16
default:
return 10
}
}
func (b numberHelper) String() string {
buf := bytes.Buffer{}
i := 0
switch b.numberFormat {
case binary:
i++
buf.WriteString(strconv.Itoa(i) + ": binary format\n")
case octal:
i++
buf.WriteString(strconv.Itoa(i) + ": octal format\n")
case hex:
i++
buf.WriteString(strconv.Itoa(i) + ": hex format\n")
case exponent:
i++
buf.WriteString(strconv.Itoa(i) + ": exponent format\n")
default:
i++
buf.WriteString(strconv.Itoa(i) + ": integer format\n")
}
if b.negative {
i++
buf.WriteString(strconv.Itoa(i) + ": negative format\n")
}
if b.negativeExponent {
i++
buf.WriteString(strconv.Itoa(i) + ": negative exponent format\n")
}
return buf.String()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/op_tokens.go
================================================
package ini
import (
"fmt"
)
var (
equalOp = []rune("=")
equalColonOp = []rune(":")
)
func isOp(b []rune) bool {
if len(b) == 0 {
return false
}
switch b[0] {
case '=':
return true
case ':':
return true
default:
return false
}
}
func newOpToken(b []rune) (Token, int, error) {
tok := Token{}
switch b[0] {
case '=':
tok = newToken(TokenOp, equalOp, NoneType)
case ':':
tok = newToken(TokenOp, equalColonOp, NoneType)
default:
return tok, 0, NewParseError(fmt.Sprintf("unexpected op type, %v", b[0]))
}
return tok, 1, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/parse_error.go
================================================
package ini
import "fmt"
const (
// ErrCodeParseError is returned when a parsing error
// has occurred.
ErrCodeParseError = "INIParseError"
)
// ParseError is an error which is returned during any part of
// the parsing process.
type ParseError struct {
msg string
}
// NewParseError will return a new ParseError where message
// is the description of the error.
func NewParseError(message string) *ParseError {
return &ParseError{
msg: message,
}
}
// Code will return the ErrCodeParseError
func (err *ParseError) Code() string {
return ErrCodeParseError
}
// Message returns the error's message
func (err *ParseError) Message() string {
return err.msg
}
// OrigError return nothing since there will never be any
// original error.
func (err *ParseError) OrigError() error {
return nil
}
func (err *ParseError) Error() string {
return fmt.Sprintf("%s: %s", err.Code(), err.Message())
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/parse_stack.go
================================================
package ini
import (
"bytes"
"fmt"
)
// ParseStack is a stack that contains a container, the stack portion,
// and the list which is the list of ASTs that have been successfully
// parsed.
type ParseStack struct {
top int
container []AST
list []AST
index int
}
func newParseStack(sizeContainer, sizeList int) ParseStack {
return ParseStack{
container: make([]AST, sizeContainer),
list: make([]AST, sizeList),
}
}
// Pop will return and truncate the last container element.
func (s *ParseStack) Pop() AST {
s.top--
return s.container[s.top]
}
// Push will add the new AST to the container
func (s *ParseStack) Push(ast AST) {
s.container[s.top] = ast
s.top++
}
// MarkComplete will append the AST to the list of completed statements
func (s *ParseStack) MarkComplete(ast AST) {
s.list[s.index] = ast
s.index++
}
// List will return the completed statements
func (s ParseStack) List() []AST {
return s.list[:s.index]
}
// Len will return the length of the container
func (s *ParseStack) Len() int {
return s.top
}
func (s ParseStack) String() string {
buf := bytes.Buffer{}
for i, node := range s.list {
buf.WriteString(fmt.Sprintf("%d: %v\n", i+1, node))
}
return buf.String()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/sep_tokens.go
================================================
package ini
import (
"fmt"
)
var (
emptyRunes = []rune{}
)
func isSep(b []rune) bool {
if len(b) == 0 {
return false
}
switch b[0] {
case '[', ']':
return true
default:
return false
}
}
var (
openBrace = []rune("[")
closeBrace = []rune("]")
)
func newSepToken(b []rune) (Token, int, error) {
tok := Token{}
switch b[0] {
case '[':
tok = newToken(TokenSep, openBrace, NoneType)
case ']':
tok = newToken(TokenSep, closeBrace, NoneType)
default:
return tok, 0, NewParseError(fmt.Sprintf("unexpected sep type, %v", b[0]))
}
return tok, 1, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/skipper.go
================================================
package ini
// skipper is used to skip certain blocks of an ini file.
// Currently skipper is used to skip nested blocks of ini
// files. See example below
//
// [ foo ]
// nested = ; this section will be skipped
// a=b
// c=d
// bar=baz ; this will be included
type skipper struct {
shouldSkip bool
TokenSet bool
prevTok Token
}
func newSkipper() skipper {
return skipper{
prevTok: emptyToken,
}
}
func (s *skipper) ShouldSkip(tok Token) bool {
// should skip state will be modified only if previous token was new line (NL);
// and the current token is not WhiteSpace (WS).
if s.shouldSkip &&
s.prevTok.Type() == TokenNL &&
tok.Type() != TokenWS {
s.Continue()
return false
}
s.prevTok = tok
return s.shouldSkip
}
func (s *skipper) Skip() {
s.shouldSkip = true
}
func (s *skipper) Continue() {
s.shouldSkip = false
// empty token is assigned as we return to default state, when should skip is false
s.prevTok = emptyToken
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/statement.go
================================================
package ini
// Statement is an empty AST mostly used for transitioning states.
func newStatement() AST {
return newAST(ASTKindStatement, AST{})
}
// SectionStatement represents a section AST
func newSectionStatement(tok Token) AST {
return newASTWithRootToken(ASTKindSectionStatement, tok)
}
// ExprStatement represents a completed expression AST
func newExprStatement(ast AST) AST {
return newAST(ASTKindExprStatement, ast)
}
// CommentStatement represents a comment in the ini definition.
//
// grammar:
// comment -> #comment' | ;comment'
// comment' -> epsilon | value
func newCommentStatement(tok Token) AST {
return newAST(ASTKindCommentStatement, newExpression(tok))
}
// CompletedSectionStatement represents a completed section
func newCompletedSectionStatement(ast AST) AST {
return newAST(ASTKindCompletedSectionStatement, ast)
}
// SkipStatement is used to skip whole statements
func newSkipStatement(ast AST) AST {
return newAST(ASTKindSkipStatement, ast)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/value_util.go
================================================
package ini
import (
"fmt"
)
// getStringValue will return a quoted string and the amount
// of bytes read
//
// an error will be returned if the string is not properly formatted
func getStringValue(b []rune) (int, error) {
if b[0] != '"' {
return 0, NewParseError("strings must start with '\"'")
}
endQuote := false
i := 1
for ; i < len(b) && !endQuote; i++ {
if escaped := isEscaped(b[:i], b[i]); b[i] == '"' && !escaped {
endQuote = true
break
} else if escaped {
/*c, err := getEscapedByte(b[i])
if err != nil {
return 0, err
}
b[i-1] = c
b = append(b[:i], b[i+1:]...)
i--*/
continue
}
}
if !endQuote {
return 0, NewParseError("missing '\"' in string value")
}
return i + 1, nil
}
// getBoolValue will return a boolean and the amount
// of bytes read
//
// an error will be returned if the boolean is not of a correct
// value
func getBoolValue(b []rune) (int, error) {
if len(b) < 4 {
return 0, NewParseError("invalid boolean value")
}
n := 0
for _, lv := range literalValues {
if len(lv) > len(b) {
continue
}
if isCaselessLitValue(lv, b) {
n = len(lv)
}
}
if n == 0 {
return 0, NewParseError("invalid boolean value")
}
return n, nil
}
// getNumericalValue will return a numerical string, the amount
// of bytes read, and the base of the number
//
// an error will be returned if the number is not of a correct
// value
func getNumericalValue(b []rune) (int, int, error) {
if !isDigit(b[0]) {
return 0, 0, NewParseError("invalid digit value")
}
i := 0
helper := numberHelper{}
loop:
for negativeIndex := 0; i < len(b); i++ {
negativeIndex++
if !isDigit(b[i]) {
switch b[i] {
case '-':
if helper.IsNegative() || negativeIndex != 1 {
return 0, 0, NewParseError("parse error '-'")
}
n := getNegativeNumber(b[i:])
i += (n - 1)
helper.Determine(b[i])
continue
case '.':
if err := helper.Determine(b[i]); err != nil {
return 0, 0, err
}
case 'e', 'E':
if err := helper.Determine(b[i]); err != nil {
return 0, 0, err
}
negativeIndex = 0
case 'b':
if helper.numberFormat == hex {
break
}
fallthrough
case 'o', 'x':
if i == 0 && b[i] != '0' {
return 0, 0, NewParseError("incorrect base format, expected leading '0'")
}
if i != 1 {
return 0, 0, NewParseError(fmt.Sprintf("incorrect base format found %s at %d index", string(b[i]), i))
}
if err := helper.Determine(b[i]); err != nil {
return 0, 0, err
}
default:
if isWhitespace(b[i]) {
break loop
}
if isNewline(b[i:]) {
break loop
}
if !(helper.numberFormat == hex && isHexByte(b[i])) {
if i+2 < len(b) && !isNewline(b[i:i+2]) {
return 0, 0, NewParseError("invalid numerical character")
} else if !isNewline([]rune{b[i]}) {
return 0, 0, NewParseError("invalid numerical character")
}
break loop
}
}
}
}
return helper.Base(), i, nil
}
// isDigit will return whether or not something is an integer
func isDigit(b rune) bool {
return b >= '0' && b <= '9'
}
func hasExponent(v []rune) bool {
return contains(v, 'e') || contains(v, 'E')
}
func isBinaryByte(b rune) bool {
switch b {
case '0', '1':
return true
default:
return false
}
}
func isOctalByte(b rune) bool {
switch b {
case '0', '1', '2', '3', '4', '5', '6', '7':
return true
default:
return false
}
}
func isHexByte(b rune) bool {
if isDigit(b) {
return true
}
return (b >= 'A' && b <= 'F') ||
(b >= 'a' && b <= 'f')
}
func getValue(b []rune) (int, error) {
i := 0
for i < len(b) {
if isNewline(b[i:]) {
break
}
if isOp(b[i:]) {
break
}
valid, n, err := isValid(b[i:])
if err != nil {
return 0, err
}
if !valid {
break
}
i += n
}
return i, nil
}
// getNegativeNumber will return a negative number from a
// byte slice. This will iterate through all characters until
// a non-digit has been found.
func getNegativeNumber(b []rune) int {
if b[0] != '-' {
return 0
}
i := 1
for ; i < len(b); i++ {
if !isDigit(b[i]) {
return i
}
}
return i
}
// isEscaped will return whether or not the character is an escaped
// character.
func isEscaped(value []rune, b rune) bool {
if len(value) == 0 {
return false
}
switch b {
case '\'': // single quote
case '"': // quote
case 'n': // newline
case 't': // tab
case '\\': // backslash
default:
return false
}
return value[len(value)-1] == '\\'
}
func getEscapedByte(b rune) (rune, error) {
switch b {
case '\'': // single quote
return '\'', nil
case '"': // quote
return '"', nil
case 'n': // newline
return '\n', nil
case 't': // table
return '\t', nil
case '\\': // backslash
return '\\', nil
default:
return b, NewParseError(fmt.Sprintf("invalid escaped character %c", b))
}
}
func removeEscapedCharacters(b []rune) []rune {
for i := 0; i < len(b); i++ {
if isEscaped(b[:i], b[i]) {
c, err := getEscapedByte(b[i])
if err != nil {
return b
}
b[i-1] = c
b = append(b[:i], b[i+1:]...)
i--
}
}
return b
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/visitor.go
================================================
package ini
import (
"fmt"
"sort"
)
// Visitor is an interface used by walkers that will
// traverse an array of ASTs.
type Visitor interface {
VisitExpr(AST) error
VisitStatement(AST) error
}
// DefaultVisitor is used to visit statements and expressions
// and ensure that they are both of the correct format.
// In addition, upon visiting this will build sections and populate
// the Sections field which can be used to retrieve profile
// configuration.
type DefaultVisitor struct {
scope string
Sections Sections
}
// NewDefaultVisitor return a DefaultVisitor
func NewDefaultVisitor() *DefaultVisitor {
return &DefaultVisitor{
Sections: Sections{
container: map[string]Section{},
},
}
}
// VisitExpr visits expressions...
func (v *DefaultVisitor) VisitExpr(expr AST) error {
t := v.Sections.container[v.scope]
if t.values == nil {
t.values = values{}
}
switch expr.Kind {
case ASTKindExprStatement:
opExpr := expr.GetRoot()
switch opExpr.Kind {
case ASTKindEqualExpr:
children := opExpr.GetChildren()
if len(children) <= 1 {
return NewParseError("unexpected token type")
}
rhs := children[1]
// The right-hand value side the equality expression is allowed to contain '[', ']', ':', '=' in the values.
// If the token is not either a literal or one of the token types that identifies those four additional
// tokens then error.
if !(rhs.Root.Type() == TokenLit || rhs.Root.Type() == TokenOp || rhs.Root.Type() == TokenSep) {
return NewParseError("unexpected token type")
}
key := EqualExprKey(opExpr)
v, err := newValue(rhs.Root.ValueType, rhs.Root.base, rhs.Root.Raw())
if err != nil {
return err
}
t.values[key] = v
default:
return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
}
default:
return NewParseError(fmt.Sprintf("unsupported expression %v", expr))
}
v.Sections.container[v.scope] = t
return nil
}
// VisitStatement visits statements...
func (v *DefaultVisitor) VisitStatement(stmt AST) error {
switch stmt.Kind {
case ASTKindCompletedSectionStatement:
child := stmt.GetRoot()
if child.Kind != ASTKindSectionStatement {
return NewParseError(fmt.Sprintf("unsupported child statement: %T", child))
}
name := string(child.Root.Raw())
v.Sections.container[name] = Section{}
v.scope = name
default:
return NewParseError(fmt.Sprintf("unsupported statement: %s", stmt.Kind))
}
return nil
}
// Sections is a map of Section structures that represent
// a configuration.
type Sections struct {
container map[string]Section
}
// GetSection will return section p. If section p does not exist,
// false will be returned in the second parameter.
func (t Sections) GetSection(p string) (Section, bool) {
v, ok := t.container[p]
return v, ok
}
// values represents a map of union values.
type values map[string]Value
// List will return a list of all sections that were successfully
// parsed.
func (t Sections) List() []string {
keys := make([]string, len(t.container))
i := 0
for k := range t.container {
keys[i] = k
i++
}
sort.Strings(keys)
return keys
}
// Section contains a name and values. This represent
// a sectioned entry in a configuration file.
type Section struct {
Name string
values values
}
// Has will return whether or not an entry exists in a given section
func (t Section) Has(k string) bool {
_, ok := t.values[k]
return ok
}
// ValueType will returned what type the union is set to. If
// k was not found, the NoneType will be returned.
func (t Section) ValueType(k string) (ValueType, bool) {
v, ok := t.values[k]
return v.Type, ok
}
// Bool returns a bool value at k
func (t Section) Bool(k string) bool {
return t.values[k].BoolValue()
}
// Int returns an integer value at k
func (t Section) Int(k string) int64 {
return t.values[k].IntValue()
}
// Float64 returns a float value at k
func (t Section) Float64(k string) float64 {
return t.values[k].FloatValue()
}
// String returns the string value at k
func (t Section) String(k string) string {
_, ok := t.values[k]
if !ok {
return ""
}
return t.values[k].StringValue()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/walker.go
================================================
package ini
// Walk will traverse the AST using the v, the Visitor.
func Walk(tree []AST, v Visitor) error {
for _, node := range tree {
switch node.Kind {
case ASTKindExpr,
ASTKindExprStatement:
if err := v.VisitExpr(node); err != nil {
return err
}
case ASTKindStatement,
ASTKindCompletedSectionStatement,
ASTKindNestedSectionStatement,
ASTKindCompletedNestedSectionStatement:
if err := v.VisitStatement(node); err != nil {
return err
}
}
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/ini/ws_token.go
================================================
package ini
import (
"unicode"
)
// isWhitespace will return whether or not the character is
// a whitespace character.
//
// Whitespace is defined as a space or tab.
func isWhitespace(c rune) bool {
return unicode.IsSpace(c) && c != '\n' && c != '\r'
}
func newWSToken(b []rune) (Token, int, error) {
i := 0
for ; i < len(b); i++ {
if !isWhitespace(b[i]) {
break
}
}
return newToken(TokenWS, b[:i], NoneType), i, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkio/byte.go
================================================
package sdkio
const (
// Byte is 8 bits
Byte int64 = 1
// KibiByte (KiB) is 1024 Bytes
KibiByte = Byte * 1024
// MebiByte (MiB) is 1024 KiB
MebiByte = KibiByte * 1024
// GibiByte (GiB) is 1024 MiB
GibiByte = MebiByte * 1024
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.6.go
================================================
//go:build !go1.7
// +build !go1.7
package sdkio
// Copy of Go 1.7 io package's Seeker constants.
const (
SeekStart = 0 // seek relative to the origin of the file
SeekCurrent = 1 // seek relative to the current offset
SeekEnd = 2 // seek relative to the end
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkio/io_go1.7.go
================================================
//go:build go1.7
// +build go1.7
package sdkio
import "io"
// Alias for Go 1.7 io package Seeker constants
const (
SeekStart = io.SeekStart // seek relative to the origin of the file
SeekCurrent = io.SeekCurrent // seek relative to the current offset
SeekEnd = io.SeekEnd // seek relative to the end
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkmath/floor.go
================================================
//go:build go1.10
// +build go1.10
package sdkmath
import "math"
// Round returns the nearest integer, rounding half away from zero.
//
// Special cases are:
// Round(±0) = ±0
// Round(±Inf) = ±Inf
// Round(NaN) = NaN
func Round(x float64) float64 {
return math.Round(x)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkmath/floor_go1.9.go
================================================
//go:build !go1.10
// +build !go1.10
package sdkmath
import "math"
// Copied from the Go standard library's (Go 1.12) math/floor.go for use in
// Go version prior to Go 1.10.
const (
uvone = 0x3FF0000000000000
mask = 0x7FF
shift = 64 - 11 - 1
bias = 1023
signMask = 1 << 63
fracMask = 1<= 0.5 {
// return t + Copysign(1, x)
// }
// return t
// }
bits := math.Float64bits(x)
e := uint(bits>>shift) & mask
if e < bias {
// Round abs(x) < 1 including denormals.
bits &= signMask // +-0
if e == bias-1 {
bits |= uvone // +-1
}
} else if e < bias+shift {
// Round any abs(x) >= 1 containing a fractional component [0,1).
//
// Numbers with larger exponents are returned unchanged since they
// must be either an integer, infinity, or NaN.
const half = 1 << (shift - 1)
e -= bias
bits += half >> e
bits &^= fracMask >> e
}
return math.Float64frombits(bits)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkrand/locked_source.go
================================================
package sdkrand
import (
"math/rand"
"sync"
"time"
)
// lockedSource is a thread-safe implementation of rand.Source
type lockedSource struct {
lk sync.Mutex
src rand.Source
}
func (r *lockedSource) Int63() (n int64) {
r.lk.Lock()
n = r.src.Int63()
r.lk.Unlock()
return
}
func (r *lockedSource) Seed(seed int64) {
r.lk.Lock()
r.src.Seed(seed)
r.lk.Unlock()
}
// SeededRand is a new RNG using a thread safe implementation of rand.Source
var SeededRand = rand.New(&lockedSource{src: rand.NewSource(time.Now().UnixNano())})
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkrand/read.go
================================================
//go:build go1.6
// +build go1.6
package sdkrand
import "math/rand"
// Read provides the stub for math.Rand.Read method support for go version's
// 1.6 and greater.
func Read(r *rand.Rand, p []byte) (int, error) {
return r.Read(p)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkrand/read_1_5.go
================================================
//go:build !go1.6
// +build !go1.6
package sdkrand
import "math/rand"
// Read backfills Go 1.6's math.Rand.Reader for Go 1.5
func Read(r *rand.Rand, p []byte) (n int, err error) {
// Copy of Go standard libraries math package's read function not added to
// standard library until Go 1.6.
var pos int8
var val int64
for n = 0; n < len(p); n++ {
if pos == 0 {
val = r.Int63()
pos = 7
}
p[n] = byte(val)
val >>= 8
pos--
}
return n, err
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sdkuri/path.go
================================================
package sdkuri
import (
"path"
"strings"
)
// PathJoin will join the elements of the path delimited by the "/"
// character. Similar to path.Join with the exception the trailing "/"
// character is preserved if present.
func PathJoin(elems ...string) string {
if len(elems) == 0 {
return ""
}
hasTrailing := strings.HasSuffix(elems[len(elems)-1], "/")
str := path.Join(elems...)
if hasTrailing && str != "/" {
str += "/"
}
return str
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/ecs_container.go
================================================
package shareddefaults
const (
// ECSCredsProviderEnvVar is an environmental variable key used to
// determine which path needs to be hit.
ECSCredsProviderEnvVar = "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI"
)
// ECSContainerCredentialsURI is the endpoint to retrieve container
// credentials. This can be overridden to test to ensure the credential process
// is behaving correctly.
var ECSContainerCredentialsURI = "http://169.254.170.2"
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/shareddefaults/shared_config.go
================================================
package shareddefaults
import (
"os"
"path/filepath"
"runtime"
)
// SharedCredentialsFilename returns the SDK's default file path
// for the shared credentials file.
//
// Builds the shared config file path based on the OS's platform.
//
// - Linux/Unix: $HOME/.aws/credentials
// - Windows: %USERPROFILE%\.aws\credentials
func SharedCredentialsFilename() string {
return filepath.Join(UserHomeDir(), ".aws", "credentials")
}
// SharedConfigFilename returns the SDK's default file path for
// the shared config file.
//
// Builds the shared config file path based on the OS's platform.
//
// - Linux/Unix: $HOME/.aws/config
// - Windows: %USERPROFILE%\.aws\config
func SharedConfigFilename() string {
return filepath.Join(UserHomeDir(), ".aws", "config")
}
// UserHomeDir returns the home directory for the user the process is
// running under.
func UserHomeDir() string {
if runtime.GOOS == "windows" { // Windows
return os.Getenv("USERPROFILE")
}
// *nix
return os.Getenv("HOME")
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/strings/strings.go
================================================
package strings
import (
"strings"
)
// HasPrefixFold tests whether the string s begins with prefix, interpreted as UTF-8 strings,
// under Unicode case-folding.
func HasPrefixFold(s, prefix string) bool {
return len(s) >= len(prefix) && strings.EqualFold(s[0:len(prefix)], prefix)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sync/singleflight/LICENSE
================================================
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/aws/aws-sdk-go/internal/sync/singleflight/singleflight.go
================================================
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package singleflight provides a duplicate function call suppression
// mechanism.
package singleflight
import "sync"
// call is an in-flight or completed singleflight.Do call
type call struct {
wg sync.WaitGroup
// These fields are written once before the WaitGroup is done
// and are only read after the WaitGroup is done.
val interface{}
err error
// forgotten indicates whether Forget was called with this call's key
// while the call was still in flight.
forgotten bool
// These fields are read and written with the singleflight
// mutex held before the WaitGroup is done, and are read but
// not written after the WaitGroup is done.
dups int
chans []chan<- Result
}
// Group represents a class of work and forms a namespace in
// which units of work can be executed with duplicate suppression.
type Group struct {
mu sync.Mutex // protects m
m map[string]*call // lazily initialized
}
// Result holds the results of Do, so they can be passed
// on a channel.
type Result struct {
Val interface{}
Err error
Shared bool
}
// Do executes and returns the results of the given function, making
// sure that only one execution is in-flight for a given key at a
// time. If a duplicate comes in, the duplicate caller waits for the
// original to complete and receives the same results.
// The return value shared indicates whether v was given to multiple callers.
func (g *Group) Do(key string, fn func() (interface{}, error)) (v interface{}, err error, shared bool) {
g.mu.Lock()
if g.m == nil {
g.m = make(map[string]*call)
}
if c, ok := g.m[key]; ok {
c.dups++
g.mu.Unlock()
c.wg.Wait()
return c.val, c.err, true
}
c := new(call)
c.wg.Add(1)
g.m[key] = c
g.mu.Unlock()
g.doCall(c, key, fn)
return c.val, c.err, c.dups > 0
}
// DoChan is like Do but returns a channel that will receive the
// results when they are ready.
func (g *Group) DoChan(key string, fn func() (interface{}, error)) <-chan Result {
ch := make(chan Result, 1)
g.mu.Lock()
if g.m == nil {
g.m = make(map[string]*call)
}
if c, ok := g.m[key]; ok {
c.dups++
c.chans = append(c.chans, ch)
g.mu.Unlock()
return ch
}
c := &call{chans: []chan<- Result{ch}}
c.wg.Add(1)
g.m[key] = c
g.mu.Unlock()
go g.doCall(c, key, fn)
return ch
}
// doCall handles the single call for a key.
func (g *Group) doCall(c *call, key string, fn func() (interface{}, error)) {
c.val, c.err = fn()
c.wg.Done()
g.mu.Lock()
if !c.forgotten {
delete(g.m, key)
}
for _, ch := range c.chans {
ch <- Result{c.val, c.err, c.dups > 0}
}
g.mu.Unlock()
}
// Forget tells the singleflight to forget about a key. Future calls
// to Do for this key will call the function rather than waiting for
// an earlier call to complete.
func (g *Group) Forget(key string) {
g.mu.Lock()
if c, ok := g.m[key]; ok {
c.forgotten = true
}
delete(g.m, key)
g.mu.Unlock()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/host.go
================================================
package protocol
import (
"github.com/aws/aws-sdk-go/aws/request"
"net"
"strconv"
"strings"
)
// ValidateEndpointHostHandler is a request handler that will validate the
// request endpoint's hosts is a valid RFC 3986 host.
var ValidateEndpointHostHandler = request.NamedHandler{
Name: "awssdk.protocol.ValidateEndpointHostHandler",
Fn: func(r *request.Request) {
err := ValidateEndpointHost(r.Operation.Name, r.HTTPRequest.URL.Host)
if err != nil {
r.Error = err
}
},
}
// ValidateEndpointHost validates that the host string passed in is a valid RFC
// 3986 host. Returns error if the host is not valid.
func ValidateEndpointHost(opName, host string) error {
paramErrs := request.ErrInvalidParams{Context: opName}
var hostname string
var port string
var err error
if strings.Contains(host, ":") {
hostname, port, err = net.SplitHostPort(host)
if err != nil {
paramErrs.Add(request.NewErrParamFormat("endpoint", err.Error(), host))
}
if !ValidPortNumber(port) {
paramErrs.Add(request.NewErrParamFormat("endpoint port number", "[0-65535]", port))
}
} else {
hostname = host
}
labels := strings.Split(hostname, ".")
for i, label := range labels {
if i == len(labels)-1 && len(label) == 0 {
// Allow trailing dot for FQDN hosts.
continue
}
if !ValidHostLabel(label) {
paramErrs.Add(request.NewErrParamFormat(
"endpoint host label", "[a-zA-Z0-9-]{1,63}", label))
}
}
if len(hostname) == 0 {
paramErrs.Add(request.NewErrParamMinLen("endpoint host", 1))
}
if len(hostname) > 255 {
paramErrs.Add(request.NewErrParamMaxLen(
"endpoint host", 255, host,
))
}
if paramErrs.Len() > 0 {
return paramErrs
}
return nil
}
// ValidHostLabel returns if the label is a valid RFC 3986 host label.
func ValidHostLabel(label string) bool {
if l := len(label); l == 0 || l > 63 {
return false
}
for _, r := range label {
switch {
case r >= '0' && r <= '9':
case r >= 'A' && r <= 'Z':
case r >= 'a' && r <= 'z':
case r == '-':
default:
return false
}
}
return true
}
// ValidPortNumber return if the port is valid RFC 3986 port
func ValidPortNumber(port string) bool {
i, err := strconv.Atoi(port)
if err != nil {
return false
}
if i < 0 || i > 65535 {
return false
}
return true
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/host_prefix.go
================================================
package protocol
import (
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
)
// HostPrefixHandlerName is the handler name for the host prefix request
// handler.
const HostPrefixHandlerName = "awssdk.endpoint.HostPrefixHandler"
// NewHostPrefixHandler constructs a build handler
func NewHostPrefixHandler(prefix string, labelsFn func() map[string]string) request.NamedHandler {
builder := HostPrefixBuilder{
Prefix: prefix,
LabelsFn: labelsFn,
}
return request.NamedHandler{
Name: HostPrefixHandlerName,
Fn: builder.Build,
}
}
// HostPrefixBuilder provides the request handler to expand and prepend
// the host prefix into the operation's request endpoint host.
type HostPrefixBuilder struct {
Prefix string
LabelsFn func() map[string]string
}
// Build updates the passed in Request with the HostPrefix template expanded.
func (h HostPrefixBuilder) Build(r *request.Request) {
if aws.BoolValue(r.Config.DisableEndpointHostPrefix) {
return
}
var labels map[string]string
if h.LabelsFn != nil {
labels = h.LabelsFn()
}
prefix := h.Prefix
for name, value := range labels {
prefix = strings.Replace(prefix, "{"+name+"}", value, -1)
}
r.HTTPRequest.URL.Host = prefix + r.HTTPRequest.URL.Host
if len(r.HTTPRequest.Host) > 0 {
r.HTTPRequest.Host = prefix + r.HTTPRequest.Host
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/idempotency.go
================================================
package protocol
import (
"crypto/rand"
"fmt"
"reflect"
)
// RandReader is the random reader the protocol package will use to read
// random bytes from. This is exported for testing, and should not be used.
var RandReader = rand.Reader
const idempotencyTokenFillTag = `idempotencyToken`
// CanSetIdempotencyToken returns true if the struct field should be
// automatically populated with a Idempotency token.
//
// Only *string and string type fields that are tagged with idempotencyToken
// which are not already set can be auto filled.
func CanSetIdempotencyToken(v reflect.Value, f reflect.StructField) bool {
switch u := v.Interface().(type) {
// To auto fill an Idempotency token the field must be a string,
// tagged for auto fill, and have a zero value.
case *string:
return u == nil && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
case string:
return len(u) == 0 && len(f.Tag.Get(idempotencyTokenFillTag)) != 0
}
return false
}
// GetIdempotencyToken returns a randomly generated idempotency token.
func GetIdempotencyToken() string {
b := make([]byte, 16)
RandReader.Read(b)
return UUIDVersion4(b)
}
// SetIdempotencyToken will set the value provided with a Idempotency Token.
// Given that the value can be set. Will panic if value is not setable.
func SetIdempotencyToken(v reflect.Value) {
if v.Kind() == reflect.Ptr {
if v.IsNil() && v.CanSet() {
v.Set(reflect.New(v.Type().Elem()))
}
v = v.Elem()
}
v = reflect.Indirect(v)
if !v.CanSet() {
panic(fmt.Sprintf("unable to set idempotnecy token %v", v))
}
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
// TODO handle error
return
}
v.Set(reflect.ValueOf(UUIDVersion4(b)))
}
// UUIDVersion4 returns a Version 4 random UUID from the byte slice provided
func UUIDVersion4(u []byte) string {
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
// 13th character is "4"
u[6] = (u[6] | 0x40) & 0x4F
// 17th character is "8", "9", "a", or "b"
u[8] = (u[8] | 0x80) & 0xBF
return fmt.Sprintf(`%X-%X-%X-%X-%X`, u[0:4], u[4:6], u[6:8], u[8:10], u[10:])
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/build.go
================================================
// Package jsonutil provides JSON serialization of AWS requests and responses.
package jsonutil
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"math"
"reflect"
"sort"
"strconv"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/private/protocol"
)
var timeType = reflect.ValueOf(time.Time{}).Type()
var byteSliceType = reflect.ValueOf([]byte{}).Type()
// BuildJSON builds a JSON string for a given object v.
func BuildJSON(v interface{}) ([]byte, error) {
var buf bytes.Buffer
err := buildAny(reflect.ValueOf(v), &buf, "")
return buf.Bytes(), err
}
func buildAny(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
origVal := value
value = reflect.Indirect(value)
if !value.IsValid() {
return nil
}
vtype := value.Type()
t := tag.Get("type")
if t == "" {
switch vtype.Kind() {
case reflect.Struct:
// also it can't be a time object
if value.Type() != timeType {
t = "structure"
}
case reflect.Slice:
// also it can't be a byte slice
if _, ok := value.Interface().([]byte); !ok {
t = "list"
}
case reflect.Map:
// cannot be a JSONValue map
if _, ok := value.Interface().(aws.JSONValue); !ok {
t = "map"
}
}
}
switch t {
case "structure":
if field, ok := vtype.FieldByName("_"); ok {
tag = field.Tag
}
return buildStruct(value, buf, tag)
case "list":
return buildList(value, buf, tag)
case "map":
return buildMap(value, buf, tag)
default:
return buildScalar(origVal, buf, tag)
}
}
func buildStruct(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
if !value.IsValid() {
return nil
}
// unwrap payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := value.Type().FieldByName(payload)
tag = field.Tag
value = elemOf(value.FieldByName(payload))
if !value.IsValid() && tag.Get("type") != "structure" {
return nil
}
}
buf.WriteByte('{')
defer buf.WriteString("}")
if !value.IsValid() {
return nil
}
t := value.Type()
first := true
for i := 0; i < t.NumField(); i++ {
member := value.Field(i)
// This allocates the most memory.
// Additionally, we cannot skip nil fields due to
// idempotency auto filling.
field := t.Field(i)
if field.PkgPath != "" {
continue // ignore unexported fields
}
if field.Tag.Get("json") == "-" {
continue
}
if field.Tag.Get("location") != "" {
continue // ignore non-body elements
}
if field.Tag.Get("ignore") != "" {
continue
}
if protocol.CanSetIdempotencyToken(member, field) {
token := protocol.GetIdempotencyToken()
member = reflect.ValueOf(&token)
}
if (member.Kind() == reflect.Ptr || member.Kind() == reflect.Slice || member.Kind() == reflect.Map) && member.IsNil() {
continue // ignore unset fields
}
if first {
first = false
} else {
buf.WriteByte(',')
}
// figure out what this field is called
name := field.Name
if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
writeString(name, buf)
buf.WriteString(`:`)
err := buildAny(member, buf, field.Tag)
if err != nil {
return err
}
}
return nil
}
func buildList(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
buf.WriteString("[")
for i := 0; i < value.Len(); i++ {
buildAny(value.Index(i), buf, "")
if i < value.Len()-1 {
buf.WriteString(",")
}
}
buf.WriteString("]")
return nil
}
type sortedValues []reflect.Value
func (sv sortedValues) Len() int { return len(sv) }
func (sv sortedValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
func (sv sortedValues) Less(i, j int) bool { return sv[i].String() < sv[j].String() }
func buildMap(value reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
buf.WriteString("{")
sv := sortedValues(value.MapKeys())
sort.Sort(sv)
for i, k := range sv {
if i > 0 {
buf.WriteByte(',')
}
writeString(k.String(), buf)
buf.WriteString(`:`)
buildAny(value.MapIndex(k), buf, "")
}
buf.WriteString("}")
return nil
}
func buildScalar(v reflect.Value, buf *bytes.Buffer, tag reflect.StructTag) error {
// prevents allocation on the heap.
scratch := [64]byte{}
switch value := reflect.Indirect(v); value.Kind() {
case reflect.String:
writeString(value.String(), buf)
case reflect.Bool:
if value.Bool() {
buf.WriteString("true")
} else {
buf.WriteString("false")
}
case reflect.Int64:
buf.Write(strconv.AppendInt(scratch[:0], value.Int(), 10))
case reflect.Float64:
f := value.Float()
if math.IsInf(f, 0) || math.IsNaN(f) {
return &json.UnsupportedValueError{Value: v, Str: strconv.FormatFloat(f, 'f', -1, 64)}
}
buf.Write(strconv.AppendFloat(scratch[:0], f, 'f', -1, 64))
default:
switch converted := value.Interface().(type) {
case time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.UnixTimeFormatName
}
ts := protocol.FormatTime(format, converted)
if format != protocol.UnixTimeFormatName {
ts = `"` + ts + `"`
}
buf.WriteString(ts)
case []byte:
if !value.IsNil() {
buf.WriteByte('"')
if len(converted) < 1024 {
// for small buffers, using Encode directly is much faster.
dst := make([]byte, base64.StdEncoding.EncodedLen(len(converted)))
base64.StdEncoding.Encode(dst, converted)
buf.Write(dst)
} else {
// for large buffers, avoid unnecessary extra temporary
// buffer space.
enc := base64.NewEncoder(base64.StdEncoding, buf)
enc.Write(converted)
enc.Close()
}
buf.WriteByte('"')
}
case aws.JSONValue:
str, err := protocol.EncodeJSONValue(converted, protocol.QuotedEscape)
if err != nil {
return fmt.Errorf("unable to encode JSONValue, %v", err)
}
buf.WriteString(str)
default:
return fmt.Errorf("unsupported JSON value %v (%s)", value.Interface(), value.Type())
}
}
return nil
}
var hex = "0123456789abcdef"
func writeString(s string, buf *bytes.Buffer) {
buf.WriteByte('"')
for i := 0; i < len(s); i++ {
if s[i] == '"' {
buf.WriteString(`\"`)
} else if s[i] == '\\' {
buf.WriteString(`\\`)
} else if s[i] == '\b' {
buf.WriteString(`\b`)
} else if s[i] == '\f' {
buf.WriteString(`\f`)
} else if s[i] == '\r' {
buf.WriteString(`\r`)
} else if s[i] == '\t' {
buf.WriteString(`\t`)
} else if s[i] == '\n' {
buf.WriteString(`\n`)
} else if s[i] < 32 {
buf.WriteString("\\u00")
buf.WriteByte(hex[s[i]>>4])
buf.WriteByte(hex[s[i]&0xF])
} else {
buf.WriteByte(s[i])
}
}
buf.WriteByte('"')
}
// Returns the reflection element of a value, if it is a pointer.
func elemOf(value reflect.Value) reflect.Value {
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/json/jsonutil/unmarshal.go
================================================
package jsonutil
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"math/big"
"reflect"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/private/protocol"
)
var millisecondsFloat = new(big.Float).SetInt64(1e3)
// UnmarshalJSONError unmarshal's the reader's JSON document into the passed in
// type. The value to unmarshal the json document into must be a pointer to the
// type.
func UnmarshalJSONError(v interface{}, stream io.Reader) error {
var errBuf bytes.Buffer
body := io.TeeReader(stream, &errBuf)
err := json.NewDecoder(body).Decode(v)
if err != nil {
msg := "failed decoding error message"
if err == io.EOF {
msg = "error message missing"
err = nil
}
return awserr.NewUnmarshalError(err, msg, errBuf.Bytes())
}
return nil
}
// UnmarshalJSON reads a stream and unmarshals the results in object v.
func UnmarshalJSON(v interface{}, stream io.Reader) error {
var out interface{}
decoder := json.NewDecoder(stream)
decoder.UseNumber()
err := decoder.Decode(&out)
if err == io.EOF {
return nil
} else if err != nil {
return err
}
return unmarshaler{}.unmarshalAny(reflect.ValueOf(v), out, "")
}
// UnmarshalJSONCaseInsensitive reads a stream and unmarshals the result into the
// object v. Ignores casing for structure members.
func UnmarshalJSONCaseInsensitive(v interface{}, stream io.Reader) error {
var out interface{}
decoder := json.NewDecoder(stream)
decoder.UseNumber()
err := decoder.Decode(&out)
if err == io.EOF {
return nil
} else if err != nil {
return err
}
return unmarshaler{
caseInsensitive: true,
}.unmarshalAny(reflect.ValueOf(v), out, "")
}
type unmarshaler struct {
caseInsensitive bool
}
func (u unmarshaler) unmarshalAny(value reflect.Value, data interface{}, tag reflect.StructTag) error {
vtype := value.Type()
if vtype.Kind() == reflect.Ptr {
vtype = vtype.Elem() // check kind of actual element type
}
t := tag.Get("type")
if t == "" {
switch vtype.Kind() {
case reflect.Struct:
// also it can't be a time object
if _, ok := value.Interface().(*time.Time); !ok {
t = "structure"
}
case reflect.Slice:
// also it can't be a byte slice
if _, ok := value.Interface().([]byte); !ok {
t = "list"
}
case reflect.Map:
// cannot be a JSONValue map
if _, ok := value.Interface().(aws.JSONValue); !ok {
t = "map"
}
}
}
switch t {
case "structure":
if field, ok := vtype.FieldByName("_"); ok {
tag = field.Tag
}
return u.unmarshalStruct(value, data, tag)
case "list":
return u.unmarshalList(value, data, tag)
case "map":
return u.unmarshalMap(value, data, tag)
default:
return u.unmarshalScalar(value, data, tag)
}
}
func (u unmarshaler) unmarshalStruct(value reflect.Value, data interface{}, tag reflect.StructTag) error {
if data == nil {
return nil
}
mapData, ok := data.(map[string]interface{})
if !ok {
return fmt.Errorf("JSON value is not a structure (%#v)", data)
}
t := value.Type()
if value.Kind() == reflect.Ptr {
if value.IsNil() { // create the structure if it's nil
s := reflect.New(value.Type().Elem())
value.Set(s)
value = s
}
value = value.Elem()
t = t.Elem()
}
// unwrap any payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := t.FieldByName(payload)
return u.unmarshalAny(value.FieldByName(payload), data, field.Tag)
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if field.PkgPath != "" {
continue // ignore unexported fields
}
// figure out what this field is called
name := field.Name
if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
if u.caseInsensitive {
if _, ok := mapData[name]; !ok {
// Fallback to uncased name search if the exact name didn't match.
for kn, v := range mapData {
if strings.EqualFold(kn, name) {
mapData[name] = v
}
}
}
}
member := value.FieldByIndex(field.Index)
err := u.unmarshalAny(member, mapData[name], field.Tag)
if err != nil {
return err
}
}
return nil
}
func (u unmarshaler) unmarshalList(value reflect.Value, data interface{}, tag reflect.StructTag) error {
if data == nil {
return nil
}
listData, ok := data.([]interface{})
if !ok {
return fmt.Errorf("JSON value is not a list (%#v)", data)
}
if value.IsNil() {
l := len(listData)
value.Set(reflect.MakeSlice(value.Type(), l, l))
}
for i, c := range listData {
err := u.unmarshalAny(value.Index(i), c, "")
if err != nil {
return err
}
}
return nil
}
func (u unmarshaler) unmarshalMap(value reflect.Value, data interface{}, tag reflect.StructTag) error {
if data == nil {
return nil
}
mapData, ok := data.(map[string]interface{})
if !ok {
return fmt.Errorf("JSON value is not a map (%#v)", data)
}
if value.IsNil() {
value.Set(reflect.MakeMap(value.Type()))
}
for k, v := range mapData {
kvalue := reflect.ValueOf(k)
vvalue := reflect.New(value.Type().Elem()).Elem()
u.unmarshalAny(vvalue, v, "")
value.SetMapIndex(kvalue, vvalue)
}
return nil
}
func (u unmarshaler) unmarshalScalar(value reflect.Value, data interface{}, tag reflect.StructTag) error {
switch d := data.(type) {
case nil:
return nil // nothing to do here
case string:
switch value.Interface().(type) {
case *string:
value.Set(reflect.ValueOf(&d))
case []byte:
b, err := base64.StdEncoding.DecodeString(d)
if err != nil {
return err
}
value.Set(reflect.ValueOf(b))
case *time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
t, err := protocol.ParseTime(format, d)
if err != nil {
return err
}
value.Set(reflect.ValueOf(&t))
case aws.JSONValue:
// No need to use escaping as the value is a non-quoted string.
v, err := protocol.DecodeJSONValue(d, protocol.NoEscape)
if err != nil {
return err
}
value.Set(reflect.ValueOf(v))
default:
return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
}
case json.Number:
switch value.Interface().(type) {
case *int64:
// Retain the old behavior where we would just truncate the float64
// calling d.Int64() here could cause an invalid syntax error due to the usage of strconv.ParseInt
f, err := d.Float64()
if err != nil {
return err
}
di := int64(f)
value.Set(reflect.ValueOf(&di))
case *float64:
f, err := d.Float64()
if err != nil {
return err
}
value.Set(reflect.ValueOf(&f))
case *time.Time:
float, ok := new(big.Float).SetString(d.String())
if !ok {
return fmt.Errorf("unsupported float time representation: %v", d.String())
}
float = float.Mul(float, millisecondsFloat)
ms, _ := float.Int64()
t := time.Unix(0, ms*1e6).UTC()
value.Set(reflect.ValueOf(&t))
default:
return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
}
case bool:
switch value.Interface().(type) {
case *bool:
value.Set(reflect.ValueOf(&d))
default:
return fmt.Errorf("unsupported value: %v (%s)", value.Interface(), value.Type())
}
default:
return fmt.Errorf("unsupported JSON value (%v)", data)
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/jsonrpc.go
================================================
// Package jsonrpc provides JSON RPC utilities for serialization of AWS
// requests and responses.
package jsonrpc
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/input/json.json build_test.go
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/output/json.json unmarshal_test.go
import (
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
"github.com/aws/aws-sdk-go/private/protocol/rest"
)
var emptyJSON = []byte("{}")
// BuildHandler is a named request handler for building jsonrpc protocol
// requests
var BuildHandler = request.NamedHandler{
Name: "awssdk.jsonrpc.Build",
Fn: Build,
}
// UnmarshalHandler is a named request handler for unmarshaling jsonrpc
// protocol requests
var UnmarshalHandler = request.NamedHandler{
Name: "awssdk.jsonrpc.Unmarshal",
Fn: Unmarshal,
}
// UnmarshalMetaHandler is a named request handler for unmarshaling jsonrpc
// protocol request metadata
var UnmarshalMetaHandler = request.NamedHandler{
Name: "awssdk.jsonrpc.UnmarshalMeta",
Fn: UnmarshalMeta,
}
// Build builds a JSON payload for a JSON RPC request.
func Build(req *request.Request) {
var buf []byte
var err error
if req.ParamsFilled() {
buf, err = jsonutil.BuildJSON(req.Params)
if err != nil {
req.Error = awserr.New(request.ErrCodeSerialization, "failed encoding JSON RPC request", err)
return
}
} else {
buf = emptyJSON
}
// Always serialize the body, don't suppress it.
req.SetBufferBody(buf)
if req.ClientInfo.TargetPrefix != "" {
target := req.ClientInfo.TargetPrefix + "." + req.Operation.Name
req.HTTPRequest.Header.Add("X-Amz-Target", target)
}
// Only set the content type if one is not already specified and an
// JSONVersion is specified.
if ct, v := req.HTTPRequest.Header.Get("Content-Type"), req.ClientInfo.JSONVersion; len(ct) == 0 && len(v) != 0 {
jsonVersion := req.ClientInfo.JSONVersion
req.HTTPRequest.Header.Set("Content-Type", "application/x-amz-json-"+jsonVersion)
}
}
// Unmarshal unmarshals a response for a JSON RPC service.
func Unmarshal(req *request.Request) {
defer req.HTTPResponse.Body.Close()
if req.DataFilled() {
err := jsonutil.UnmarshalJSON(req.Data, req.HTTPResponse.Body)
if err != nil {
req.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization, "failed decoding JSON RPC response", err),
req.HTTPResponse.StatusCode,
req.RequestID,
)
}
}
return
}
// UnmarshalMeta unmarshals headers from a response for a JSON RPC service.
func UnmarshalMeta(req *request.Request) {
rest.UnmarshalMeta(req)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/jsonrpc/unmarshal_error.go
================================================
package jsonrpc
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
)
// UnmarshalTypedError provides unmarshaling errors API response errors
// for both typed and untyped errors.
type UnmarshalTypedError struct {
exceptions map[string]func(protocol.ResponseMetadata) error
}
// NewUnmarshalTypedError returns an UnmarshalTypedError initialized for the
// set of exception names to the error unmarshalers
func NewUnmarshalTypedError(exceptions map[string]func(protocol.ResponseMetadata) error) *UnmarshalTypedError {
return &UnmarshalTypedError{
exceptions: exceptions,
}
}
// UnmarshalError attempts to unmarshal the HTTP response error as a known
// error type. If unable to unmarshal the error type, the generic SDK error
// type will be used.
func (u *UnmarshalTypedError) UnmarshalError(
resp *http.Response,
respMeta protocol.ResponseMetadata,
) (error, error) {
var buf bytes.Buffer
var jsonErr jsonErrorResponse
teeReader := io.TeeReader(resp.Body, &buf)
err := jsonutil.UnmarshalJSONError(&jsonErr, teeReader)
if err != nil {
return nil, err
}
body := ioutil.NopCloser(&buf)
// Code may be separated by hash(#), with the last element being the code
// used by the SDK.
codeParts := strings.SplitN(jsonErr.Code, "#", 2)
code := codeParts[len(codeParts)-1]
msg := jsonErr.Message
if fn, ok := u.exceptions[code]; ok {
// If exception code is know, use associated constructor to get a value
// for the exception that the JSON body can be unmarshaled into.
v := fn(respMeta)
err := jsonutil.UnmarshalJSONCaseInsensitive(v, body)
if err != nil {
return nil, err
}
return v, nil
}
// fallback to unmodeled generic exceptions
return awserr.NewRequestFailure(
awserr.New(code, msg, nil),
respMeta.StatusCode,
respMeta.RequestID,
), nil
}
// UnmarshalErrorHandler is a named request handler for unmarshaling jsonrpc
// protocol request errors
var UnmarshalErrorHandler = request.NamedHandler{
Name: "awssdk.jsonrpc.UnmarshalError",
Fn: UnmarshalError,
}
// UnmarshalError unmarshals an error response for a JSON RPC service.
func UnmarshalError(req *request.Request) {
defer req.HTTPResponse.Body.Close()
var jsonErr jsonErrorResponse
err := jsonutil.UnmarshalJSONError(&jsonErr, req.HTTPResponse.Body)
if err != nil {
req.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to unmarshal error message", err),
req.HTTPResponse.StatusCode,
req.RequestID,
)
return
}
codes := strings.SplitN(jsonErr.Code, "#", 2)
req.Error = awserr.NewRequestFailure(
awserr.New(codes[len(codes)-1], jsonErr.Message, nil),
req.HTTPResponse.StatusCode,
req.RequestID,
)
}
type jsonErrorResponse struct {
Code string `json:"__type"`
Message string `json:"message"`
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/jsonvalue.go
================================================
package protocol
import (
"encoding/base64"
"encoding/json"
"fmt"
"strconv"
"github.com/aws/aws-sdk-go/aws"
)
// EscapeMode is the mode that should be use for escaping a value
type EscapeMode uint
// The modes for escaping a value before it is marshaled, and unmarshaled.
const (
NoEscape EscapeMode = iota
Base64Escape
QuotedEscape
)
// EncodeJSONValue marshals the value into a JSON string, and optionally base64
// encodes the string before returning it.
//
// Will panic if the escape mode is unknown.
func EncodeJSONValue(v aws.JSONValue, escape EscapeMode) (string, error) {
b, err := json.Marshal(v)
if err != nil {
return "", err
}
switch escape {
case NoEscape:
return string(b), nil
case Base64Escape:
return base64.StdEncoding.EncodeToString(b), nil
case QuotedEscape:
return strconv.Quote(string(b)), nil
}
panic(fmt.Sprintf("EncodeJSONValue called with unknown EscapeMode, %v", escape))
}
// DecodeJSONValue will attempt to decode the string input as a JSONValue.
// Optionally decoding base64 the value first before JSON unmarshaling.
//
// Will panic if the escape mode is unknown.
func DecodeJSONValue(v string, escape EscapeMode) (aws.JSONValue, error) {
var b []byte
var err error
switch escape {
case NoEscape:
b = []byte(v)
case Base64Escape:
b, err = base64.StdEncoding.DecodeString(v)
case QuotedEscape:
var u string
u, err = strconv.Unquote(v)
b = []byte(u)
default:
panic(fmt.Sprintf("DecodeJSONValue called with unknown EscapeMode, %v", escape))
}
if err != nil {
return nil, err
}
m := aws.JSONValue{}
err = json.Unmarshal(b, &m)
if err != nil {
return nil, err
}
return m, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/payload.go
================================================
package protocol
import (
"io"
"io/ioutil"
"net/http"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
)
// PayloadUnmarshaler provides the interface for unmarshaling a payload's
// reader into a SDK shape.
type PayloadUnmarshaler interface {
UnmarshalPayload(io.Reader, interface{}) error
}
// HandlerPayloadUnmarshal implements the PayloadUnmarshaler from a
// HandlerList. This provides the support for unmarshaling a payload reader to
// a shape without needing a SDK request first.
type HandlerPayloadUnmarshal struct {
Unmarshalers request.HandlerList
}
// UnmarshalPayload unmarshals the io.Reader payload into the SDK shape using
// the Unmarshalers HandlerList provided. Returns an error if unable
// unmarshaling fails.
func (h HandlerPayloadUnmarshal) UnmarshalPayload(r io.Reader, v interface{}) error {
req := &request.Request{
HTTPRequest: &http.Request{},
HTTPResponse: &http.Response{
StatusCode: 200,
Header: http.Header{},
Body: ioutil.NopCloser(r),
},
Data: v,
}
h.Unmarshalers.Run(req)
return req.Error
}
// PayloadMarshaler provides the interface for marshaling a SDK shape into and
// io.Writer.
type PayloadMarshaler interface {
MarshalPayload(io.Writer, interface{}) error
}
// HandlerPayloadMarshal implements the PayloadMarshaler from a HandlerList.
// This provides support for marshaling a SDK shape into an io.Writer without
// needing a SDK request first.
type HandlerPayloadMarshal struct {
Marshalers request.HandlerList
}
// MarshalPayload marshals the SDK shape into the io.Writer using the
// Marshalers HandlerList provided. Returns an error if unable if marshal
// fails.
func (h HandlerPayloadMarshal) MarshalPayload(w io.Writer, v interface{}) error {
req := request.New(
aws.Config{},
metadata.ClientInfo{},
request.Handlers{},
nil,
&request.Operation{HTTPMethod: "PUT"},
v,
nil,
)
h.Marshalers.Run(req)
if req.Error != nil {
return req.Error
}
io.Copy(w, req.GetBody())
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/protocol.go
================================================
package protocol
import (
"fmt"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
)
// RequireHTTPMinProtocol request handler is used to enforce that
// the target endpoint supports the given major and minor HTTP protocol version.
type RequireHTTPMinProtocol struct {
Major, Minor int
}
// Handler will mark the request.Request with an error if the
// target endpoint did not connect with the required HTTP protocol
// major and minor version.
func (p RequireHTTPMinProtocol) Handler(r *request.Request) {
if r.Error != nil || r.HTTPResponse == nil {
return
}
if !strings.HasPrefix(r.HTTPResponse.Proto, "HTTP") {
r.Error = newMinHTTPProtoError(p.Major, p.Minor, r)
}
if r.HTTPResponse.ProtoMajor < p.Major || r.HTTPResponse.ProtoMinor < p.Minor {
r.Error = newMinHTTPProtoError(p.Major, p.Minor, r)
}
}
// ErrCodeMinimumHTTPProtocolError error code is returned when the target endpoint
// did not match the required HTTP major and minor protocol version.
const ErrCodeMinimumHTTPProtocolError = "MinimumHTTPProtocolError"
func newMinHTTPProtoError(major, minor int, r *request.Request) error {
return awserr.NewRequestFailure(
awserr.New("MinimumHTTPProtocolError",
fmt.Sprintf(
"operation requires minimum HTTP protocol of HTTP/%d.%d, but was %s",
major, minor, r.HTTPResponse.Proto,
),
nil,
),
r.HTTPResponse.StatusCode, r.RequestID,
)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/query/build.go
================================================
// Package query provides serialization of AWS query requests, and responses.
package query
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/input/query.json build_test.go
import (
"net/url"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/query/queryutil"
)
// BuildHandler is a named request handler for building query protocol requests
var BuildHandler = request.NamedHandler{Name: "awssdk.query.Build", Fn: Build}
// Build builds a request for an AWS Query service.
func Build(r *request.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.ClientInfo.APIVersion},
}
if err := queryutil.Parse(body, r.Params, false); err != nil {
r.Error = awserr.New(request.ErrCodeSerialization, "failed encoding Query request", err)
return
}
if !r.IsPresigned() {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/query/queryutil/queryutil.go
================================================
package queryutil
import (
"encoding/base64"
"fmt"
"net/url"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/private/protocol"
)
// Parse parses an object i and fills a url.Values object. The isEC2 flag
// indicates if this is the EC2 Query sub-protocol.
func Parse(body url.Values, i interface{}, isEC2 bool) error {
q := queryParser{isEC2: isEC2}
return q.parseValue(body, reflect.ValueOf(i), "", "")
}
func elemOf(value reflect.Value) reflect.Value {
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value
}
type queryParser struct {
isEC2 bool
}
func (q *queryParser) parseValue(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
value = elemOf(value)
// no need to handle zero values
if !value.IsValid() {
return nil
}
t := tag.Get("type")
if t == "" {
switch value.Kind() {
case reflect.Struct:
t = "structure"
case reflect.Slice:
t = "list"
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
return q.parseStruct(v, value, prefix)
case "list":
return q.parseList(v, value, prefix, tag)
case "map":
return q.parseMap(v, value, prefix, tag)
default:
return q.parseScalar(v, value, prefix, tag)
}
}
func (q *queryParser) parseStruct(v url.Values, value reflect.Value, prefix string) error {
if !value.IsValid() {
return nil
}
t := value.Type()
for i := 0; i < value.NumField(); i++ {
elemValue := elemOf(value.Field(i))
field := t.Field(i)
if field.PkgPath != "" {
continue // ignore unexported fields
}
if field.Tag.Get("ignore") != "" {
continue
}
if protocol.CanSetIdempotencyToken(value.Field(i), field) {
token := protocol.GetIdempotencyToken()
elemValue = reflect.ValueOf(token)
}
var name string
if q.isEC2 {
name = field.Tag.Get("queryName")
}
if name == "" {
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
name = field.Tag.Get("locationNameList")
} else if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
if name != "" && q.isEC2 {
name = strings.ToUpper(name[0:1]) + name[1:]
}
}
if name == "" {
name = field.Name
}
if prefix != "" {
name = prefix + "." + name
}
if err := q.parseValue(v, elemValue, name, field.Tag); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseList(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
// If it's empty, generate an empty value
if !value.IsNil() && value.Len() == 0 {
v.Set(prefix, "")
return nil
}
if _, ok := value.Interface().([]byte); ok {
return q.parseScalar(v, value, prefix, tag)
}
// check for unflattened list member
if !q.isEC2 && tag.Get("flattened") == "" {
if listName := tag.Get("locationNameList"); listName == "" {
prefix += ".member"
} else {
prefix += "." + listName
}
}
for i := 0; i < value.Len(); i++ {
slicePrefix := prefix
if slicePrefix == "" {
slicePrefix = strconv.Itoa(i + 1)
} else {
slicePrefix = slicePrefix + "." + strconv.Itoa(i+1)
}
if err := q.parseValue(v, value.Index(i), slicePrefix, ""); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseMap(v url.Values, value reflect.Value, prefix string, tag reflect.StructTag) error {
// If it's empty, generate an empty value
if !value.IsNil() && value.Len() == 0 {
v.Set(prefix, "")
return nil
}
// check for unflattened list member
if !q.isEC2 && tag.Get("flattened") == "" {
prefix += ".entry"
}
// sort keys for improved serialization consistency.
// this is not strictly necessary for protocol support.
mapKeyValues := value.MapKeys()
mapKeys := map[string]reflect.Value{}
mapKeyNames := make([]string, len(mapKeyValues))
for i, mapKey := range mapKeyValues {
name := mapKey.String()
mapKeys[name] = mapKey
mapKeyNames[i] = name
}
sort.Strings(mapKeyNames)
for i, mapKeyName := range mapKeyNames {
mapKey := mapKeys[mapKeyName]
mapValue := value.MapIndex(mapKey)
kname := tag.Get("locationNameKey")
if kname == "" {
kname = "key"
}
vname := tag.Get("locationNameValue")
if vname == "" {
vname = "value"
}
// serialize key
var keyName string
if prefix == "" {
keyName = strconv.Itoa(i+1) + "." + kname
} else {
keyName = prefix + "." + strconv.Itoa(i+1) + "." + kname
}
if err := q.parseValue(v, mapKey, keyName, ""); err != nil {
return err
}
// serialize value
var valueName string
if prefix == "" {
valueName = strconv.Itoa(i+1) + "." + vname
} else {
valueName = prefix + "." + strconv.Itoa(i+1) + "." + vname
}
if err := q.parseValue(v, mapValue, valueName, ""); err != nil {
return err
}
}
return nil
}
func (q *queryParser) parseScalar(v url.Values, r reflect.Value, name string, tag reflect.StructTag) error {
switch value := r.Interface().(type) {
case string:
v.Set(name, value)
case []byte:
if !r.IsNil() {
v.Set(name, base64.StdEncoding.EncodeToString(value))
}
case bool:
v.Set(name, strconv.FormatBool(value))
case int64:
v.Set(name, strconv.FormatInt(value, 10))
case int:
v.Set(name, strconv.Itoa(value))
case float64:
v.Set(name, strconv.FormatFloat(value, 'f', -1, 64))
case float32:
v.Set(name, strconv.FormatFloat(float64(value), 'f', -1, 32))
case time.Time:
const ISO8601UTC = "2006-01-02T15:04:05Z"
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
v.Set(name, protocol.FormatTime(format, value))
default:
return fmt.Errorf("unsupported value for param %s: %v (%s)", name, r.Interface(), r.Type().Name())
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal.go
================================================
package query
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/output/query.json unmarshal_test.go
import (
"encoding/xml"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
)
// UnmarshalHandler is a named request handler for unmarshaling query protocol requests
var UnmarshalHandler = request.NamedHandler{Name: "awssdk.query.Unmarshal", Fn: Unmarshal}
// UnmarshalMetaHandler is a named request handler for unmarshaling query protocol request metadata
var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalMeta", Fn: UnmarshalMeta}
// Unmarshal unmarshals a response for an AWS Query service.
func Unmarshal(r *request.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
decoder := xml.NewDecoder(r.HTTPResponse.Body)
err := xmlutil.UnmarshalXML(r.Data, decoder, r.Operation.Name+"Result")
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization, "failed decoding Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
}
}
// UnmarshalMeta unmarshals header response values for an AWS Query service.
func UnmarshalMeta(r *request.Request) {
r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid")
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/query/unmarshal_error.go
================================================
package query
import (
"encoding/xml"
"fmt"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
)
// UnmarshalErrorHandler is a name request handler to unmarshal request errors
var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.query.UnmarshalError", Fn: UnmarshalError}
type xmlErrorResponse struct {
Code string `xml:"Error>Code"`
Message string `xml:"Error>Message"`
RequestID string `xml:"RequestId"`
}
type xmlResponseError struct {
xmlErrorResponse
}
func (e *xmlResponseError) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
const svcUnavailableTagName = "ServiceUnavailableException"
const errorResponseTagName = "ErrorResponse"
switch start.Name.Local {
case svcUnavailableTagName:
e.Code = svcUnavailableTagName
e.Message = "service is unavailable"
return d.Skip()
case errorResponseTagName:
return d.DecodeElement(&e.xmlErrorResponse, &start)
default:
return fmt.Errorf("unknown error response tag, %v", start)
}
}
// UnmarshalError unmarshals an error response for an AWS Query service.
func UnmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var respErr xmlResponseError
err := xmlutil.UnmarshalXMLError(&respErr, r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to unmarshal error message", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
reqID := respErr.RequestID
if len(reqID) == 0 {
reqID = r.RequestID
}
r.Error = awserr.NewRequestFailure(
awserr.New(respErr.Code, respErr.Message, nil),
r.HTTPResponse.StatusCode,
reqID,
)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/rest/build.go
================================================
// Package rest provides RESTful serialization of AWS requests and responses.
package rest
import (
"bytes"
"encoding/base64"
"fmt"
"io"
"net/http"
"net/url"
"path"
"reflect"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
)
// Whether the byte value can be sent without escaping in AWS URLs
var noEscape [256]bool
var errValueNotSet = fmt.Errorf("value not set")
var byteSliceType = reflect.TypeOf([]byte{})
func init() {
for i := 0; i < len(noEscape); i++ {
// AWS expects every character except these to be escaped
noEscape[i] = (i >= 'A' && i <= 'Z') ||
(i >= 'a' && i <= 'z') ||
(i >= '0' && i <= '9') ||
i == '-' ||
i == '.' ||
i == '_' ||
i == '~'
}
}
// BuildHandler is a named request handler for building rest protocol requests
var BuildHandler = request.NamedHandler{Name: "awssdk.rest.Build", Fn: Build}
// Build builds the REST component of a service request.
func Build(r *request.Request) {
if r.ParamsFilled() {
v := reflect.ValueOf(r.Params).Elem()
buildLocationElements(r, v, false)
buildBody(r, v)
}
}
// BuildAsGET builds the REST component of a service request with the ability to hoist
// data from the body.
func BuildAsGET(r *request.Request) {
if r.ParamsFilled() {
v := reflect.ValueOf(r.Params).Elem()
buildLocationElements(r, v, true)
buildBody(r, v)
}
}
func buildLocationElements(r *request.Request, v reflect.Value, buildGETQuery bool) {
query := r.HTTPRequest.URL.Query()
// Setup the raw path to match the base path pattern. This is needed
// so that when the path is mutated a custom escaped version can be
// stored in RawPath that will be used by the Go client.
r.HTTPRequest.URL.RawPath = r.HTTPRequest.URL.Path
for i := 0; i < v.NumField(); i++ {
m := v.Field(i)
if n := v.Type().Field(i).Name; n[0:1] == strings.ToLower(n[0:1]) {
continue
}
if m.IsValid() {
field := v.Type().Field(i)
name := field.Tag.Get("locationName")
if name == "" {
name = field.Name
}
if kind := m.Kind(); kind == reflect.Ptr {
m = m.Elem()
} else if kind == reflect.Interface {
if !m.Elem().IsValid() {
continue
}
}
if !m.IsValid() {
continue
}
if field.Tag.Get("ignore") != "" {
continue
}
// Support the ability to customize values to be marshaled as a
// blob even though they were modeled as a string. Required for S3
// API operations like SSECustomerKey is modeled as string but
// required to be base64 encoded in request.
if field.Tag.Get("marshal-as") == "blob" {
m = m.Convert(byteSliceType)
}
var err error
switch field.Tag.Get("location") {
case "headers": // header maps
err = buildHeaderMap(&r.HTTPRequest.Header, m, field.Tag)
case "header":
err = buildHeader(&r.HTTPRequest.Header, m, name, field.Tag)
case "uri":
err = buildURI(r.HTTPRequest.URL, m, name, field.Tag)
case "querystring":
err = buildQueryString(query, m, name, field.Tag)
default:
if buildGETQuery {
err = buildQueryString(query, m, name, field.Tag)
}
}
r.Error = err
}
if r.Error != nil {
return
}
}
r.HTTPRequest.URL.RawQuery = query.Encode()
if !aws.BoolValue(r.Config.DisableRestProtocolURICleaning) {
cleanPath(r.HTTPRequest.URL)
}
}
func buildBody(r *request.Request, v reflect.Value) {
if field, ok := v.Type().FieldByName("_"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
pfield, _ := v.Type().FieldByName(payloadName)
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
payload := reflect.Indirect(v.FieldByName(payloadName))
if payload.IsValid() && payload.Interface() != nil {
switch reader := payload.Interface().(type) {
case io.ReadSeeker:
r.SetReaderBody(reader)
case []byte:
r.SetBufferBody(reader)
case string:
r.SetStringBody(reader)
default:
r.Error = awserr.New(request.ErrCodeSerialization,
"failed to encode REST request",
fmt.Errorf("unknown payload type %s", payload.Type()))
}
}
}
}
}
}
func buildHeader(header *http.Header, v reflect.Value, name string, tag reflect.StructTag) error {
str, err := convertType(v, tag)
if err == errValueNotSet {
return nil
} else if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to encode REST request", err)
}
name = strings.TrimSpace(name)
str = strings.TrimSpace(str)
header.Add(name, str)
return nil
}
func buildHeaderMap(header *http.Header, v reflect.Value, tag reflect.StructTag) error {
prefix := tag.Get("locationName")
for _, key := range v.MapKeys() {
str, err := convertType(v.MapIndex(key), tag)
if err == errValueNotSet {
continue
} else if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to encode REST request", err)
}
keyStr := strings.TrimSpace(key.String())
str = strings.TrimSpace(str)
header.Add(prefix+keyStr, str)
}
return nil
}
func buildURI(u *url.URL, v reflect.Value, name string, tag reflect.StructTag) error {
value, err := convertType(v, tag)
if err == errValueNotSet {
return nil
} else if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to encode REST request", err)
}
u.Path = strings.Replace(u.Path, "{"+name+"}", value, -1)
u.Path = strings.Replace(u.Path, "{"+name+"+}", value, -1)
u.RawPath = strings.Replace(u.RawPath, "{"+name+"}", EscapePath(value, true), -1)
u.RawPath = strings.Replace(u.RawPath, "{"+name+"+}", EscapePath(value, false), -1)
return nil
}
func buildQueryString(query url.Values, v reflect.Value, name string, tag reflect.StructTag) error {
switch value := v.Interface().(type) {
case []*string:
for _, item := range value {
query.Add(name, *item)
}
case map[string]*string:
for key, item := range value {
query.Add(key, *item)
}
case map[string][]*string:
for key, items := range value {
for _, item := range items {
query.Add(key, *item)
}
}
default:
str, err := convertType(v, tag)
if err == errValueNotSet {
return nil
} else if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to encode REST request", err)
}
query.Set(name, str)
}
return nil
}
func cleanPath(u *url.URL) {
hasSlash := strings.HasSuffix(u.Path, "/")
// clean up path, removing duplicate `/`
u.Path = path.Clean(u.Path)
u.RawPath = path.Clean(u.RawPath)
if hasSlash && !strings.HasSuffix(u.Path, "/") {
u.Path += "/"
u.RawPath += "/"
}
}
// EscapePath escapes part of a URL path in Amazon style
func EscapePath(path string, encodeSep bool) string {
var buf bytes.Buffer
for i := 0; i < len(path); i++ {
c := path[i]
if noEscape[c] || (c == '/' && !encodeSep) {
buf.WriteByte(c)
} else {
fmt.Fprintf(&buf, "%%%02X", c)
}
}
return buf.String()
}
func convertType(v reflect.Value, tag reflect.StructTag) (str string, err error) {
v = reflect.Indirect(v)
if !v.IsValid() {
return "", errValueNotSet
}
switch value := v.Interface().(type) {
case string:
if tag.Get("suppressedJSONValue") == "true" && tag.Get("location") == "header" {
value = base64.StdEncoding.EncodeToString([]byte(value))
}
str = value
case []*string:
if tag.Get("location") != "header" || tag.Get("enum") == "" {
return "", fmt.Errorf("%T is only supported with location header and enum shapes", value)
}
buff := &bytes.Buffer{}
for i, sv := range value {
if sv == nil || len(*sv) == 0 {
continue
}
if i != 0 {
buff.WriteRune(',')
}
item := *sv
if strings.Index(item, `,`) != -1 || strings.Index(item, `"`) != -1 {
item = strconv.Quote(item)
}
buff.WriteString(item)
}
str = string(buff.Bytes())
case []byte:
str = base64.StdEncoding.EncodeToString(value)
case bool:
str = strconv.FormatBool(value)
case int64:
str = strconv.FormatInt(value, 10)
case float64:
str = strconv.FormatFloat(value, 'f', -1, 64)
case time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.RFC822TimeFormatName
if tag.Get("location") == "querystring" {
format = protocol.ISO8601TimeFormatName
}
}
str = protocol.FormatTime(format, value)
case aws.JSONValue:
if len(value) == 0 {
return "", errValueNotSet
}
escaping := protocol.NoEscape
if tag.Get("location") == "header" {
escaping = protocol.Base64Escape
}
str, err = protocol.EncodeJSONValue(value, escaping)
if err != nil {
return "", fmt.Errorf("unable to encode JSONValue, %v", err)
}
default:
err := fmt.Errorf("unsupported value for param %v (%s)", v.Interface(), v.Type())
return "", err
}
return str, nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/rest/payload.go
================================================
package rest
import "reflect"
// PayloadMember returns the payload field member of i if there is one, or nil.
func PayloadMember(i interface{}) interface{} {
if i == nil {
return nil
}
v := reflect.ValueOf(i).Elem()
if !v.IsValid() {
return nil
}
if field, ok := v.Type().FieldByName("_"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
field, _ := v.Type().FieldByName(payloadName)
if field.Tag.Get("type") != "structure" {
return nil
}
payload := v.FieldByName(payloadName)
if payload.IsValid() || (payload.Kind() == reflect.Ptr && !payload.IsNil()) {
return payload.Interface()
}
}
}
return nil
}
const nopayloadPayloadType = "nopayload"
// PayloadType returns the type of a payload field member of i if there is one,
// or "".
func PayloadType(i interface{}) string {
v := reflect.Indirect(reflect.ValueOf(i))
if !v.IsValid() {
return ""
}
if field, ok := v.Type().FieldByName("_"); ok {
if noPayload := field.Tag.Get(nopayloadPayloadType); noPayload != "" {
return nopayloadPayloadType
}
if payloadName := field.Tag.Get("payload"); payloadName != "" {
if member, ok := v.Type().FieldByName(payloadName); ok {
return member.Tag.Get("type")
}
}
}
return ""
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/rest/unmarshal.go
================================================
package rest
import (
"bytes"
"encoding/base64"
"fmt"
"io"
"io/ioutil"
"net/http"
"reflect"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
awsStrings "github.com/aws/aws-sdk-go/internal/strings"
"github.com/aws/aws-sdk-go/private/protocol"
)
// UnmarshalHandler is a named request handler for unmarshaling rest protocol requests
var UnmarshalHandler = request.NamedHandler{Name: "awssdk.rest.Unmarshal", Fn: Unmarshal}
// UnmarshalMetaHandler is a named request handler for unmarshaling rest protocol request metadata
var UnmarshalMetaHandler = request.NamedHandler{Name: "awssdk.rest.UnmarshalMeta", Fn: UnmarshalMeta}
// Unmarshal unmarshals the REST component of a response in a REST service.
func Unmarshal(r *request.Request) {
if r.DataFilled() {
v := reflect.Indirect(reflect.ValueOf(r.Data))
if err := unmarshalBody(r, v); err != nil {
r.Error = err
}
}
}
// UnmarshalMeta unmarshals the REST metadata of a response in a REST service
func UnmarshalMeta(r *request.Request) {
r.RequestID = r.HTTPResponse.Header.Get("X-Amzn-Requestid")
if r.RequestID == "" {
// Alternative version of request id in the header
r.RequestID = r.HTTPResponse.Header.Get("X-Amz-Request-Id")
}
if r.DataFilled() {
if err := UnmarshalResponse(r.HTTPResponse, r.Data, aws.BoolValue(r.Config.LowerCaseHeaderMaps)); err != nil {
r.Error = err
}
}
}
// UnmarshalResponse attempts to unmarshal the REST response headers to
// the data type passed in. The type must be a pointer. An error is returned
// with any error unmarshaling the response into the target datatype.
func UnmarshalResponse(resp *http.Response, data interface{}, lowerCaseHeaderMaps bool) error {
v := reflect.Indirect(reflect.ValueOf(data))
return unmarshalLocationElements(resp, v, lowerCaseHeaderMaps)
}
func unmarshalBody(r *request.Request, v reflect.Value) error {
if field, ok := v.Type().FieldByName("_"); ok {
if payloadName := field.Tag.Get("payload"); payloadName != "" {
pfield, _ := v.Type().FieldByName(payloadName)
if ptag := pfield.Tag.Get("type"); ptag != "" && ptag != "structure" {
payload := v.FieldByName(payloadName)
if payload.IsValid() {
switch payload.Interface().(type) {
case []byte:
defer r.HTTPResponse.Body.Close()
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to decode REST response", err)
}
payload.Set(reflect.ValueOf(b))
case *string:
defer r.HTTPResponse.Body.Close()
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to decode REST response", err)
}
str := string(b)
payload.Set(reflect.ValueOf(&str))
default:
switch payload.Type().String() {
case "io.ReadCloser":
payload.Set(reflect.ValueOf(r.HTTPResponse.Body))
case "io.ReadSeeker":
b, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
return awserr.New(request.ErrCodeSerialization,
"failed to read response body", err)
}
payload.Set(reflect.ValueOf(ioutil.NopCloser(bytes.NewReader(b))))
default:
io.Copy(ioutil.Discard, r.HTTPResponse.Body)
r.HTTPResponse.Body.Close()
return awserr.New(request.ErrCodeSerialization,
"failed to decode REST response",
fmt.Errorf("unknown payload type %s", payload.Type()))
}
}
}
}
}
}
return nil
}
func unmarshalLocationElements(resp *http.Response, v reflect.Value, lowerCaseHeaderMaps bool) error {
for i := 0; i < v.NumField(); i++ {
m, field := v.Field(i), v.Type().Field(i)
if n := field.Name; n[0:1] == strings.ToLower(n[0:1]) {
continue
}
if m.IsValid() {
name := field.Tag.Get("locationName")
if name == "" {
name = field.Name
}
switch field.Tag.Get("location") {
case "statusCode":
unmarshalStatusCode(m, resp.StatusCode)
case "header":
err := unmarshalHeader(m, resp.Header.Get(name), field.Tag)
if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to decode REST response", err)
}
case "headers":
prefix := field.Tag.Get("locationName")
err := unmarshalHeaderMap(m, resp.Header, prefix, lowerCaseHeaderMaps)
if err != nil {
return awserr.New(request.ErrCodeSerialization, "failed to decode REST response", err)
}
}
}
}
return nil
}
func unmarshalStatusCode(v reflect.Value, statusCode int) {
if !v.IsValid() {
return
}
switch v.Interface().(type) {
case *int64:
s := int64(statusCode)
v.Set(reflect.ValueOf(&s))
}
}
func unmarshalHeaderMap(r reflect.Value, headers http.Header, prefix string, normalize bool) error {
if len(headers) == 0 {
return nil
}
switch r.Interface().(type) {
case map[string]*string: // we only support string map value types
out := map[string]*string{}
for k, v := range headers {
if awsStrings.HasPrefixFold(k, prefix) {
if normalize == true {
k = strings.ToLower(k)
} else {
k = http.CanonicalHeaderKey(k)
}
out[k[len(prefix):]] = &v[0]
}
}
if len(out) != 0 {
r.Set(reflect.ValueOf(out))
}
}
return nil
}
func unmarshalHeader(v reflect.Value, header string, tag reflect.StructTag) error {
switch tag.Get("type") {
case "jsonvalue":
if len(header) == 0 {
return nil
}
case "blob":
if len(header) == 0 {
return nil
}
default:
if !v.IsValid() || (header == "" && v.Elem().Kind() != reflect.String) {
return nil
}
}
switch v.Interface().(type) {
case *string:
if tag.Get("suppressedJSONValue") == "true" && tag.Get("location") == "header" {
b, err := base64.StdEncoding.DecodeString(header)
if err != nil {
return fmt.Errorf("failed to decode JSONValue, %v", err)
}
header = string(b)
}
v.Set(reflect.ValueOf(&header))
case []byte:
b, err := base64.StdEncoding.DecodeString(header)
if err != nil {
return err
}
v.Set(reflect.ValueOf(b))
case *bool:
b, err := strconv.ParseBool(header)
if err != nil {
return err
}
v.Set(reflect.ValueOf(&b))
case *int64:
i, err := strconv.ParseInt(header, 10, 64)
if err != nil {
return err
}
v.Set(reflect.ValueOf(&i))
case *float64:
f, err := strconv.ParseFloat(header, 64)
if err != nil {
return err
}
v.Set(reflect.ValueOf(&f))
case *time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.RFC822TimeFormatName
}
t, err := protocol.ParseTime(format, header)
if err != nil {
return err
}
v.Set(reflect.ValueOf(&t))
case aws.JSONValue:
escaping := protocol.NoEscape
if tag.Get("location") == "header" {
escaping = protocol.Base64Escape
}
m, err := protocol.DecodeJSONValue(header, escaping)
if err != nil {
return err
}
v.Set(reflect.ValueOf(m))
default:
err := fmt.Errorf("Unsupported value for param %v (%s)", v.Interface(), v.Type())
return err
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/restjson.go
================================================
// Package restjson provides RESTful JSON serialization of AWS
// requests and responses.
package restjson
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/input/rest-json.json build_test.go
//go:generate go run -tags codegen ../../../private/model/cli/gen-protocol-tests ../../../models/protocol_tests/output/rest-json.json unmarshal_test.go
import (
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
"github.com/aws/aws-sdk-go/private/protocol/rest"
)
// BuildHandler is a named request handler for building restjson protocol
// requests
var BuildHandler = request.NamedHandler{
Name: "awssdk.restjson.Build",
Fn: Build,
}
// UnmarshalHandler is a named request handler for unmarshaling restjson
// protocol requests
var UnmarshalHandler = request.NamedHandler{
Name: "awssdk.restjson.Unmarshal",
Fn: Unmarshal,
}
// UnmarshalMetaHandler is a named request handler for unmarshaling restjson
// protocol request metadata
var UnmarshalMetaHandler = request.NamedHandler{
Name: "awssdk.restjson.UnmarshalMeta",
Fn: UnmarshalMeta,
}
// Build builds a request for the REST JSON protocol.
func Build(r *request.Request) {
rest.Build(r)
if t := rest.PayloadType(r.Params); t == "structure" || t == "" {
if v := r.HTTPRequest.Header.Get("Content-Type"); len(v) == 0 {
r.HTTPRequest.Header.Set("Content-Type", "application/json")
}
jsonrpc.Build(r)
}
}
// Unmarshal unmarshals a response body for the REST JSON protocol.
func Unmarshal(r *request.Request) {
if t := rest.PayloadType(r.Data); t == "structure" || t == "" {
jsonrpc.Unmarshal(r)
} else {
rest.Unmarshal(r)
}
}
// UnmarshalMeta unmarshals response headers for the REST JSON protocol.
func UnmarshalMeta(r *request.Request) {
rest.UnmarshalMeta(r)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/restjson/unmarshal_error.go
================================================
package restjson
import (
"bytes"
"io"
"io/ioutil"
"net/http"
"strings"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/json/jsonutil"
"github.com/aws/aws-sdk-go/private/protocol/rest"
)
const (
errorTypeHeader = "X-Amzn-Errortype"
errorMessageHeader = "X-Amzn-Errormessage"
)
// UnmarshalTypedError provides unmarshaling errors API response errors
// for both typed and untyped errors.
type UnmarshalTypedError struct {
exceptions map[string]func(protocol.ResponseMetadata) error
}
// NewUnmarshalTypedError returns an UnmarshalTypedError initialized for the
// set of exception names to the error unmarshalers
func NewUnmarshalTypedError(exceptions map[string]func(protocol.ResponseMetadata) error) *UnmarshalTypedError {
return &UnmarshalTypedError{
exceptions: exceptions,
}
}
// UnmarshalError attempts to unmarshal the HTTP response error as a known
// error type. If unable to unmarshal the error type, the generic SDK error
// type will be used.
func (u *UnmarshalTypedError) UnmarshalError(
resp *http.Response,
respMeta protocol.ResponseMetadata,
) (error, error) {
code := resp.Header.Get(errorTypeHeader)
msg := resp.Header.Get(errorMessageHeader)
body := resp.Body
if len(code) == 0 {
// If unable to get code from HTTP headers have to parse JSON message
// to determine what kind of exception this will be.
var buf bytes.Buffer
var jsonErr jsonErrorResponse
teeReader := io.TeeReader(resp.Body, &buf)
err := jsonutil.UnmarshalJSONError(&jsonErr, teeReader)
if err != nil {
return nil, err
}
body = ioutil.NopCloser(&buf)
code = jsonErr.Code
msg = jsonErr.Message
}
// If code has colon separators remove them so can compare against modeled
// exception names.
code = strings.SplitN(code, ":", 2)[0]
if fn, ok := u.exceptions[code]; ok {
// If exception code is know, use associated constructor to get a value
// for the exception that the JSON body can be unmarshaled into.
v := fn(respMeta)
if err := jsonutil.UnmarshalJSONCaseInsensitive(v, body); err != nil {
return nil, err
}
if err := rest.UnmarshalResponse(resp, v, true); err != nil {
return nil, err
}
return v, nil
}
// fallback to unmodeled generic exceptions
return awserr.NewRequestFailure(
awserr.New(code, msg, nil),
respMeta.StatusCode,
respMeta.RequestID,
), nil
}
// UnmarshalErrorHandler is a named request handler for unmarshaling restjson
// protocol request errors
var UnmarshalErrorHandler = request.NamedHandler{
Name: "awssdk.restjson.UnmarshalError",
Fn: UnmarshalError,
}
// UnmarshalError unmarshals a response error for the REST JSON protocol.
func UnmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
var jsonErr jsonErrorResponse
err := jsonutil.UnmarshalJSONError(&jsonErr, r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to unmarshal response error", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
code := r.HTTPResponse.Header.Get(errorTypeHeader)
if code == "" {
code = jsonErr.Code
}
msg := r.HTTPResponse.Header.Get(errorMessageHeader)
if msg == "" {
msg = jsonErr.Message
}
code = strings.SplitN(code, ":", 2)[0]
r.Error = awserr.NewRequestFailure(
awserr.New(code, jsonErr.Message, nil),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
type jsonErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/timestamp.go
================================================
package protocol
import (
"bytes"
"fmt"
"math"
"strconv"
"time"
"github.com/aws/aws-sdk-go/internal/sdkmath"
)
// Names of time formats supported by the SDK
const (
RFC822TimeFormatName = "rfc822"
ISO8601TimeFormatName = "iso8601"
UnixTimeFormatName = "unixTimestamp"
)
// Time formats supported by the SDK
// Output time is intended to not contain decimals
const (
// RFC 7231#section-7.1.1.1 timetamp format. e.g Tue, 29 Apr 2014 18:30:38 GMT
RFC822TimeFormat = "Mon, 2 Jan 2006 15:04:05 GMT"
rfc822TimeFormatSingleDigitDay = "Mon, _2 Jan 2006 15:04:05 GMT"
rfc822TimeFormatSingleDigitDayTwoDigitYear = "Mon, _2 Jan 06 15:04:05 GMT"
// This format is used for output time without seconds precision
RFC822OutputTimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
// RFC3339 a subset of the ISO8601 timestamp format. e.g 2014-04-29T18:30:38Z
ISO8601TimeFormat = "2006-01-02T15:04:05.999999999Z"
iso8601TimeFormatNoZ = "2006-01-02T15:04:05.999999999"
// This format is used for output time with fractional second precision up to milliseconds
ISO8601OutputTimeFormat = "2006-01-02T15:04:05.999999999Z"
)
// IsKnownTimestampFormat returns if the timestamp format name
// is know to the SDK's protocols.
func IsKnownTimestampFormat(name string) bool {
switch name {
case RFC822TimeFormatName:
fallthrough
case ISO8601TimeFormatName:
fallthrough
case UnixTimeFormatName:
return true
default:
return false
}
}
// FormatTime returns a string value of the time.
func FormatTime(name string, t time.Time) string {
t = t.UTC().Truncate(time.Millisecond)
switch name {
case RFC822TimeFormatName:
return t.Format(RFC822OutputTimeFormat)
case ISO8601TimeFormatName:
return t.Format(ISO8601OutputTimeFormat)
case UnixTimeFormatName:
ms := t.UnixNano() / int64(time.Millisecond)
return strconv.FormatFloat(float64(ms)/1e3, 'f', -1, 64)
default:
panic("unknown timestamp format name, " + name)
}
}
// ParseTime attempts to parse the time given the format. Returns
// the time if it was able to be parsed, and fails otherwise.
func ParseTime(formatName, value string) (time.Time, error) {
switch formatName {
case RFC822TimeFormatName: // Smithy HTTPDate format
return tryParse(value,
RFC822TimeFormat,
rfc822TimeFormatSingleDigitDay,
rfc822TimeFormatSingleDigitDayTwoDigitYear,
time.RFC850,
time.ANSIC,
)
case ISO8601TimeFormatName: // Smithy DateTime format
return tryParse(value,
ISO8601TimeFormat,
iso8601TimeFormatNoZ,
time.RFC3339Nano,
time.RFC3339,
)
case UnixTimeFormatName:
v, err := strconv.ParseFloat(value, 64)
_, dec := math.Modf(v)
dec = sdkmath.Round(dec*1e3) / 1e3 //Rounds 0.1229999 to 0.123
if err != nil {
return time.Time{}, err
}
return time.Unix(int64(v), int64(dec*(1e9))), nil
default:
panic("unknown timestamp format name, " + formatName)
}
}
func tryParse(v string, formats ...string) (time.Time, error) {
var errs parseErrors
for _, f := range formats {
t, err := time.Parse(f, v)
if err != nil {
errs = append(errs, parseError{
Format: f,
Err: err,
})
continue
}
return t, nil
}
return time.Time{}, fmt.Errorf("unable to parse time string, %v", errs)
}
type parseErrors []parseError
func (es parseErrors) Error() string {
var s bytes.Buffer
for _, e := range es {
fmt.Fprintf(&s, "\n * %q: %v", e.Format, e.Err)
}
return "parse errors:" + s.String()
}
type parseError struct {
Format string
Err error
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal.go
================================================
package protocol
import (
"io"
"io/ioutil"
"github.com/aws/aws-sdk-go/aws/request"
)
// UnmarshalDiscardBodyHandler is a named request handler to empty and close a response's body
var UnmarshalDiscardBodyHandler = request.NamedHandler{Name: "awssdk.shared.UnmarshalDiscardBody", Fn: UnmarshalDiscardBody}
// UnmarshalDiscardBody is a request handler to empty a response's body and closing it.
func UnmarshalDiscardBody(r *request.Request) {
if r.HTTPResponse == nil || r.HTTPResponse.Body == nil {
return
}
io.Copy(ioutil.Discard, r.HTTPResponse.Body)
r.HTTPResponse.Body.Close()
}
// ResponseMetadata provides the SDK response metadata attributes.
type ResponseMetadata struct {
StatusCode int
RequestID string
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/unmarshal_error.go
================================================
package protocol
import (
"net/http"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/request"
)
// UnmarshalErrorHandler provides unmarshaling errors API response errors for
// both typed and untyped errors.
type UnmarshalErrorHandler struct {
unmarshaler ErrorUnmarshaler
}
// ErrorUnmarshaler is an abstract interface for concrete implementations to
// unmarshal protocol specific response errors.
type ErrorUnmarshaler interface {
UnmarshalError(*http.Response, ResponseMetadata) (error, error)
}
// NewUnmarshalErrorHandler returns an UnmarshalErrorHandler
// initialized for the set of exception names to the error unmarshalers
func NewUnmarshalErrorHandler(unmarshaler ErrorUnmarshaler) *UnmarshalErrorHandler {
return &UnmarshalErrorHandler{
unmarshaler: unmarshaler,
}
}
// UnmarshalErrorHandlerName is the name of the named handler.
const UnmarshalErrorHandlerName = "awssdk.protocol.UnmarshalError"
// NamedHandler returns a NamedHandler for the unmarshaler using the set of
// errors the unmarshaler was initialized for.
func (u *UnmarshalErrorHandler) NamedHandler() request.NamedHandler {
return request.NamedHandler{
Name: UnmarshalErrorHandlerName,
Fn: u.UnmarshalError,
}
}
// UnmarshalError will attempt to unmarshal the API response's error message
// into either a generic SDK error type, or a typed error corresponding to the
// errors exception name.
func (u *UnmarshalErrorHandler) UnmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
respMeta := ResponseMetadata{
StatusCode: r.HTTPResponse.StatusCode,
RequestID: r.RequestID,
}
v, err := u.unmarshaler.UnmarshalError(r.HTTPResponse, respMeta)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to unmarshal response error", err),
respMeta.StatusCode,
respMeta.RequestID,
)
return
}
r.Error = v
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/build.go
================================================
// Package xmlutil provides XML serialization of AWS requests and responses.
package xmlutil
import (
"encoding/base64"
"encoding/xml"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/private/protocol"
)
// BuildXML will serialize params into an xml.Encoder. Error will be returned
// if the serialization of any of the params or nested values fails.
func BuildXML(params interface{}, e *xml.Encoder) error {
return buildXML(params, e, false)
}
func buildXML(params interface{}, e *xml.Encoder, sorted bool) error {
b := xmlBuilder{encoder: e, namespaces: map[string]string{}}
root := NewXMLElement(xml.Name{})
if err := b.buildValue(reflect.ValueOf(params), root, ""); err != nil {
return err
}
for _, c := range root.Children {
for _, v := range c {
return StructToXML(e, v, sorted)
}
}
return nil
}
// Returns the reflection element of a value, if it is a pointer.
func elemOf(value reflect.Value) reflect.Value {
for value.Kind() == reflect.Ptr {
value = value.Elem()
}
return value
}
// A xmlBuilder serializes values from Go code to XML
type xmlBuilder struct {
encoder *xml.Encoder
namespaces map[string]string
}
// buildValue generic XMLNode builder for any type. Will build value for their specific type
// struct, list, map, scalar.
//
// Also takes a "type" tag value to set what type a value should be converted to XMLNode as. If
// type is not provided reflect will be used to determine the value's type.
func (b *xmlBuilder) buildValue(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
value = elemOf(value)
if !value.IsValid() { // no need to handle zero values
return nil
} else if tag.Get("location") != "" { // don't handle non-body location values
return nil
}
xml := tag.Get("xml")
if len(xml) != 0 {
name := strings.SplitAfterN(xml, ",", 2)[0]
if name == "-" {
return nil
}
}
t := tag.Get("type")
if t == "" {
switch value.Kind() {
case reflect.Struct:
t = "structure"
case reflect.Slice:
t = "list"
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
if field, ok := value.Type().FieldByName("_"); ok {
tag = tag + reflect.StructTag(" ") + field.Tag
}
return b.buildStruct(value, current, tag)
case "list":
return b.buildList(value, current, tag)
case "map":
return b.buildMap(value, current, tag)
default:
return b.buildScalar(value, current, tag)
}
}
// buildStruct adds a struct and its fields to the current XMLNode. All fields and any nested
// types are converted to XMLNodes also.
func (b *xmlBuilder) buildStruct(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if !value.IsValid() {
return nil
}
// unwrap payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := value.Type().FieldByName(payload)
tag = field.Tag
value = elemOf(value.FieldByName(payload))
if !value.IsValid() {
return nil
}
}
child := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
// there is an xmlNamespace associated with this struct
if prefix, uri := tag.Get("xmlPrefix"), tag.Get("xmlURI"); uri != "" {
ns := xml.Attr{
Name: xml.Name{Local: "xmlns"},
Value: uri,
}
if prefix != "" {
b.namespaces[prefix] = uri // register the namespace
ns.Name.Local = "xmlns:" + prefix
}
child.Attr = append(child.Attr, ns)
}
var payloadFields, nonPayloadFields int
t := value.Type()
for i := 0; i < value.NumField(); i++ {
member := elemOf(value.Field(i))
field := t.Field(i)
if field.PkgPath != "" {
continue // ignore unexported fields
}
if field.Tag.Get("ignore") != "" {
continue
}
mTag := field.Tag
if mTag.Get("location") != "" { // skip non-body members
nonPayloadFields++
continue
}
payloadFields++
if protocol.CanSetIdempotencyToken(value.Field(i), field) {
token := protocol.GetIdempotencyToken()
member = reflect.ValueOf(token)
}
memberName := mTag.Get("locationName")
if memberName == "" {
memberName = field.Name
mTag = reflect.StructTag(string(mTag) + ` locationName:"` + memberName + `"`)
}
if err := b.buildValue(member, child, mTag); err != nil {
return err
}
}
// Only case where the child shape is not added is if the shape only contains
// non-payload fields, e.g headers/query.
if !(payloadFields == 0 && nonPayloadFields > 0) {
current.AddChild(child)
}
return nil
}
// buildList adds the value's list items to the current XMLNode as children nodes. All
// nested values in the list are converted to XMLNodes also.
func (b *xmlBuilder) buildList(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if value.IsNil() { // don't build omitted lists
return nil
}
// check for unflattened list member
flattened := tag.Get("flattened") != ""
xname := xml.Name{Local: tag.Get("locationName")}
if flattened {
for i := 0; i < value.Len(); i++ {
child := NewXMLElement(xname)
current.AddChild(child)
if err := b.buildValue(value.Index(i), child, ""); err != nil {
return err
}
}
} else {
list := NewXMLElement(xname)
current.AddChild(list)
for i := 0; i < value.Len(); i++ {
iname := tag.Get("locationNameList")
if iname == "" {
iname = "member"
}
child := NewXMLElement(xml.Name{Local: iname})
list.AddChild(child)
if err := b.buildValue(value.Index(i), child, ""); err != nil {
return err
}
}
}
return nil
}
// buildMap adds the value's key/value pairs to the current XMLNode as children nodes. All
// nested values in the map are converted to XMLNodes also.
//
// Error will be returned if it is unable to build the map's values into XMLNodes
func (b *xmlBuilder) buildMap(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
if value.IsNil() { // don't build omitted maps
return nil
}
maproot := NewXMLElement(xml.Name{Local: tag.Get("locationName")})
current.AddChild(maproot)
current = maproot
kname, vname := "key", "value"
if n := tag.Get("locationNameKey"); n != "" {
kname = n
}
if n := tag.Get("locationNameValue"); n != "" {
vname = n
}
// sorting is not required for compliance, but it makes testing easier
keys := make([]string, value.Len())
for i, k := range value.MapKeys() {
keys[i] = k.String()
}
sort.Strings(keys)
for _, k := range keys {
v := value.MapIndex(reflect.ValueOf(k))
mapcur := current
if tag.Get("flattened") == "" { // add "entry" tag to non-flat maps
child := NewXMLElement(xml.Name{Local: "entry"})
mapcur.AddChild(child)
mapcur = child
}
kchild := NewXMLElement(xml.Name{Local: kname})
kchild.Text = k
vchild := NewXMLElement(xml.Name{Local: vname})
mapcur.AddChild(kchild)
mapcur.AddChild(vchild)
if err := b.buildValue(v, vchild, ""); err != nil {
return err
}
}
return nil
}
// buildScalar will convert the value into a string and append it as a attribute or child
// of the current XMLNode.
//
// The value will be added as an attribute if tag contains a "xmlAttribute" attribute value.
//
// Error will be returned if the value type is unsupported.
func (b *xmlBuilder) buildScalar(value reflect.Value, current *XMLNode, tag reflect.StructTag) error {
var str string
switch converted := value.Interface().(type) {
case string:
str = converted
case []byte:
if !value.IsNil() {
str = base64.StdEncoding.EncodeToString(converted)
}
case bool:
str = strconv.FormatBool(converted)
case int64:
str = strconv.FormatInt(converted, 10)
case int:
str = strconv.Itoa(converted)
case float64:
str = strconv.FormatFloat(converted, 'f', -1, 64)
case float32:
str = strconv.FormatFloat(float64(converted), 'f', -1, 32)
case time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
str = protocol.FormatTime(format, converted)
default:
return fmt.Errorf("unsupported value for param %s: %v (%s)",
tag.Get("locationName"), value.Interface(), value.Type().Name())
}
xname := xml.Name{Local: tag.Get("locationName")}
if tag.Get("xmlAttribute") != "" { // put into current node's attribute list
attr := xml.Attr{Name: xname, Value: str}
current.Attr = append(current.Attr, attr)
} else if len(xname.Local) == 0 {
current.Text = str
} else { // regular text node
current.AddChild(&XMLNode{Name: xname, Text: str})
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/sort.go
================================================
package xmlutil
import (
"encoding/xml"
"strings"
)
type xmlAttrSlice []xml.Attr
func (x xmlAttrSlice) Len() int {
return len(x)
}
func (x xmlAttrSlice) Less(i, j int) bool {
spaceI, spaceJ := x[i].Name.Space, x[j].Name.Space
localI, localJ := x[i].Name.Local, x[j].Name.Local
valueI, valueJ := x[i].Value, x[j].Value
spaceCmp := strings.Compare(spaceI, spaceJ)
localCmp := strings.Compare(localI, localJ)
valueCmp := strings.Compare(valueI, valueJ)
if spaceCmp == -1 || (spaceCmp == 0 && (localCmp == -1 || (localCmp == 0 && valueCmp == -1))) {
return true
}
return false
}
func (x xmlAttrSlice) Swap(i, j int) {
x[i], x[j] = x[j], x[i]
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/unmarshal.go
================================================
package xmlutil
import (
"bytes"
"encoding/base64"
"encoding/xml"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/private/protocol"
)
// UnmarshalXMLError unmarshals the XML error from the stream into the value
// type specified. The value must be a pointer. If the message fails to
// unmarshal, the message content will be included in the returned error as a
// awserr.UnmarshalError.
func UnmarshalXMLError(v interface{}, stream io.Reader) error {
var errBuf bytes.Buffer
body := io.TeeReader(stream, &errBuf)
err := xml.NewDecoder(body).Decode(v)
if err != nil && err != io.EOF {
return awserr.NewUnmarshalError(err,
"failed to unmarshal error message", errBuf.Bytes())
}
return nil
}
// UnmarshalXML deserializes an xml.Decoder into the container v. V
// needs to match the shape of the XML expected to be decoded.
// If the shape doesn't match unmarshaling will fail.
func UnmarshalXML(v interface{}, d *xml.Decoder, wrapper string) error {
n, err := XMLToStruct(d, nil)
if err != nil {
return err
}
if n.Children != nil {
for _, root := range n.Children {
for _, c := range root {
if wrappedChild, ok := c.Children[wrapper]; ok {
c = wrappedChild[0] // pull out wrapped element
}
err = parse(reflect.ValueOf(v), c, "")
if err != nil {
if err == io.EOF {
return nil
}
return err
}
}
}
return nil
}
return nil
}
// parse deserializes any value from the XMLNode. The type tag is used to infer the type, or reflect
// will be used to determine the type from r.
func parse(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
xml := tag.Get("xml")
if len(xml) != 0 {
name := strings.SplitAfterN(xml, ",", 2)[0]
if name == "-" {
return nil
}
}
rtype := r.Type()
if rtype.Kind() == reflect.Ptr {
rtype = rtype.Elem() // check kind of actual element type
}
t := tag.Get("type")
if t == "" {
switch rtype.Kind() {
case reflect.Struct:
// also it can't be a time object
if _, ok := r.Interface().(*time.Time); !ok {
t = "structure"
}
case reflect.Slice:
// also it can't be a byte slice
if _, ok := r.Interface().([]byte); !ok {
t = "list"
}
case reflect.Map:
t = "map"
}
}
switch t {
case "structure":
if field, ok := rtype.FieldByName("_"); ok {
tag = field.Tag
}
return parseStruct(r, node, tag)
case "list":
return parseList(r, node, tag)
case "map":
return parseMap(r, node, tag)
default:
return parseScalar(r, node, tag)
}
}
// parseStruct deserializes a structure and its fields from an XMLNode. Any nested
// types in the structure will also be deserialized.
func parseStruct(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
t := r.Type()
if r.Kind() == reflect.Ptr {
if r.IsNil() { // create the structure if it's nil
s := reflect.New(r.Type().Elem())
r.Set(s)
r = s
}
r = r.Elem()
t = t.Elem()
}
// unwrap any payloads
if payload := tag.Get("payload"); payload != "" {
field, _ := t.FieldByName(payload)
return parseStruct(r.FieldByName(payload), node, field.Tag)
}
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if c := field.Name[0:1]; strings.ToLower(c) == c {
continue // ignore unexported fields
}
// figure out what this field is called
name := field.Name
if field.Tag.Get("flattened") != "" && field.Tag.Get("locationNameList") != "" {
name = field.Tag.Get("locationNameList")
} else if locName := field.Tag.Get("locationName"); locName != "" {
name = locName
}
// try to find the field by name in elements
elems := node.Children[name]
if elems == nil { // try to find the field in attributes
if val, ok := node.findElem(name); ok {
elems = []*XMLNode{{Text: val}}
}
}
member := r.FieldByName(field.Name)
for _, elem := range elems {
err := parse(member, elem, field.Tag)
if err != nil {
return err
}
}
}
return nil
}
// parseList deserializes a list of values from an XML node. Each list entry
// will also be deserialized.
func parseList(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
t := r.Type()
if tag.Get("flattened") == "" { // look at all item entries
mname := "member"
if name := tag.Get("locationNameList"); name != "" {
mname = name
}
if Children, ok := node.Children[mname]; ok {
if r.IsNil() {
r.Set(reflect.MakeSlice(t, len(Children), len(Children)))
}
for i, c := range Children {
err := parse(r.Index(i), c, "")
if err != nil {
return err
}
}
}
} else { // flattened list means this is a single element
if r.IsNil() {
r.Set(reflect.MakeSlice(t, 0, 0))
}
childR := reflect.Zero(t.Elem())
r.Set(reflect.Append(r, childR))
err := parse(r.Index(r.Len()-1), node, "")
if err != nil {
return err
}
}
return nil
}
// parseMap deserializes a map from an XMLNode. The direct children of the XMLNode
// will also be deserialized as map entries.
func parseMap(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
if r.IsNil() {
r.Set(reflect.MakeMap(r.Type()))
}
if tag.Get("flattened") == "" { // look at all child entries
for _, entry := range node.Children["entry"] {
parseMapEntry(r, entry, tag)
}
} else { // this element is itself an entry
parseMapEntry(r, node, tag)
}
return nil
}
// parseMapEntry deserializes a map entry from a XML node.
func parseMapEntry(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
kname, vname := "key", "value"
if n := tag.Get("locationNameKey"); n != "" {
kname = n
}
if n := tag.Get("locationNameValue"); n != "" {
vname = n
}
keys, ok := node.Children[kname]
values := node.Children[vname]
if ok {
for i, key := range keys {
keyR := reflect.ValueOf(key.Text)
value := values[i]
valueR := reflect.New(r.Type().Elem()).Elem()
parse(valueR, value, "")
r.SetMapIndex(keyR, valueR)
}
}
return nil
}
// parseScaller deserializes an XMLNode value into a concrete type based on the
// interface type of r.
//
// Error is returned if the deserialization fails due to invalid type conversion,
// or unsupported interface type.
func parseScalar(r reflect.Value, node *XMLNode, tag reflect.StructTag) error {
switch r.Interface().(type) {
case *string:
r.Set(reflect.ValueOf(&node.Text))
return nil
case []byte:
b, err := base64.StdEncoding.DecodeString(node.Text)
if err != nil {
return err
}
r.Set(reflect.ValueOf(b))
case *bool:
v, err := strconv.ParseBool(node.Text)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *int64:
v, err := strconv.ParseInt(node.Text, 10, 64)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *float64:
v, err := strconv.ParseFloat(node.Text, 64)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&v))
case *time.Time:
format := tag.Get("timestampFormat")
if len(format) == 0 {
format = protocol.ISO8601TimeFormatName
}
t, err := protocol.ParseTime(format, node.Text)
if err != nil {
return err
}
r.Set(reflect.ValueOf(&t))
default:
return fmt.Errorf("unsupported value: %v (%s)", r.Interface(), r.Type())
}
return nil
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil/xml_to_struct.go
================================================
package xmlutil
import (
"encoding/xml"
"fmt"
"io"
"sort"
)
// A XMLNode contains the values to be encoded or decoded.
type XMLNode struct {
Name xml.Name `json:",omitempty"`
Children map[string][]*XMLNode `json:",omitempty"`
Text string `json:",omitempty"`
Attr []xml.Attr `json:",omitempty"`
namespaces map[string]string
parent *XMLNode
}
// textEncoder is a string type alias that implemnts the TextMarshaler interface.
// This alias type is used to ensure that the line feed (\n) (U+000A) is escaped.
type textEncoder string
func (t textEncoder) MarshalText() ([]byte, error) {
return []byte(t), nil
}
// NewXMLElement returns a pointer to a new XMLNode initialized to default values.
func NewXMLElement(name xml.Name) *XMLNode {
return &XMLNode{
Name: name,
Children: map[string][]*XMLNode{},
Attr: []xml.Attr{},
}
}
// AddChild adds child to the XMLNode.
func (n *XMLNode) AddChild(child *XMLNode) {
child.parent = n
if _, ok := n.Children[child.Name.Local]; !ok {
n.Children[child.Name.Local] = []*XMLNode{}
}
n.Children[child.Name.Local] = append(n.Children[child.Name.Local], child)
}
// XMLToStruct converts a xml.Decoder stream to XMLNode with nested values.
func XMLToStruct(d *xml.Decoder, s *xml.StartElement) (*XMLNode, error) {
out := &XMLNode{}
for {
tok, err := d.Token()
if err != nil {
if err == io.EOF {
break
} else {
return out, err
}
}
if tok == nil {
break
}
switch typed := tok.(type) {
case xml.CharData:
out.Text = string(typed.Copy())
case xml.StartElement:
el := typed.Copy()
out.Attr = el.Attr
if out.Children == nil {
out.Children = map[string][]*XMLNode{}
}
name := typed.Name.Local
slice := out.Children[name]
if slice == nil {
slice = []*XMLNode{}
}
node, e := XMLToStruct(d, &el)
out.findNamespaces()
if e != nil {
return out, e
}
node.Name = typed.Name
node.findNamespaces()
tempOut := *out
// Save into a temp variable, simply because out gets squashed during
// loop iterations
node.parent = &tempOut
slice = append(slice, node)
out.Children[name] = slice
case xml.EndElement:
if s != nil && s.Name.Local == typed.Name.Local { // matching end token
return out, nil
}
out = &XMLNode{}
}
}
return out, nil
}
func (n *XMLNode) findNamespaces() {
ns := map[string]string{}
for _, a := range n.Attr {
if a.Name.Space == "xmlns" {
ns[a.Value] = a.Name.Local
}
}
n.namespaces = ns
}
func (n *XMLNode) findElem(name string) (string, bool) {
for node := n; node != nil; node = node.parent {
for _, a := range node.Attr {
namespace := a.Name.Space
if v, ok := node.namespaces[namespace]; ok {
namespace = v
}
if name == fmt.Sprintf("%s:%s", namespace, a.Name.Local) {
return a.Value, true
}
}
}
return "", false
}
// StructToXML writes an XMLNode to a xml.Encoder as tokens.
func StructToXML(e *xml.Encoder, node *XMLNode, sorted bool) error {
// Sort Attributes
attrs := node.Attr
if sorted {
sortedAttrs := make([]xml.Attr, len(attrs))
for _, k := range node.Attr {
sortedAttrs = append(sortedAttrs, k)
}
sort.Sort(xmlAttrSlice(sortedAttrs))
attrs = sortedAttrs
}
startElement := xml.StartElement{Name: node.Name, Attr: attrs}
if node.Text != "" {
e.EncodeElement(textEncoder(node.Text), startElement)
return e.Flush()
}
e.EncodeToken(startElement)
if sorted {
sortedNames := []string{}
for k := range node.Children {
sortedNames = append(sortedNames, k)
}
sort.Strings(sortedNames)
for _, k := range sortedNames {
for _, v := range node.Children[k] {
StructToXML(e, v, sorted)
}
}
} else {
for _, c := range node.Children {
for _, v := range c {
StructToXML(e, v, sorted)
}
}
}
e.EncodeToken(startElement.End())
return e.Flush()
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/kms/api.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package kms
import (
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
)
const opCancelKeyDeletion = "CancelKeyDeletion"
// CancelKeyDeletionRequest generates a "aws/request.Request" representing the
// client's request for the CancelKeyDeletion operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See CancelKeyDeletion for more information on using the CancelKeyDeletion
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the CancelKeyDeletionRequest method.
// req, resp := client.CancelKeyDeletionRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CancelKeyDeletion
func (c *KMS) CancelKeyDeletionRequest(input *CancelKeyDeletionInput) (req *request.Request, output *CancelKeyDeletionOutput) {
op := &request.Operation{
Name: opCancelKeyDeletion,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &CancelKeyDeletionInput{}
}
output = &CancelKeyDeletionOutput{}
req = c.newRequest(op, input, output)
return
}
// CancelKeyDeletion API operation for AWS Key Management Service.
//
// Cancels the deletion of a KMS key. When this operation succeeds, the key
// state of the KMS key is Disabled. To enable the KMS key, use EnableKey.
//
// For more information about scheduling and canceling deletion of a KMS key,
// see Deleting KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:CancelKeyDeletion (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: ScheduleKeyDeletion
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation CancelKeyDeletion for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CancelKeyDeletion
func (c *KMS) CancelKeyDeletion(input *CancelKeyDeletionInput) (*CancelKeyDeletionOutput, error) {
req, out := c.CancelKeyDeletionRequest(input)
return out, req.Send()
}
// CancelKeyDeletionWithContext is the same as CancelKeyDeletion with the addition of
// the ability to pass a context and additional request options.
//
// See CancelKeyDeletion for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) CancelKeyDeletionWithContext(ctx aws.Context, input *CancelKeyDeletionInput, opts ...request.Option) (*CancelKeyDeletionOutput, error) {
req, out := c.CancelKeyDeletionRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opConnectCustomKeyStore = "ConnectCustomKeyStore"
// ConnectCustomKeyStoreRequest generates a "aws/request.Request" representing the
// client's request for the ConnectCustomKeyStore operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ConnectCustomKeyStore for more information on using the ConnectCustomKeyStore
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ConnectCustomKeyStoreRequest method.
// req, resp := client.ConnectCustomKeyStoreRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ConnectCustomKeyStore
func (c *KMS) ConnectCustomKeyStoreRequest(input *ConnectCustomKeyStoreInput) (req *request.Request, output *ConnectCustomKeyStoreOutput) {
op := &request.Operation{
Name: opConnectCustomKeyStore,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ConnectCustomKeyStoreInput{}
}
output = &ConnectCustomKeyStoreOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// ConnectCustomKeyStore API operation for AWS Key Management Service.
//
// Connects or reconnects a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// to its associated CloudHSM cluster.
//
// The custom key store must be connected before you can create KMS keys in
// the key store or use the KMS keys it contains. You can disconnect and reconnect
// a custom key store at any time.
//
// To connect a custom key store, its associated CloudHSM cluster must have
// at least one active HSM. To get the number of active HSMs in a cluster, use
// the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation. To add HSMs to the cluster, use the CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. Also, the kmsuser crypto user (https://docs.aws.amazon.com/kms/latest/developerguide/key-store-concepts.html#concept-kmsuser)
// (CU) must not be logged into the cluster. This prevents KMS from using this
// account to log in.
//
// The connection process can take an extended amount of time to complete; up
// to 20 minutes. This operation starts the connection process, but it does
// not wait for it to complete. When it succeeds, this operation quickly returns
// an HTTP 200 response and a JSON object with no properties. However, this
// response does not indicate that the custom key store is connected. To get
// the connection state of the custom key store, use the DescribeCustomKeyStores
// operation.
//
// During the connection process, KMS finds the CloudHSM cluster that is associated
// with the custom key store, creates the connection infrastructure, connects
// to the cluster, logs into the CloudHSM client as the kmsuser CU, and rotates
// its password.
//
// The ConnectCustomKeyStore operation might fail for various reasons. To find
// the reason, use the DescribeCustomKeyStores operation and see the ConnectionErrorCode
// in the response. For help interpreting the ConnectionErrorCode, see CustomKeyStoresListEntry.
//
// To fix the failure, use the DisconnectCustomKeyStore operation to disconnect
// the custom key store, correct the error, use the UpdateCustomKeyStore operation
// if necessary, and then use ConnectCustomKeyStore again.
//
// If you are having trouble connecting or disconnecting a custom key store,
// see Troubleshooting a Custom Key Store (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:ConnectCustomKeyStore (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations
//
// * CreateCustomKeyStore
//
// * DeleteCustomKeyStore
//
// * DescribeCustomKeyStores
//
// * DisconnectCustomKeyStore
//
// * UpdateCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ConnectCustomKeyStore for usage and error information.
//
// Returned Error Types:
// * CloudHsmClusterNotActiveException
// The request was rejected because the CloudHSM cluster that is associated
// with the custom key store is not active. Initialize and activate the cluster
// and try the command again. For detailed instructions, see Getting Started
// (https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html)
// in the CloudHSM User Guide.
//
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * CloudHsmClusterInvalidConfigurationException
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ConnectCustomKeyStore
func (c *KMS) ConnectCustomKeyStore(input *ConnectCustomKeyStoreInput) (*ConnectCustomKeyStoreOutput, error) {
req, out := c.ConnectCustomKeyStoreRequest(input)
return out, req.Send()
}
// ConnectCustomKeyStoreWithContext is the same as ConnectCustomKeyStore with the addition of
// the ability to pass a context and additional request options.
//
// See ConnectCustomKeyStore for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ConnectCustomKeyStoreWithContext(ctx aws.Context, input *ConnectCustomKeyStoreInput, opts ...request.Option) (*ConnectCustomKeyStoreOutput, error) {
req, out := c.ConnectCustomKeyStoreRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opCreateAlias = "CreateAlias"
// CreateAliasRequest generates a "aws/request.Request" representing the
// client's request for the CreateAlias operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See CreateAlias for more information on using the CreateAlias
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the CreateAliasRequest method.
// req, resp := client.CreateAliasRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateAlias
func (c *KMS) CreateAliasRequest(input *CreateAliasInput) (req *request.Request, output *CreateAliasOutput) {
op := &request.Operation{
Name: opCreateAlias,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &CreateAliasInput{}
}
output = &CreateAliasOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// CreateAlias API operation for AWS Key Management Service.
//
// Creates a friendly name for a KMS key.
//
// Adding, deleting, or updating an alias can allow or deny permission to the
// KMS key. For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// You can use an alias to identify a KMS key in the KMS console, in the DescribeKey
// operation and in cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations),
// such as Encrypt and GenerateDataKey. You can also change the KMS key that's
// associated with the alias (UpdateAlias) or delete the alias (DeleteAlias)
// at any time. These operations don't affect the underlying KMS key.
//
// You can associate the alias with any customer managed key in the same Amazon
// Web Services Region. Each alias is associated with only one KMS key at a
// time, but a KMS key can have multiple aliases. A valid KMS key is required.
// You can't create an alias without a KMS key.
//
// The alias must be unique in the account and Region, but you can have aliases
// with the same name in different Regions. For detailed information about aliases,
// see Using aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html)
// in the Key Management Service Developer Guide.
//
// This operation does not return a response. To get the alias that you created,
// use the ListAliases operation.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on an alias in a
// different Amazon Web Services account.
//
// Required permissions
//
// * kms:CreateAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the alias (IAM policy).
//
// * kms:CreateAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the KMS key (key policy).
//
// For details, see Controlling access to aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html#alias-access)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * DeleteAlias
//
// * ListAliases
//
// * UpdateAlias
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation CreateAlias for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * AlreadyExistsException
// The request was rejected because it attempted to create a resource that already
// exists.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidAliasNameException
// The request was rejected because the specified alias name is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateAlias
func (c *KMS) CreateAlias(input *CreateAliasInput) (*CreateAliasOutput, error) {
req, out := c.CreateAliasRequest(input)
return out, req.Send()
}
// CreateAliasWithContext is the same as CreateAlias with the addition of
// the ability to pass a context and additional request options.
//
// See CreateAlias for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) CreateAliasWithContext(ctx aws.Context, input *CreateAliasInput, opts ...request.Option) (*CreateAliasOutput, error) {
req, out := c.CreateAliasRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opCreateCustomKeyStore = "CreateCustomKeyStore"
// CreateCustomKeyStoreRequest generates a "aws/request.Request" representing the
// client's request for the CreateCustomKeyStore operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See CreateCustomKeyStore for more information on using the CreateCustomKeyStore
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the CreateCustomKeyStoreRequest method.
// req, resp := client.CreateCustomKeyStoreRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateCustomKeyStore
func (c *KMS) CreateCustomKeyStoreRequest(input *CreateCustomKeyStoreInput) (req *request.Request, output *CreateCustomKeyStoreOutput) {
op := &request.Operation{
Name: opCreateCustomKeyStore,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &CreateCustomKeyStoreInput{}
}
output = &CreateCustomKeyStoreOutput{}
req = c.newRequest(op, input, output)
return
}
// CreateCustomKeyStore API operation for AWS Key Management Service.
//
// Creates a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// that is associated with an CloudHSM cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/clusters.html)
// that you own and manage.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
//
// Before you create the custom key store, you must assemble the required elements,
// including an CloudHSM cluster that fulfills the requirements for a custom
// key store. For details about the required elements, see Assemble the Prerequisites
// (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide.
//
// When the operation completes successfully, it returns the ID of the new custom
// key store. Before you can use your new custom key store, you need to use
// the ConnectCustomKeyStore operation to connect the new key store to its CloudHSM
// cluster. Even if you are not going to use your custom key store immediately,
// you might want to connect it to verify that all settings are correct and
// then disconnect it until you are ready to use it.
//
// For help with failures, see Troubleshooting a Custom Key Store (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:CreateCustomKeyStore (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy).
//
// Related operations:
//
// * ConnectCustomKeyStore
//
// * DeleteCustomKeyStore
//
// * DescribeCustomKeyStores
//
// * DisconnectCustomKeyStore
//
// * UpdateCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation CreateCustomKeyStore for usage and error information.
//
// Returned Error Types:
// * CloudHsmClusterInUseException
// The request was rejected because the specified CloudHSM cluster is already
// associated with a custom key store or it shares a backup history with a cluster
// that is associated with a custom key store. Each custom key store must be
// associated with a different CloudHSM cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
//
// * CustomKeyStoreNameInUseException
// The request was rejected because the specified custom key store name is already
// assigned to another custom key store in the account. Try again with a custom
// key store name that is unique in the account.
//
// * CloudHsmClusterNotFoundException
// The request was rejected because KMS cannot find the CloudHSM cluster with
// the specified cluster ID. Retry the request with a different cluster ID.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * CloudHsmClusterNotActiveException
// The request was rejected because the CloudHSM cluster that is associated
// with the custom key store is not active. Initialize and activate the cluster
// and try the command again. For detailed instructions, see Getting Started
// (https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html)
// in the CloudHSM User Guide.
//
// * IncorrectTrustAnchorException
// The request was rejected because the trust anchor certificate in the request
// is not the trust anchor certificate for the specified CloudHSM cluster.
//
// When you initialize the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html#sign-csr),
// you create the trust anchor certificate and save it in the customerCA.crt
// file.
//
// * CloudHsmClusterInvalidConfigurationException
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateCustomKeyStore
func (c *KMS) CreateCustomKeyStore(input *CreateCustomKeyStoreInput) (*CreateCustomKeyStoreOutput, error) {
req, out := c.CreateCustomKeyStoreRequest(input)
return out, req.Send()
}
// CreateCustomKeyStoreWithContext is the same as CreateCustomKeyStore with the addition of
// the ability to pass a context and additional request options.
//
// See CreateCustomKeyStore for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) CreateCustomKeyStoreWithContext(ctx aws.Context, input *CreateCustomKeyStoreInput, opts ...request.Option) (*CreateCustomKeyStoreOutput, error) {
req, out := c.CreateCustomKeyStoreRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opCreateGrant = "CreateGrant"
// CreateGrantRequest generates a "aws/request.Request" representing the
// client's request for the CreateGrant operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See CreateGrant for more information on using the CreateGrant
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the CreateGrantRequest method.
// req, resp := client.CreateGrantRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateGrant
func (c *KMS) CreateGrantRequest(input *CreateGrantInput) (req *request.Request, output *CreateGrantOutput) {
op := &request.Operation{
Name: opCreateGrant,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &CreateGrantInput{}
}
output = &CreateGrantOutput{}
req = c.newRequest(op, input, output)
return
}
// CreateGrant API operation for AWS Key Management Service.
//
// Adds a grant to a KMS key.
//
// A grant is a policy instrument that allows Amazon Web Services principals
// to use KMS keys in cryptographic operations. It also can allow them to view
// a KMS key (DescribeKey) and create and manage grants. When authorizing access
// to a KMS key, grants are considered along with key policies and IAM policies.
// Grants are often used for temporary permissions because you can create one,
// use its permissions, and delete it without changing your key policies or
// IAM policies.
//
// For detailed information about grants, including grant terminology, see Grants
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)
// in the Key Management Service Developer Guide . For examples of working with
// grants in several programming languages, see Programming grants (https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html).
//
// The CreateGrant operation returns a GrantToken and a GrantId.
//
// * When you create, retire, or revoke a grant, there might be a brief delay,
// usually less than five minutes, until the grant is available throughout
// KMS. This state is known as eventual consistency. Once the grant has achieved
// eventual consistency, the grantee principal can use the permissions in
// the grant without identifying the grant. However, to use the permissions
// in the grant immediately, use the GrantToken that CreateGrant returns.
// For details, see Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide .
//
// * The CreateGrant operation also returns a GrantId. You can use the GrantId
// and a key identifier to identify the grant in the RetireGrant and RevokeGrant
// operations. To find the grant ID, use the ListGrants or ListRetirableGrants
// operations.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation on a KMS key in a different
// Amazon Web Services account, specify the key ARN in the value of the KeyId
// parameter.
//
// Required permissions: kms:CreateGrant (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * ListGrants
//
// * ListRetirableGrants
//
// * RetireGrant
//
// * RevokeGrant
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation CreateGrant for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateGrant
func (c *KMS) CreateGrant(input *CreateGrantInput) (*CreateGrantOutput, error) {
req, out := c.CreateGrantRequest(input)
return out, req.Send()
}
// CreateGrantWithContext is the same as CreateGrant with the addition of
// the ability to pass a context and additional request options.
//
// See CreateGrant for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) CreateGrantWithContext(ctx aws.Context, input *CreateGrantInput, opts ...request.Option) (*CreateGrantOutput, error) {
req, out := c.CreateGrantRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opCreateKey = "CreateKey"
// CreateKeyRequest generates a "aws/request.Request" representing the
// client's request for the CreateKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See CreateKey for more information on using the CreateKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the CreateKeyRequest method.
// req, resp := client.CreateKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateKey
func (c *KMS) CreateKeyRequest(input *CreateKeyInput) (req *request.Request, output *CreateKeyOutput) {
op := &request.Operation{
Name: opCreateKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &CreateKeyInput{}
}
output = &CreateKeyOutput{}
req = c.newRequest(op, input, output)
return
}
// CreateKey API operation for AWS Key Management Service.
//
// Creates a unique customer managed KMS key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms-keys)
// in your Amazon Web Services account and Region.
//
// In addition to the required parameters, you can use the optional parameters
// to specify a key policy, description, tags, and other useful elements for
// any key type.
//
// KMS is replacing the term customer master key (CMK) with KMS key and KMS
// key. The concept has not changed. To prevent breaking changes, KMS is keeping
// some variations of this term.
//
// To create different types of KMS keys, use the following guidance:
//
// Symmetric encryption KMS key
//
// To create a symmetric encryption KMS key, you aren't required to specify
// any parameters. The default value for KeySpec, SYMMETRIC_DEFAULT, and the
// default value for KeyUsage, ENCRYPT_DECRYPT, create a symmetric encryption
// KMS key.
//
// If you need a key for basic encryption and decryption or you are creating
// a KMS key to protect your resources in an Amazon Web Services service, create
// a symmetric encryption KMS key. The key material in a symmetric encryption
// key never leaves KMS unencrypted. You can use a symmetric encryption KMS
// key to encrypt and decrypt data up to 4,096 bytes, but they are typically
// used to generate data keys and data keys pairs. For details, see GenerateDataKey
// and GenerateDataKeyPair.
//
// Asymmetric KMS keys
//
// To create an asymmetric KMS key, use the KeySpec parameter to specify the
// type of key material in the KMS key. Then, use the KeyUsage parameter to
// determine whether the KMS key will be used to encrypt and decrypt or sign
// and verify. You can't change these properties after the KMS key is created.
//
// Asymmetric KMS keys contain an RSA key pair or an Elliptic Curve (ECC) key
// pair. The private key in an asymmetric KMS key never leaves AWS KMS unencrypted.
// However, you can use the GetPublicKey operation to download the public key
// so it can be used outside of AWS KMS. KMS keys with RSA key pairs can be
// used to encrypt or decrypt data or sign and verify messages (but not both).
// KMS keys with ECC key pairs can be used only to sign and verify messages.
// For information about asymmetric KMS keys, see Asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
// in the Key Management Service Developer Guide.
//
// HMAC KMS key
//
// To create an HMAC KMS key, set the KeySpec parameter to a key spec value
// for HMAC KMS keys. Then set the KeyUsage parameter to GENERATE_VERIFY_MAC.
// You must set the key usage even though GENERATE_VERIFY_MAC is the only valid
// key usage value for HMAC KMS keys. You can't change these properties after
// the KMS key is created.
//
// HMAC KMS keys are symmetric keys that never leave KMS unencrypted. You can
// use HMAC keys to generate (GenerateMac) and verify (VerifyMac) HMAC codes
// for messages up to 4096 bytes.
//
// HMAC KMS keys are not supported in all Amazon Web Services Regions. If you
// try to create an HMAC KMS key in an Amazon Web Services Region in which HMAC
// keys are not supported, the CreateKey operation returns an UnsupportedOperationException.
// For a list of Regions in which HMAC KMS keys are supported, see HMAC keys
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html)
// in the Key Management Service Developer Guide.
//
// Multi-Region primary keys
//
// Imported key material
//
// To create a multi-Region primary key in the local Amazon Web Services Region,
// use the MultiRegion parameter with a value of True. To create a multi-Region
// replica key, that is, a KMS key with the same key ID and key material as
// a primary key, but in a different Amazon Web Services Region, use the ReplicateKey
// operation. To change a replica key to a primary key, and its primary key
// to a replica key, use the UpdatePrimaryRegion operation.
//
// You can create multi-Region KMS keys for all supported KMS key types: symmetric
// encryption KMS keys, HMAC KMS keys, asymmetric encryption KMS keys, and asymmetric
// signing KMS keys. You can also create multi-Region keys with imported key
// material. However, you can't create multi-Region keys in a custom key store.
//
// This operation supports multi-Region keys, an KMS feature that lets you create
// multiple interoperable KMS keys in different Amazon Web Services Regions.
// Because these KMS keys have the same key ID, key material, and other metadata,
// you can use them interchangeably to encrypt data in one Amazon Web Services
// Region and decrypt it in a different Amazon Web Services Region without re-encrypting
// the data or making a cross-Region call. For more information about multi-Region
// keys, see Multi-Region keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
//
// To import your own key material, begin by creating a symmetric encryption
// KMS key with no key material. To do this, use the Origin parameter of CreateKey
// with a value of EXTERNAL. Next, use GetParametersForImport operation to get
// a public key and import token, and use the public key to encrypt your key
// material. Then, use ImportKeyMaterial with your import token to import the
// key material. For step-by-step instructions, see Importing Key Material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)
// in the Key Management Service Developer Guide .
//
// This feature supports only symmetric encryption KMS keys, including multi-Region
// symmetric encryption KMS keys. You cannot import key material into any other
// type of KMS key.
//
// To create a multi-Region primary key with imported key material, use the
// Origin parameter of CreateKey with a value of EXTERNAL and the MultiRegion
// parameter with a value of True. To create replicas of the multi-Region primary
// key, use the ReplicateKey operation. For more information about multi-Region
// keys, see Multi-Region keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
//
// Custom key store
//
// To create a symmetric encryption KMS key in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html),
// use the CustomKeyStoreId parameter to specify the custom key store. You must
// also use the Origin parameter with a value of AWS_CLOUDHSM. The CloudHSM
// cluster that is associated with the custom key store must have at least two
// active HSMs in different Availability Zones in the Amazon Web Services Region.
//
// Custom key stores support only symmetric encryption KMS keys. You cannot
// create an HMAC KMS key or an asymmetric KMS key in a custom key store. For
// information about custom key stores in KMS see Custom key stores in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// in the Key Management Service Developer Guide .
//
// Cross-account use: No. You cannot use this operation to create a KMS key
// in a different Amazon Web Services account.
//
// Required permissions: kms:CreateKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy). To use the Tags parameter, kms:TagResource (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy). For examples and information about related permissions, see
// Allow a user to create KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html#iam-policy-example-create-key)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * DescribeKey
//
// * ListKeys
//
// * ScheduleKeyDeletion
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation CreateKey for usage and error information.
//
// Returned Error Types:
// * MalformedPolicyDocumentException
// The request was rejected because the specified policy is not syntactically
// or semantically correct.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * TagException
// The request was rejected because one or more tags are not valid.
//
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// * CloudHsmClusterInvalidConfigurationException
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/CreateKey
func (c *KMS) CreateKey(input *CreateKeyInput) (*CreateKeyOutput, error) {
req, out := c.CreateKeyRequest(input)
return out, req.Send()
}
// CreateKeyWithContext is the same as CreateKey with the addition of
// the ability to pass a context and additional request options.
//
// See CreateKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) CreateKeyWithContext(ctx aws.Context, input *CreateKeyInput, opts ...request.Option) (*CreateKeyOutput, error) {
req, out := c.CreateKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDecrypt = "Decrypt"
// DecryptRequest generates a "aws/request.Request" representing the
// client's request for the Decrypt operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See Decrypt for more information on using the Decrypt
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DecryptRequest method.
// req, resp := client.DecryptRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Decrypt
func (c *KMS) DecryptRequest(input *DecryptInput) (req *request.Request, output *DecryptOutput) {
op := &request.Operation{
Name: opDecrypt,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DecryptInput{}
}
output = &DecryptOutput{}
req = c.newRequest(op, input, output)
return
}
// Decrypt API operation for AWS Key Management Service.
//
// Decrypts ciphertext that was encrypted by a KMS key using any of the following
// operations:
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// * GenerateDataKeyWithoutPlaintext
//
// * GenerateDataKeyPairWithoutPlaintext
//
// You can use this operation to decrypt ciphertext that was encrypted under
// a symmetric encryption KMS key or an asymmetric encryption KMS key. When
// the KMS key is asymmetric, you must specify the KMS key and the encryption
// algorithm that was used to encrypt the ciphertext. For information about
// asymmetric KMS keys, see Asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
// in the Key Management Service Developer Guide.
//
// The Decrypt operation also decrypts ciphertext that was encrypted outside
// of KMS by the public key in an KMS asymmetric KMS key. However, it cannot
// decrypt symmetric ciphertext produced by other libraries, such as the Amazon
// Web Services Encryption SDK (https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/)
// or Amazon S3 client-side encryption (https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html).
// These libraries return a ciphertext format that is incompatible with KMS.
//
// If the ciphertext was encrypted under a symmetric encryption KMS key, the
// KeyId parameter is optional. KMS can get this information from metadata that
// it adds to the symmetric ciphertext blob. This feature adds durability to
// your implementation by ensuring that authorized users can decrypt ciphertext
// decades after it was encrypted, even if they've lost track of the key ID.
// However, specifying the KMS key is always recommended as a best practice.
// When you use the KeyId parameter to specify a KMS key, KMS only uses the
// KMS key you specify. If the ciphertext was encrypted under a different KMS
// key, the Decrypt operation fails. This practice ensures that you use the
// KMS key that you intend.
//
// Whenever possible, use key policies to give users permission to call the
// Decrypt operation on a particular KMS key, instead of using IAM policies.
// Otherwise, you might create an IAM user policy that gives the user Decrypt
// permission on all KMS keys. This user could decrypt ciphertext that was encrypted
// by KMS keys in other accounts if the key policy for the cross-account KMS
// key permits it. If you must use an IAM policy for Decrypt permissions, limit
// the user to particular KMS keys or particular trusted accounts. For details,
// see Best practices for IAM policies (https://docs.aws.amazon.com/kms/latest/developerguide/iam-policies.html#iam-policies-best-practices)
// in the Key Management Service Developer Guide.
//
// Applications in Amazon Web Services Nitro Enclaves can call this operation
// by using the Amazon Web Services Nitro Enclaves Development Kit (https://github.com/aws/aws-nitro-enclaves-sdk-c).
// For information about the supporting parameters, see How Amazon Web Services
// Nitro Enclaves use KMS (https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:Decrypt (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// * ReEncrypt
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation Decrypt for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidCiphertextException
// From the Decrypt or ReEncrypt operation, the request was rejected because
// the specified ciphertext, or additional authenticated data incorporated into
// the ciphertext, such as the encryption context, is corrupted, missing, or
// otherwise invalid.
//
// From the ImportKeyMaterial operation, the request was rejected because KMS
// could not decrypt the encrypted (wrapped) key material.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * IncorrectKeyException
// The request was rejected because the specified KMS key cannot decrypt the
// data. The KeyId in a Decrypt request and the SourceKeyId in a ReEncrypt request
// must identify the same KMS key that was used to encrypt the ciphertext.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Decrypt
func (c *KMS) Decrypt(input *DecryptInput) (*DecryptOutput, error) {
req, out := c.DecryptRequest(input)
return out, req.Send()
}
// DecryptWithContext is the same as Decrypt with the addition of
// the ability to pass a context and additional request options.
//
// See Decrypt for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DecryptWithContext(ctx aws.Context, input *DecryptInput, opts ...request.Option) (*DecryptOutput, error) {
req, out := c.DecryptRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDeleteAlias = "DeleteAlias"
// DeleteAliasRequest generates a "aws/request.Request" representing the
// client's request for the DeleteAlias operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DeleteAlias for more information on using the DeleteAlias
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DeleteAliasRequest method.
// req, resp := client.DeleteAliasRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteAlias
func (c *KMS) DeleteAliasRequest(input *DeleteAliasInput) (req *request.Request, output *DeleteAliasOutput) {
op := &request.Operation{
Name: opDeleteAlias,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DeleteAliasInput{}
}
output = &DeleteAliasOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DeleteAlias API operation for AWS Key Management Service.
//
// Deletes the specified alias.
//
// Adding, deleting, or updating an alias can allow or deny permission to the
// KMS key. For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// Because an alias is not a property of a KMS key, you can delete and change
// the aliases of a KMS key without affecting the KMS key. Also, aliases do
// not appear in the response from the DescribeKey operation. To get the aliases
// of all KMS keys, use the ListAliases operation.
//
// Each KMS key can have multiple aliases. To change the alias of a KMS key,
// use DeleteAlias to delete the current alias and CreateAlias to create a new
// alias. To associate an existing alias with a different KMS key, call UpdateAlias.
//
// Cross-account use: No. You cannot perform this operation on an alias in a
// different Amazon Web Services account.
//
// Required permissions
//
// * kms:DeleteAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the alias (IAM policy).
//
// * kms:DeleteAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the KMS key (key policy).
//
// For details, see Controlling access to aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html#alias-access)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * CreateAlias
//
// * ListAliases
//
// * UpdateAlias
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DeleteAlias for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteAlias
func (c *KMS) DeleteAlias(input *DeleteAliasInput) (*DeleteAliasOutput, error) {
req, out := c.DeleteAliasRequest(input)
return out, req.Send()
}
// DeleteAliasWithContext is the same as DeleteAlias with the addition of
// the ability to pass a context and additional request options.
//
// See DeleteAlias for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DeleteAliasWithContext(ctx aws.Context, input *DeleteAliasInput, opts ...request.Option) (*DeleteAliasOutput, error) {
req, out := c.DeleteAliasRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDeleteCustomKeyStore = "DeleteCustomKeyStore"
// DeleteCustomKeyStoreRequest generates a "aws/request.Request" representing the
// client's request for the DeleteCustomKeyStore operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DeleteCustomKeyStore for more information on using the DeleteCustomKeyStore
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DeleteCustomKeyStoreRequest method.
// req, resp := client.DeleteCustomKeyStoreRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteCustomKeyStore
func (c *KMS) DeleteCustomKeyStoreRequest(input *DeleteCustomKeyStoreInput) (req *request.Request, output *DeleteCustomKeyStoreOutput) {
op := &request.Operation{
Name: opDeleteCustomKeyStore,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DeleteCustomKeyStoreInput{}
}
output = &DeleteCustomKeyStoreOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DeleteCustomKeyStore API operation for AWS Key Management Service.
//
// Deletes a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// This operation does not delete the CloudHSM cluster that is associated with
// the custom key store, or affect any users or keys in the cluster.
//
// The custom key store that you delete cannot contain any KMS KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys).
// Before deleting the key store, verify that you will never need to use any
// of the KMS keys in the key store for any cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations).
// Then, use ScheduleKeyDeletion to delete the KMS keys from the key store.
// When the scheduled waiting period expires, the ScheduleKeyDeletion operation
// deletes the KMS keys. Then it makes a best effort to delete the key material
// from the associated cluster. However, you might need to manually delete the
// orphaned key material (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-orphaned-key)
// from the cluster and its backups.
//
// After all KMS keys are deleted from KMS, use DisconnectCustomKeyStore to
// disconnect the key store from KMS. Then, you can delete the custom key store.
//
// Instead of deleting the custom key store, consider using DisconnectCustomKeyStore
// to disconnect it from KMS. While the key store is disconnected, you cannot
// create or use the KMS keys in the key store. But, you do not need to delete
// KMS keys and you can reconnect a disconnected custom key store at any time.
//
// If the operation succeeds, it returns a JSON object with no properties.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:DeleteCustomKeyStore (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations:
//
// * ConnectCustomKeyStore
//
// * CreateCustomKeyStore
//
// * DescribeCustomKeyStores
//
// * DisconnectCustomKeyStore
//
// * UpdateCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DeleteCustomKeyStore for usage and error information.
//
// Returned Error Types:
// * CustomKeyStoreHasCMKsException
// The request was rejected because the custom key store contains KMS keys.
// After verifying that you do not need to use the KMS keys, use the ScheduleKeyDeletion
// operation to delete the KMS keys. After they are deleted, you can delete
// the custom key store.
//
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteCustomKeyStore
func (c *KMS) DeleteCustomKeyStore(input *DeleteCustomKeyStoreInput) (*DeleteCustomKeyStoreOutput, error) {
req, out := c.DeleteCustomKeyStoreRequest(input)
return out, req.Send()
}
// DeleteCustomKeyStoreWithContext is the same as DeleteCustomKeyStore with the addition of
// the ability to pass a context and additional request options.
//
// See DeleteCustomKeyStore for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DeleteCustomKeyStoreWithContext(ctx aws.Context, input *DeleteCustomKeyStoreInput, opts ...request.Option) (*DeleteCustomKeyStoreOutput, error) {
req, out := c.DeleteCustomKeyStoreRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDeleteImportedKeyMaterial = "DeleteImportedKeyMaterial"
// DeleteImportedKeyMaterialRequest generates a "aws/request.Request" representing the
// client's request for the DeleteImportedKeyMaterial operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DeleteImportedKeyMaterial for more information on using the DeleteImportedKeyMaterial
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DeleteImportedKeyMaterialRequest method.
// req, resp := client.DeleteImportedKeyMaterialRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteImportedKeyMaterial
func (c *KMS) DeleteImportedKeyMaterialRequest(input *DeleteImportedKeyMaterialInput) (req *request.Request, output *DeleteImportedKeyMaterialOutput) {
op := &request.Operation{
Name: opDeleteImportedKeyMaterial,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DeleteImportedKeyMaterialInput{}
}
output = &DeleteImportedKeyMaterialOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DeleteImportedKeyMaterial API operation for AWS Key Management Service.
//
// Deletes key material that you previously imported. This operation makes the
// specified KMS key unusable. For more information about importing key material
// into KMS, see Importing Key Material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)
// in the Key Management Service Developer Guide.
//
// When the specified KMS key is in the PendingDeletion state, this operation
// does not change the KMS key's state. Otherwise, it changes the KMS key's
// state to PendingImport.
//
// After you delete key material, you can use ImportKeyMaterial to reimport
// the same key material into the KMS key.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:DeleteImportedKeyMaterial (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * GetParametersForImport
//
// * ImportKeyMaterial
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DeleteImportedKeyMaterial for usage and error information.
//
// Returned Error Types:
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DeleteImportedKeyMaterial
func (c *KMS) DeleteImportedKeyMaterial(input *DeleteImportedKeyMaterialInput) (*DeleteImportedKeyMaterialOutput, error) {
req, out := c.DeleteImportedKeyMaterialRequest(input)
return out, req.Send()
}
// DeleteImportedKeyMaterialWithContext is the same as DeleteImportedKeyMaterial with the addition of
// the ability to pass a context and additional request options.
//
// See DeleteImportedKeyMaterial for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DeleteImportedKeyMaterialWithContext(ctx aws.Context, input *DeleteImportedKeyMaterialInput, opts ...request.Option) (*DeleteImportedKeyMaterialOutput, error) {
req, out := c.DeleteImportedKeyMaterialRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDescribeCustomKeyStores = "DescribeCustomKeyStores"
// DescribeCustomKeyStoresRequest generates a "aws/request.Request" representing the
// client's request for the DescribeCustomKeyStores operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DescribeCustomKeyStores for more information on using the DescribeCustomKeyStores
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DescribeCustomKeyStoresRequest method.
// req, resp := client.DescribeCustomKeyStoresRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DescribeCustomKeyStores
func (c *KMS) DescribeCustomKeyStoresRequest(input *DescribeCustomKeyStoresInput) (req *request.Request, output *DescribeCustomKeyStoresOutput) {
op := &request.Operation{
Name: opDescribeCustomKeyStores,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DescribeCustomKeyStoresInput{}
}
output = &DescribeCustomKeyStoresOutput{}
req = c.newRequest(op, input, output)
return
}
// DescribeCustomKeyStores API operation for AWS Key Management Service.
//
// Gets information about custom key stores (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// in the account and Region.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
//
// By default, this operation returns information about all custom key stores
// in the account and Region. To get only information about a particular custom
// key store, use either the CustomKeyStoreName or CustomKeyStoreId parameter
// (but not both).
//
// To determine whether the custom key store is connected to its CloudHSM cluster,
// use the ConnectionState element in the response. If an attempt to connect
// the custom key store failed, the ConnectionState value is FAILED and the
// ConnectionErrorCode element in the response indicates the cause of the failure.
// For help interpreting the ConnectionErrorCode, see CustomKeyStoresListEntry.
//
// Custom key stores have a DISCONNECTED connection state if the key store has
// never been connected or you use the DisconnectCustomKeyStore operation to
// disconnect it. If your custom key store state is CONNECTED but you are having
// trouble using it, make sure that its associated CloudHSM cluster is active
// and contains the minimum number of HSMs required for the operation, if any.
//
// For help repairing your custom key store, see the Troubleshooting Custom
// Key Stores (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html)
// topic in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:DescribeCustomKeyStores (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations:
//
// * ConnectCustomKeyStore
//
// * CreateCustomKeyStore
//
// * DeleteCustomKeyStore
//
// * DisconnectCustomKeyStore
//
// * UpdateCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DescribeCustomKeyStores for usage and error information.
//
// Returned Error Types:
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DescribeCustomKeyStores
func (c *KMS) DescribeCustomKeyStores(input *DescribeCustomKeyStoresInput) (*DescribeCustomKeyStoresOutput, error) {
req, out := c.DescribeCustomKeyStoresRequest(input)
return out, req.Send()
}
// DescribeCustomKeyStoresWithContext is the same as DescribeCustomKeyStores with the addition of
// the ability to pass a context and additional request options.
//
// See DescribeCustomKeyStores for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DescribeCustomKeyStoresWithContext(ctx aws.Context, input *DescribeCustomKeyStoresInput, opts ...request.Option) (*DescribeCustomKeyStoresOutput, error) {
req, out := c.DescribeCustomKeyStoresRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDescribeKey = "DescribeKey"
// DescribeKeyRequest generates a "aws/request.Request" representing the
// client's request for the DescribeKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DescribeKey for more information on using the DescribeKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DescribeKeyRequest method.
// req, resp := client.DescribeKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DescribeKey
func (c *KMS) DescribeKeyRequest(input *DescribeKeyInput) (req *request.Request, output *DescribeKeyOutput) {
op := &request.Operation{
Name: opDescribeKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DescribeKeyInput{}
}
output = &DescribeKeyOutput{}
req = c.newRequest(op, input, output)
return
}
// DescribeKey API operation for AWS Key Management Service.
//
// Provides detailed information about a KMS key. You can run DescribeKey on
// a customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)
// or an Amazon Web Services managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk).
//
// This detailed information includes the key ARN, creation date (and deletion
// date, if applicable), the key state, and the origin and expiration date (if
// any) of the key material. It includes fields, like KeySpec, that help you
// distinguish different types of KMS keys. It also displays the key usage (encryption,
// signing, or generating and verifying MACs) and the algorithms that the KMS
// key supports. For KMS keys in custom key stores, it includes information
// about the custom key store, such as the key store ID and the CloudHSM cluster
// ID. For multi-Region keys, it displays the primary key and all related replica
// keys.
//
// DescribeKey does not return the following information:
//
// * Aliases associated with the KMS key. To get this information, use ListAliases.
//
// * Whether automatic key rotation is enabled on the KMS key. To get this
// information, use GetKeyRotationStatus. Also, some key states prevent a
// KMS key from being automatically rotated. For details, see How Automatic
// Key Rotation Works (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html#rotate-keys-how-it-works)
// in Key Management Service Developer Guide.
//
// * Tags on the KMS key. To get this information, use ListResourceTags.
//
// * Key policies and grants on the KMS key. To get this information, use
// GetKeyPolicy and ListGrants.
//
// In general, DescribeKey is a non-mutating operation. It returns data about
// KMS keys, but doesn't change them. However, Amazon Web Services services
// use DescribeKey to create Amazon Web Services managed keys (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk)
// from a predefined Amazon Web Services alias with no key ID.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:DescribeKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * GetKeyPolicy
//
// * GetKeyRotationStatus
//
// * ListAliases
//
// * ListGrants
//
// * ListKeys
//
// * ListResourceTags
//
// * ListRetirableGrants
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DescribeKey for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DescribeKey
func (c *KMS) DescribeKey(input *DescribeKeyInput) (*DescribeKeyOutput, error) {
req, out := c.DescribeKeyRequest(input)
return out, req.Send()
}
// DescribeKeyWithContext is the same as DescribeKey with the addition of
// the ability to pass a context and additional request options.
//
// See DescribeKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DescribeKeyWithContext(ctx aws.Context, input *DescribeKeyInput, opts ...request.Option) (*DescribeKeyOutput, error) {
req, out := c.DescribeKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDisableKey = "DisableKey"
// DisableKeyRequest generates a "aws/request.Request" representing the
// client's request for the DisableKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DisableKey for more information on using the DisableKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DisableKeyRequest method.
// req, resp := client.DisableKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisableKey
func (c *KMS) DisableKeyRequest(input *DisableKeyInput) (req *request.Request, output *DisableKeyOutput) {
op := &request.Operation{
Name: opDisableKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DisableKeyInput{}
}
output = &DisableKeyOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DisableKey API operation for AWS Key Management Service.
//
// Sets the state of a KMS key to disabled. This change temporarily prevents
// use of the KMS key for cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations).
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:DisableKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: EnableKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DisableKey for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisableKey
func (c *KMS) DisableKey(input *DisableKeyInput) (*DisableKeyOutput, error) {
req, out := c.DisableKeyRequest(input)
return out, req.Send()
}
// DisableKeyWithContext is the same as DisableKey with the addition of
// the ability to pass a context and additional request options.
//
// See DisableKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DisableKeyWithContext(ctx aws.Context, input *DisableKeyInput, opts ...request.Option) (*DisableKeyOutput, error) {
req, out := c.DisableKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDisableKeyRotation = "DisableKeyRotation"
// DisableKeyRotationRequest generates a "aws/request.Request" representing the
// client's request for the DisableKeyRotation operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DisableKeyRotation for more information on using the DisableKeyRotation
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DisableKeyRotationRequest method.
// req, resp := client.DisableKeyRotationRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisableKeyRotation
func (c *KMS) DisableKeyRotationRequest(input *DisableKeyRotationInput) (req *request.Request, output *DisableKeyRotationOutput) {
op := &request.Operation{
Name: opDisableKeyRotation,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DisableKeyRotationInput{}
}
output = &DisableKeyRotationOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DisableKeyRotation API operation for AWS Key Management Service.
//
// Disables automatic rotation of the key material (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
// for the specified symmetric encryption KMS key.
//
// You cannot enable automatic rotation of asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html),
// HMAC KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html),
// KMS keys with imported key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html),
// or KMS keys in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// To enable or disable automatic rotation of a set of related multi-Region
// keys (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-manage.html#multi-region-rotate),
// set the property on the primary key.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:DisableKeyRotation (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * EnableKeyRotation
//
// * GetKeyRotationStatus
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DisableKeyRotation for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisableKeyRotation
func (c *KMS) DisableKeyRotation(input *DisableKeyRotationInput) (*DisableKeyRotationOutput, error) {
req, out := c.DisableKeyRotationRequest(input)
return out, req.Send()
}
// DisableKeyRotationWithContext is the same as DisableKeyRotation with the addition of
// the ability to pass a context and additional request options.
//
// See DisableKeyRotation for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DisableKeyRotationWithContext(ctx aws.Context, input *DisableKeyRotationInput, opts ...request.Option) (*DisableKeyRotationOutput, error) {
req, out := c.DisableKeyRotationRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDisconnectCustomKeyStore = "DisconnectCustomKeyStore"
// DisconnectCustomKeyStoreRequest generates a "aws/request.Request" representing the
// client's request for the DisconnectCustomKeyStore operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DisconnectCustomKeyStore for more information on using the DisconnectCustomKeyStore
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DisconnectCustomKeyStoreRequest method.
// req, resp := client.DisconnectCustomKeyStoreRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisconnectCustomKeyStore
func (c *KMS) DisconnectCustomKeyStoreRequest(input *DisconnectCustomKeyStoreInput) (req *request.Request, output *DisconnectCustomKeyStoreOutput) {
op := &request.Operation{
Name: opDisconnectCustomKeyStore,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DisconnectCustomKeyStoreInput{}
}
output = &DisconnectCustomKeyStoreOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// DisconnectCustomKeyStore API operation for AWS Key Management Service.
//
// Disconnects the custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// from its associated CloudHSM cluster. While a custom key store is disconnected,
// you can manage the custom key store and its KMS keys, but you cannot create
// or use KMS keys in the custom key store. You can reconnect the custom key
// store at any time.
//
// While a custom key store is disconnected, all attempts to create KMS keys
// in the custom key store or to use existing KMS keys in cryptographic operations
// (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// will fail. This action can prevent users from storing and accessing sensitive
// data.
//
// To find the connection state of a custom key store, use the DescribeCustomKeyStores
// operation. To reconnect a custom key store, use the ConnectCustomKeyStore
// operation.
//
// If the operation succeeds, it returns a JSON object with no properties.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:DisconnectCustomKeyStore (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations:
//
// * ConnectCustomKeyStore
//
// * CreateCustomKeyStore
//
// * DeleteCustomKeyStore
//
// * DescribeCustomKeyStores
//
// * UpdateCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation DisconnectCustomKeyStore for usage and error information.
//
// Returned Error Types:
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/DisconnectCustomKeyStore
func (c *KMS) DisconnectCustomKeyStore(input *DisconnectCustomKeyStoreInput) (*DisconnectCustomKeyStoreOutput, error) {
req, out := c.DisconnectCustomKeyStoreRequest(input)
return out, req.Send()
}
// DisconnectCustomKeyStoreWithContext is the same as DisconnectCustomKeyStore with the addition of
// the ability to pass a context and additional request options.
//
// See DisconnectCustomKeyStore for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) DisconnectCustomKeyStoreWithContext(ctx aws.Context, input *DisconnectCustomKeyStoreInput, opts ...request.Option) (*DisconnectCustomKeyStoreOutput, error) {
req, out := c.DisconnectCustomKeyStoreRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opEnableKey = "EnableKey"
// EnableKeyRequest generates a "aws/request.Request" representing the
// client's request for the EnableKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See EnableKey for more information on using the EnableKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the EnableKeyRequest method.
// req, resp := client.EnableKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/EnableKey
func (c *KMS) EnableKeyRequest(input *EnableKeyInput) (req *request.Request, output *EnableKeyOutput) {
op := &request.Operation{
Name: opEnableKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &EnableKeyInput{}
}
output = &EnableKeyOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// EnableKey API operation for AWS Key Management Service.
//
// Sets the key state of a KMS key to enabled. This allows you to use the KMS
// key for cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations).
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:EnableKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: DisableKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation EnableKey for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/EnableKey
func (c *KMS) EnableKey(input *EnableKeyInput) (*EnableKeyOutput, error) {
req, out := c.EnableKeyRequest(input)
return out, req.Send()
}
// EnableKeyWithContext is the same as EnableKey with the addition of
// the ability to pass a context and additional request options.
//
// See EnableKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) EnableKeyWithContext(ctx aws.Context, input *EnableKeyInput, opts ...request.Option) (*EnableKeyOutput, error) {
req, out := c.EnableKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opEnableKeyRotation = "EnableKeyRotation"
// EnableKeyRotationRequest generates a "aws/request.Request" representing the
// client's request for the EnableKeyRotation operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See EnableKeyRotation for more information on using the EnableKeyRotation
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the EnableKeyRotationRequest method.
// req, resp := client.EnableKeyRotationRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/EnableKeyRotation
func (c *KMS) EnableKeyRotationRequest(input *EnableKeyRotationInput) (req *request.Request, output *EnableKeyRotationOutput) {
op := &request.Operation{
Name: opEnableKeyRotation,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &EnableKeyRotationInput{}
}
output = &EnableKeyRotationOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// EnableKeyRotation API operation for AWS Key Management Service.
//
// Enables automatic rotation of the key material (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
// for the specified symmetric encryption KMS key.
//
// You cannot enable automatic rotation of asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html),
// HMAC KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html),
// KMS keys with imported key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html),
// or KMS keys in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// To enable or disable automatic rotation of a set of related multi-Region
// keys (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-manage.html#multi-region-rotate),
// set the property on the primary key.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:EnableKeyRotation (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * DisableKeyRotation
//
// * GetKeyRotationStatus
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation EnableKeyRotation for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/EnableKeyRotation
func (c *KMS) EnableKeyRotation(input *EnableKeyRotationInput) (*EnableKeyRotationOutput, error) {
req, out := c.EnableKeyRotationRequest(input)
return out, req.Send()
}
// EnableKeyRotationWithContext is the same as EnableKeyRotation with the addition of
// the ability to pass a context and additional request options.
//
// See EnableKeyRotation for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) EnableKeyRotationWithContext(ctx aws.Context, input *EnableKeyRotationInput, opts ...request.Option) (*EnableKeyRotationOutput, error) {
req, out := c.EnableKeyRotationRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opEncrypt = "Encrypt"
// EncryptRequest generates a "aws/request.Request" representing the
// client's request for the Encrypt operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See Encrypt for more information on using the Encrypt
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the EncryptRequest method.
// req, resp := client.EncryptRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Encrypt
func (c *KMS) EncryptRequest(input *EncryptInput) (req *request.Request, output *EncryptOutput) {
op := &request.Operation{
Name: opEncrypt,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &EncryptInput{}
}
output = &EncryptOutput{}
req = c.newRequest(op, input, output)
return
}
// Encrypt API operation for AWS Key Management Service.
//
// Encrypts plaintext of up to 4,096 bytes using a KMS key. You can use a symmetric
// or asymmetric KMS key with a KeyUsage of ENCRYPT_DECRYPT.
//
// You can use this operation to encrypt small amounts of arbitrary data, such
// as a personal identifier or database password, or other sensitive information.
// You don't need to use the Encrypt operation to encrypt a data key. The GenerateDataKey
// and GenerateDataKeyPair operations return a plaintext data key and an encrypted
// copy of that data key.
//
// If you use a symmetric encryption KMS key, you can use an encryption context
// to add additional security to your encryption operation. If you specify an
// EncryptionContext when encrypting data, you must specify the same encryption
// context (a case-sensitive exact match) when decrypting the data. Otherwise,
// the request to decrypt fails with an InvalidCiphertextException. For more
// information, see Encryption Context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
//
// If you specify an asymmetric KMS key, you must also specify the encryption
// algorithm. The algorithm must be compatible with the KMS key type.
//
// When you use an asymmetric KMS key to encrypt or reencrypt data, be sure
// to record the KMS key and encryption algorithm that you choose. You will
// be required to provide the same KMS key and encryption algorithm when you
// decrypt the data. If the KMS key and algorithm do not match the values used
// to encrypt the data, the decrypt operation fails.
//
// You are not required to supply the key ID and encryption algorithm when you
// decrypt with symmetric encryption KMS keys because KMS stores this information
// in the ciphertext blob. KMS cannot store metadata in ciphertext generated
// with asymmetric keys. The standard format for asymmetric key ciphertext does
// not include configurable fields.
//
// The maximum size of the data that you can encrypt varies with the type of
// KMS key and the encryption algorithm that you choose.
//
// * Symmetric encryption KMS keys SYMMETRIC_DEFAULT: 4096 bytes
//
// * RSA_2048 RSAES_OAEP_SHA_1: 214 bytes RSAES_OAEP_SHA_256: 190 bytes
//
// * RSA_3072 RSAES_OAEP_SHA_1: 342 bytes RSAES_OAEP_SHA_256: 318 bytes
//
// * RSA_4096 RSAES_OAEP_SHA_1: 470 bytes RSAES_OAEP_SHA_256: 446 bytes
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:Encrypt (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Decrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation Encrypt for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Encrypt
func (c *KMS) Encrypt(input *EncryptInput) (*EncryptOutput, error) {
req, out := c.EncryptRequest(input)
return out, req.Send()
}
// EncryptWithContext is the same as Encrypt with the addition of
// the ability to pass a context and additional request options.
//
// See Encrypt for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) EncryptWithContext(ctx aws.Context, input *EncryptInput, opts ...request.Option) (*EncryptOutput, error) {
req, out := c.EncryptRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateDataKey = "GenerateDataKey"
// GenerateDataKeyRequest generates a "aws/request.Request" representing the
// client's request for the GenerateDataKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateDataKey for more information on using the GenerateDataKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateDataKeyRequest method.
// req, resp := client.GenerateDataKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKey
func (c *KMS) GenerateDataKeyRequest(input *GenerateDataKeyInput) (req *request.Request, output *GenerateDataKeyOutput) {
op := &request.Operation{
Name: opGenerateDataKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateDataKeyInput{}
}
output = &GenerateDataKeyOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateDataKey API operation for AWS Key Management Service.
//
// Returns a unique symmetric data key for use outside of KMS. This operation
// returns a plaintext copy of the data key and a copy that is encrypted under
// a symmetric encryption KMS key that you specify. The bytes in the plaintext
// key are random; they are not related to the caller or the KMS key. You can
// use the plaintext key to encrypt your data outside of KMS and store the encrypted
// data key with the encrypted data.
//
// To generate a data key, specify the symmetric encryption KMS key that will
// be used to encrypt the data key. You cannot use an asymmetric KMS key to
// encrypt data keys. To get the type of your KMS key, use the DescribeKey operation.
// You must also specify the length of the data key. Use either the KeySpec
// or NumberOfBytes parameters (but not both). For 128-bit and 256-bit data
// keys, use the KeySpec parameter.
//
// To get only an encrypted copy of the data key, use GenerateDataKeyWithoutPlaintext.
// To generate an asymmetric data key pair, use the GenerateDataKeyPair or GenerateDataKeyPairWithoutPlaintext
// operation. To get a cryptographically secure random byte string, use GenerateRandom.
//
// You can use an optional encryption context to add additional security to
// the encryption operation. If you specify an EncryptionContext, you must specify
// the same encryption context (a case-sensitive exact match) when decrypting
// the encrypted data key. Otherwise, the request to decrypt fails with an InvalidCiphertextException.
// For more information, see Encryption Context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
//
// Applications in Amazon Web Services Nitro Enclaves can call this operation
// by using the Amazon Web Services Nitro Enclaves Development Kit (https://github.com/aws/aws-nitro-enclaves-sdk-c).
// For information about the supporting parameters, see How Amazon Web Services
// Nitro Enclaves use KMS (https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// How to use your data key
//
// We recommend that you use the following pattern to encrypt data locally in
// your application. You can write your own code or use a client-side encryption
// library, such as the Amazon Web Services Encryption SDK (https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/),
// the Amazon DynamoDB Encryption Client (https://docs.aws.amazon.com/dynamodb-encryption-client/latest/devguide/),
// or Amazon S3 client-side encryption (https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html)
// to do these tasks for you.
//
// To encrypt data outside of KMS:
//
// Use the GenerateDataKey operation to get a data key.
//
// Use the plaintext data key (in the Plaintext field of the response) to encrypt
// your data outside of KMS. Then erase the plaintext data key from memory.
//
// Store the encrypted data key (in the CiphertextBlob field of the response)
// with the encrypted data.
//
// To decrypt data outside of KMS:
//
// Use the Decrypt operation to decrypt the encrypted data key. The operation
// returns a plaintext copy of the data key.
//
// Use the plaintext data key to decrypt data outside of KMS, then erase the
// plaintext data key from memory.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GenerateDataKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Decrypt
//
// * Encrypt
//
// * GenerateDataKeyPair
//
// * GenerateDataKeyPairWithoutPlaintext
//
// * GenerateDataKeyWithoutPlaintext
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateDataKey for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKey
func (c *KMS) GenerateDataKey(input *GenerateDataKeyInput) (*GenerateDataKeyOutput, error) {
req, out := c.GenerateDataKeyRequest(input)
return out, req.Send()
}
// GenerateDataKeyWithContext is the same as GenerateDataKey with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateDataKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateDataKeyWithContext(ctx aws.Context, input *GenerateDataKeyInput, opts ...request.Option) (*GenerateDataKeyOutput, error) {
req, out := c.GenerateDataKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateDataKeyPair = "GenerateDataKeyPair"
// GenerateDataKeyPairRequest generates a "aws/request.Request" representing the
// client's request for the GenerateDataKeyPair operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateDataKeyPair for more information on using the GenerateDataKeyPair
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateDataKeyPairRequest method.
// req, resp := client.GenerateDataKeyPairRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyPair
func (c *KMS) GenerateDataKeyPairRequest(input *GenerateDataKeyPairInput) (req *request.Request, output *GenerateDataKeyPairOutput) {
op := &request.Operation{
Name: opGenerateDataKeyPair,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateDataKeyPairInput{}
}
output = &GenerateDataKeyPairOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateDataKeyPair API operation for AWS Key Management Service.
//
// Returns a unique asymmetric data key pair for use outside of KMS. This operation
// returns a plaintext public key, a plaintext private key, and a copy of the
// private key that is encrypted under the symmetric encryption KMS key you
// specify. You can use the data key pair to perform asymmetric cryptography
// and implement digital signatures outside of KMS. The bytes in the keys are
// random; they not related to the caller or to the KMS key that is used to
// encrypt the private key.
//
// You can use the public key that GenerateDataKeyPair returns to encrypt data
// or verify a signature outside of KMS. Then, store the encrypted private key
// with the data. When you are ready to decrypt data or sign a message, you
// can use the Decrypt operation to decrypt the encrypted private key.
//
// To generate a data key pair, you must specify a symmetric encryption KMS
// key to encrypt the private key in a data key pair. You cannot use an asymmetric
// KMS key or a KMS key in a custom key store. To get the type and origin of
// your KMS key, use the DescribeKey operation.
//
// Use the KeyPairSpec parameter to choose an RSA or Elliptic Curve (ECC) data
// key pair. KMS recommends that your use ECC key pairs for signing, and use
// RSA key pairs for either encryption or signing, but not both. However, KMS
// cannot enforce any restrictions on the use of data key pairs outside of KMS.
//
// If you are using the data key pair to encrypt data, or for any operation
// where you don't immediately need a private key, consider using the GenerateDataKeyPairWithoutPlaintext
// operation. GenerateDataKeyPairWithoutPlaintext returns a plaintext public
// key and an encrypted private key, but omits the plaintext private key that
// you need only to decrypt ciphertext or sign a message. Later, when you need
// to decrypt the data or sign a message, use the Decrypt operation to decrypt
// the encrypted private key in the data key pair.
//
// GenerateDataKeyPair returns a unique data key pair for each request. The
// bytes in the keys are random; they are not related to the caller or the KMS
// key that is used to encrypt the private key. The public key is a DER-encoded
// X.509 SubjectPublicKeyInfo, as specified in RFC 5280 (https://tools.ietf.org/html/rfc5280).
// The private key is a DER-encoded PKCS8 PrivateKeyInfo, as specified in RFC
// 5958 (https://tools.ietf.org/html/rfc5958).
//
// You can use an optional encryption context to add additional security to
// the encryption operation. If you specify an EncryptionContext, you must specify
// the same encryption context (a case-sensitive exact match) when decrypting
// the encrypted data key. Otherwise, the request to decrypt fails with an InvalidCiphertextException.
// For more information, see Encryption Context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GenerateDataKeyPair (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Decrypt
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPairWithoutPlaintext
//
// * GenerateDataKeyWithoutPlaintext
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateDataKeyPair for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyPair
func (c *KMS) GenerateDataKeyPair(input *GenerateDataKeyPairInput) (*GenerateDataKeyPairOutput, error) {
req, out := c.GenerateDataKeyPairRequest(input)
return out, req.Send()
}
// GenerateDataKeyPairWithContext is the same as GenerateDataKeyPair with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateDataKeyPair for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateDataKeyPairWithContext(ctx aws.Context, input *GenerateDataKeyPairInput, opts ...request.Option) (*GenerateDataKeyPairOutput, error) {
req, out := c.GenerateDataKeyPairRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateDataKeyPairWithoutPlaintext = "GenerateDataKeyPairWithoutPlaintext"
// GenerateDataKeyPairWithoutPlaintextRequest generates a "aws/request.Request" representing the
// client's request for the GenerateDataKeyPairWithoutPlaintext operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateDataKeyPairWithoutPlaintext for more information on using the GenerateDataKeyPairWithoutPlaintext
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateDataKeyPairWithoutPlaintextRequest method.
// req, resp := client.GenerateDataKeyPairWithoutPlaintextRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyPairWithoutPlaintext
func (c *KMS) GenerateDataKeyPairWithoutPlaintextRequest(input *GenerateDataKeyPairWithoutPlaintextInput) (req *request.Request, output *GenerateDataKeyPairWithoutPlaintextOutput) {
op := &request.Operation{
Name: opGenerateDataKeyPairWithoutPlaintext,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateDataKeyPairWithoutPlaintextInput{}
}
output = &GenerateDataKeyPairWithoutPlaintextOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateDataKeyPairWithoutPlaintext API operation for AWS Key Management Service.
//
// Returns a unique asymmetric data key pair for use outside of KMS. This operation
// returns a plaintext public key and a copy of the private key that is encrypted
// under the symmetric encryption KMS key you specify. Unlike GenerateDataKeyPair,
// this operation does not return a plaintext private key. The bytes in the
// keys are random; they are not related to the caller or to the KMS key that
// is used to encrypt the private key.
//
// You can use the public key that GenerateDataKeyPairWithoutPlaintext returns
// to encrypt data or verify a signature outside of KMS. Then, store the encrypted
// private key with the data. When you are ready to decrypt data or sign a message,
// you can use the Decrypt operation to decrypt the encrypted private key.
//
// To generate a data key pair, you must specify a symmetric encryption KMS
// key to encrypt the private key in a data key pair. You cannot use an asymmetric
// KMS key or a KMS key in a custom key store. To get the type and origin of
// your KMS key, use the DescribeKey operation.
//
// Use the KeyPairSpec parameter to choose an RSA or Elliptic Curve (ECC) data
// key pair. KMS recommends that your use ECC key pairs for signing, and use
// RSA key pairs for either encryption or signing, but not both. However, KMS
// cannot enforce any restrictions on the use of data key pairs outside of KMS.
//
// GenerateDataKeyPairWithoutPlaintext returns a unique data key pair for each
// request. The bytes in the key are not related to the caller or KMS key that
// is used to encrypt the private key. The public key is a DER-encoded X.509
// SubjectPublicKeyInfo, as specified in RFC 5280 (https://tools.ietf.org/html/rfc5280).
//
// You can use an optional encryption context to add additional security to
// the encryption operation. If you specify an EncryptionContext, you must specify
// the same encryption context (a case-sensitive exact match) when decrypting
// the encrypted data key. Otherwise, the request to decrypt fails with an InvalidCiphertextException.
// For more information, see Encryption Context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GenerateDataKeyPairWithoutPlaintext (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Decrypt
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// * GenerateDataKeyWithoutPlaintext
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateDataKeyPairWithoutPlaintext for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyPairWithoutPlaintext
func (c *KMS) GenerateDataKeyPairWithoutPlaintext(input *GenerateDataKeyPairWithoutPlaintextInput) (*GenerateDataKeyPairWithoutPlaintextOutput, error) {
req, out := c.GenerateDataKeyPairWithoutPlaintextRequest(input)
return out, req.Send()
}
// GenerateDataKeyPairWithoutPlaintextWithContext is the same as GenerateDataKeyPairWithoutPlaintext with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateDataKeyPairWithoutPlaintext for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateDataKeyPairWithoutPlaintextWithContext(ctx aws.Context, input *GenerateDataKeyPairWithoutPlaintextInput, opts ...request.Option) (*GenerateDataKeyPairWithoutPlaintextOutput, error) {
req, out := c.GenerateDataKeyPairWithoutPlaintextRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateDataKeyWithoutPlaintext = "GenerateDataKeyWithoutPlaintext"
// GenerateDataKeyWithoutPlaintextRequest generates a "aws/request.Request" representing the
// client's request for the GenerateDataKeyWithoutPlaintext operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateDataKeyWithoutPlaintext for more information on using the GenerateDataKeyWithoutPlaintext
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateDataKeyWithoutPlaintextRequest method.
// req, resp := client.GenerateDataKeyWithoutPlaintextRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyWithoutPlaintext
func (c *KMS) GenerateDataKeyWithoutPlaintextRequest(input *GenerateDataKeyWithoutPlaintextInput) (req *request.Request, output *GenerateDataKeyWithoutPlaintextOutput) {
op := &request.Operation{
Name: opGenerateDataKeyWithoutPlaintext,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateDataKeyWithoutPlaintextInput{}
}
output = &GenerateDataKeyWithoutPlaintextOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateDataKeyWithoutPlaintext API operation for AWS Key Management Service.
//
// Returns a unique symmetric data key for use outside of KMS. This operation
// returns a data key that is encrypted under a symmetric encryption KMS key
// that you specify. The bytes in the key are random; they are not related to
// the caller or to the KMS key.
//
// GenerateDataKeyWithoutPlaintext is identical to the GenerateDataKey operation
// except that it does not return a plaintext copy of the data key.
//
// This operation is useful for systems that need to encrypt data at some point,
// but not immediately. When you need to encrypt the data, you call the Decrypt
// operation on the encrypted copy of the key. It's also useful in distributed
// systems with different levels of trust. For example, you might store encrypted
// data in containers. One component of your system creates new containers and
// stores an encrypted data key with each container. Then, a different component
// puts the data into the containers. That component first decrypts the data
// key, uses the plaintext data key to encrypt data, puts the encrypted data
// into the container, and then destroys the plaintext data key. In this system,
// the component that creates the containers never sees the plaintext data key.
//
// To request an asymmetric data key pair, use the GenerateDataKeyPair or GenerateDataKeyPairWithoutPlaintext
// operations.
//
// To generate a data key, you must specify the symmetric encryption KMS key
// that is used to encrypt the data key. You cannot use an asymmetric KMS key
// or a key in a custom key store to generate a data key. To get the type of
// your KMS key, use the DescribeKey operation.
//
// If the operation succeeds, you will find the encrypted copy of the data key
// in the CiphertextBlob field.
//
// You can use an optional encryption context to add additional security to
// the encryption operation. If you specify an EncryptionContext, you must specify
// the same encryption context (a case-sensitive exact match) when decrypting
// the encrypted data key. Otherwise, the request to decrypt fails with an InvalidCiphertextException.
// For more information, see Encryption Context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GenerateDataKeyWithoutPlaintext (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * Decrypt
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// * GenerateDataKeyPairWithoutPlaintext
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateDataKeyWithoutPlaintext for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateDataKeyWithoutPlaintext
func (c *KMS) GenerateDataKeyWithoutPlaintext(input *GenerateDataKeyWithoutPlaintextInput) (*GenerateDataKeyWithoutPlaintextOutput, error) {
req, out := c.GenerateDataKeyWithoutPlaintextRequest(input)
return out, req.Send()
}
// GenerateDataKeyWithoutPlaintextWithContext is the same as GenerateDataKeyWithoutPlaintext with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateDataKeyWithoutPlaintext for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateDataKeyWithoutPlaintextWithContext(ctx aws.Context, input *GenerateDataKeyWithoutPlaintextInput, opts ...request.Option) (*GenerateDataKeyWithoutPlaintextOutput, error) {
req, out := c.GenerateDataKeyWithoutPlaintextRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateMac = "GenerateMac"
// GenerateMacRequest generates a "aws/request.Request" representing the
// client's request for the GenerateMac operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateMac for more information on using the GenerateMac
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateMacRequest method.
// req, resp := client.GenerateMacRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateMac
func (c *KMS) GenerateMacRequest(input *GenerateMacInput) (req *request.Request, output *GenerateMacOutput) {
op := &request.Operation{
Name: opGenerateMac,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateMacInput{}
}
output = &GenerateMacOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateMac API operation for AWS Key Management Service.
//
// Generates a hash-based message authentication code (HMAC) for a message using
// an HMAC KMS key and a MAC algorithm that the key supports. The MAC algorithm
// computes the HMAC for the message and the key as described in RFC 2104 (https://datatracker.ietf.org/doc/html/rfc2104).
//
// You can use the HMAC that this operation generates with the VerifyMac operation
// to demonstrate that the original message has not changed. Also, because a
// secret key is used to create the hash, you can verify that the party that
// generated the hash has the required secret key. This operation is part of
// KMS support for HMAC KMS keys. For details, see HMAC keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html)
// in the Key Management Service Developer Guide .
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GenerateMac (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: VerifyMac
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateMac for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateMac
func (c *KMS) GenerateMac(input *GenerateMacInput) (*GenerateMacOutput, error) {
req, out := c.GenerateMacRequest(input)
return out, req.Send()
}
// GenerateMacWithContext is the same as GenerateMac with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateMac for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateMacWithContext(ctx aws.Context, input *GenerateMacInput, opts ...request.Option) (*GenerateMacOutput, error) {
req, out := c.GenerateMacRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGenerateRandom = "GenerateRandom"
// GenerateRandomRequest generates a "aws/request.Request" representing the
// client's request for the GenerateRandom operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GenerateRandom for more information on using the GenerateRandom
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GenerateRandomRequest method.
// req, resp := client.GenerateRandomRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateRandom
func (c *KMS) GenerateRandomRequest(input *GenerateRandomInput) (req *request.Request, output *GenerateRandomOutput) {
op := &request.Operation{
Name: opGenerateRandom,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GenerateRandomInput{}
}
output = &GenerateRandomOutput{}
req = c.newRequest(op, input, output)
return
}
// GenerateRandom API operation for AWS Key Management Service.
//
// Returns a random byte string that is cryptographically secure.
//
// By default, the random byte string is generated in KMS. To generate the byte
// string in the CloudHSM cluster that is associated with a custom key store
// (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html),
// specify the custom key store ID.
//
// Applications in Amazon Web Services Nitro Enclaves can call this operation
// by using the Amazon Web Services Nitro Enclaves Development Kit (https://github.com/aws/aws-nitro-enclaves-sdk-c).
// For information about the supporting parameters, see How Amazon Web Services
// Nitro Enclaves use KMS (https://docs.aws.amazon.com/kms/latest/developerguide/services-nitro-enclaves.html)
// in the Key Management Service Developer Guide.
//
// For more information about entropy and random number generation, see Key
// Management Service Cryptographic Details (https://docs.aws.amazon.com/kms/latest/cryptographic-details/).
//
// Required permissions: kms:GenerateRandom (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GenerateRandom for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GenerateRandom
func (c *KMS) GenerateRandom(input *GenerateRandomInput) (*GenerateRandomOutput, error) {
req, out := c.GenerateRandomRequest(input)
return out, req.Send()
}
// GenerateRandomWithContext is the same as GenerateRandom with the addition of
// the ability to pass a context and additional request options.
//
// See GenerateRandom for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GenerateRandomWithContext(ctx aws.Context, input *GenerateRandomInput, opts ...request.Option) (*GenerateRandomOutput, error) {
req, out := c.GenerateRandomRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetKeyPolicy = "GetKeyPolicy"
// GetKeyPolicyRequest generates a "aws/request.Request" representing the
// client's request for the GetKeyPolicy operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetKeyPolicy for more information on using the GetKeyPolicy
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetKeyPolicyRequest method.
// req, resp := client.GetKeyPolicyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetKeyPolicy
func (c *KMS) GetKeyPolicyRequest(input *GetKeyPolicyInput) (req *request.Request, output *GetKeyPolicyOutput) {
op := &request.Operation{
Name: opGetKeyPolicy,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetKeyPolicyInput{}
}
output = &GetKeyPolicyOutput{}
req = c.newRequest(op, input, output)
return
}
// GetKeyPolicy API operation for AWS Key Management Service.
//
// Gets a key policy attached to the specified KMS key.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:GetKeyPolicy (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: PutKeyPolicy
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GetKeyPolicy for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetKeyPolicy
func (c *KMS) GetKeyPolicy(input *GetKeyPolicyInput) (*GetKeyPolicyOutput, error) {
req, out := c.GetKeyPolicyRequest(input)
return out, req.Send()
}
// GetKeyPolicyWithContext is the same as GetKeyPolicy with the addition of
// the ability to pass a context and additional request options.
//
// See GetKeyPolicy for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GetKeyPolicyWithContext(ctx aws.Context, input *GetKeyPolicyInput, opts ...request.Option) (*GetKeyPolicyOutput, error) {
req, out := c.GetKeyPolicyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetKeyRotationStatus = "GetKeyRotationStatus"
// GetKeyRotationStatusRequest generates a "aws/request.Request" representing the
// client's request for the GetKeyRotationStatus operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetKeyRotationStatus for more information on using the GetKeyRotationStatus
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetKeyRotationStatusRequest method.
// req, resp := client.GetKeyRotationStatusRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetKeyRotationStatus
func (c *KMS) GetKeyRotationStatusRequest(input *GetKeyRotationStatusInput) (req *request.Request, output *GetKeyRotationStatusOutput) {
op := &request.Operation{
Name: opGetKeyRotationStatus,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetKeyRotationStatusInput{}
}
output = &GetKeyRotationStatusOutput{}
req = c.newRequest(op, input, output)
return
}
// GetKeyRotationStatus API operation for AWS Key Management Service.
//
// Gets a Boolean value that indicates whether automatic rotation of the key
// material (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html)
// is enabled for the specified KMS key.
//
// You cannot enable automatic rotation of asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html),
// HMAC KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html),
// KMS keys with imported key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html),
// or KMS keys in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// To enable or disable automatic rotation of a set of related multi-Region
// keys (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-manage.html#multi-region-rotate),
// set the property on the primary key. The key rotation status for these KMS
// keys is always false.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// * Disabled: The key rotation status does not change when you disable a
// KMS key. However, while the KMS key is disabled, KMS does not rotate the
// key material.
//
// * Pending deletion: While a KMS key is pending deletion, its key rotation
// status is false and KMS does not rotate the key material. If you cancel
// the deletion, the original key rotation status is restored.
//
// Cross-account use: Yes. To perform this operation on a KMS key in a different
// Amazon Web Services account, specify the key ARN in the value of the KeyId
// parameter.
//
// Required permissions: kms:GetKeyRotationStatus (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * DisableKeyRotation
//
// * EnableKeyRotation
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GetKeyRotationStatus for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetKeyRotationStatus
func (c *KMS) GetKeyRotationStatus(input *GetKeyRotationStatusInput) (*GetKeyRotationStatusOutput, error) {
req, out := c.GetKeyRotationStatusRequest(input)
return out, req.Send()
}
// GetKeyRotationStatusWithContext is the same as GetKeyRotationStatus with the addition of
// the ability to pass a context and additional request options.
//
// See GetKeyRotationStatus for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GetKeyRotationStatusWithContext(ctx aws.Context, input *GetKeyRotationStatusInput, opts ...request.Option) (*GetKeyRotationStatusOutput, error) {
req, out := c.GetKeyRotationStatusRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetParametersForImport = "GetParametersForImport"
// GetParametersForImportRequest generates a "aws/request.Request" representing the
// client's request for the GetParametersForImport operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetParametersForImport for more information on using the GetParametersForImport
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetParametersForImportRequest method.
// req, resp := client.GetParametersForImportRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetParametersForImport
func (c *KMS) GetParametersForImportRequest(input *GetParametersForImportInput) (req *request.Request, output *GetParametersForImportOutput) {
op := &request.Operation{
Name: opGetParametersForImport,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetParametersForImportInput{}
}
output = &GetParametersForImportOutput{}
req = c.newRequest(op, input, output)
return
}
// GetParametersForImport API operation for AWS Key Management Service.
//
// Returns the items you need to import key material into a symmetric encryption
// KMS key. For more information about importing key material into KMS, see
// Importing key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)
// in the Key Management Service Developer Guide.
//
// This operation returns a public key and an import token. Use the public key
// to encrypt the symmetric key material. Store the import token to send with
// a subsequent ImportKeyMaterial request.
//
// You must specify the key ID of the symmetric encryption KMS key into which
// you will import key material. This KMS key's Origin must be EXTERNAL. You
// must also specify the wrapping algorithm and type of wrapping key (public
// key) that you will use to encrypt the key material. You cannot perform this
// operation on an asymmetric KMS key, an HMAC KMS key, or on any KMS key in
// a different Amazon Web Services account.
//
// To import key material, you must use the public key and import token from
// the same response. These items are valid for 24 hours. The expiration date
// and time appear in the GetParametersForImport response. You cannot use an
// expired token in an ImportKeyMaterial request. If your key and token expire,
// send another GetParametersForImport request.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:GetParametersForImport (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * ImportKeyMaterial
//
// * DeleteImportedKeyMaterial
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GetParametersForImport for usage and error information.
//
// Returned Error Types:
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetParametersForImport
func (c *KMS) GetParametersForImport(input *GetParametersForImportInput) (*GetParametersForImportOutput, error) {
req, out := c.GetParametersForImportRequest(input)
return out, req.Send()
}
// GetParametersForImportWithContext is the same as GetParametersForImport with the addition of
// the ability to pass a context and additional request options.
//
// See GetParametersForImport for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GetParametersForImportWithContext(ctx aws.Context, input *GetParametersForImportInput, opts ...request.Option) (*GetParametersForImportOutput, error) {
req, out := c.GetParametersForImportRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetPublicKey = "GetPublicKey"
// GetPublicKeyRequest generates a "aws/request.Request" representing the
// client's request for the GetPublicKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetPublicKey for more information on using the GetPublicKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetPublicKeyRequest method.
// req, resp := client.GetPublicKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetPublicKey
func (c *KMS) GetPublicKeyRequest(input *GetPublicKeyInput) (req *request.Request, output *GetPublicKeyOutput) {
op := &request.Operation{
Name: opGetPublicKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetPublicKeyInput{}
}
output = &GetPublicKeyOutput{}
req = c.newRequest(op, input, output)
return
}
// GetPublicKey API operation for AWS Key Management Service.
//
// Returns the public key of an asymmetric KMS key. Unlike the private key of
// a asymmetric KMS key, which never leaves KMS unencrypted, callers with kms:GetPublicKey
// permission can download the public key of an asymmetric KMS key. You can
// share the public key to allow others to encrypt messages and verify signatures
// outside of KMS. For information about asymmetric KMS keys, see Asymmetric
// KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
// in the Key Management Service Developer Guide.
//
// You do not need to download the public key. Instead, you can use the public
// key within KMS by calling the Encrypt, ReEncrypt, or Verify operations with
// the identifier of an asymmetric KMS key. When you use the public key within
// KMS, you benefit from the authentication, authorization, and logging that
// are part of every KMS operation. You also reduce of risk of encrypting data
// that cannot be decrypted. These features are not effective outside of KMS.
// For details, see Special Considerations for Downloading Public Keys (https://docs.aws.amazon.com/kms/latest/developerguide/download-public-key.html#download-public-key-considerations).
//
// To help you use the public key safely outside of KMS, GetPublicKey returns
// important information about the public key in the response, including:
//
// * KeySpec (https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html#KMS-GetPublicKey-response-KeySpec):
// The type of key material in the public key, such as RSA_4096 or ECC_NIST_P521.
//
// * KeyUsage (https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html#KMS-GetPublicKey-response-KeyUsage):
// Whether the key is used for encryption or signing.
//
// * EncryptionAlgorithms (https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html#KMS-GetPublicKey-response-EncryptionAlgorithms)
// or SigningAlgorithms (https://docs.aws.amazon.com/kms/latest/APIReference/API_GetPublicKey.html#KMS-GetPublicKey-response-SigningAlgorithms):
// A list of the encryption algorithms or the signing algorithms for the
// key.
//
// Although KMS cannot enforce these restrictions on external operations, it
// is crucial that you use this information to prevent the public key from being
// used improperly. For example, you can prevent a public signing key from being
// used encrypt data, or prevent a public key from being used with an encryption
// algorithm that is not supported by KMS. You can also avoid errors, such as
// using the wrong signing algorithm in a verification operation.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:GetPublicKey (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: CreateKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation GetPublicKey for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/GetPublicKey
func (c *KMS) GetPublicKey(input *GetPublicKeyInput) (*GetPublicKeyOutput, error) {
req, out := c.GetPublicKeyRequest(input)
return out, req.Send()
}
// GetPublicKeyWithContext is the same as GetPublicKey with the addition of
// the ability to pass a context and additional request options.
//
// See GetPublicKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) GetPublicKeyWithContext(ctx aws.Context, input *GetPublicKeyInput, opts ...request.Option) (*GetPublicKeyOutput, error) {
req, out := c.GetPublicKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opImportKeyMaterial = "ImportKeyMaterial"
// ImportKeyMaterialRequest generates a "aws/request.Request" representing the
// client's request for the ImportKeyMaterial operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ImportKeyMaterial for more information on using the ImportKeyMaterial
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ImportKeyMaterialRequest method.
// req, resp := client.ImportKeyMaterialRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ImportKeyMaterial
func (c *KMS) ImportKeyMaterialRequest(input *ImportKeyMaterialInput) (req *request.Request, output *ImportKeyMaterialOutput) {
op := &request.Operation{
Name: opImportKeyMaterial,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ImportKeyMaterialInput{}
}
output = &ImportKeyMaterialOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// ImportKeyMaterial API operation for AWS Key Management Service.
//
// Imports key material into an existing symmetric encryption KMS key that was
// created without key material. After you successfully import key material
// into a KMS key, you can reimport the same key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html#reimport-key-material)
// into that KMS key, but you cannot import different key material.
//
// You cannot perform this operation on an asymmetric KMS key, an HMAC KMS key,
// or on any KMS key in a different Amazon Web Services account. For more information
// about creating KMS keys with no key material and then importing key material,
// see Importing Key Material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)
// in the Key Management Service Developer Guide.
//
// Before using this operation, call GetParametersForImport. Its response includes
// a public key and an import token. Use the public key to encrypt the key material.
// Then, submit the import token from the same GetParametersForImport response.
//
// When calling this operation, you must specify the following values:
//
// * The key ID or key ARN of a KMS key with no key material. Its Origin
// must be EXTERNAL. To create a KMS key with no key material, call CreateKey
// and set the value of its Origin parameter to EXTERNAL. To get the Origin
// of a KMS key, call DescribeKey.)
//
// * The encrypted key material. To get the public key to encrypt the key
// material, call GetParametersForImport.
//
// * The import token that GetParametersForImport returned. You must use
// a public key and token from the same GetParametersForImport response.
//
// * Whether the key material expires and if so, when. If you set an expiration
// date, KMS deletes the key material from the KMS key on the specified date,
// and the KMS key becomes unusable. To use the KMS key again, you must reimport
// the same key material. The only way to change an expiration date is by
// reimporting the same key material and specifying a new expiration date.
//
// When this operation is successful, the key state of the KMS key changes from
// PendingImport to Enabled, and you can use the KMS key.
//
// If this operation fails, use the exception to help determine the problem.
// If the error is related to the key material, the import token, or wrapping
// key, use GetParametersForImport to get a new public key and import token
// for the KMS key and repeat the import procedure. For help, see How To Import
// Key Material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html#importing-keys-overview)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:ImportKeyMaterial (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * DeleteImportedKeyMaterial
//
// * GetParametersForImport
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ImportKeyMaterial for usage and error information.
//
// Returned Error Types:
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * InvalidCiphertextException
// From the Decrypt or ReEncrypt operation, the request was rejected because
// the specified ciphertext, or additional authenticated data incorporated into
// the ciphertext, such as the encryption context, is corrupted, missing, or
// otherwise invalid.
//
// From the ImportKeyMaterial operation, the request was rejected because KMS
// could not decrypt the encrypted (wrapped) key material.
//
// * IncorrectKeyMaterialException
// The request was rejected because the key material in the request is, expired,
// invalid, or is not the same key material that was previously imported into
// this KMS key.
//
// * ExpiredImportTokenException
// The request was rejected because the specified import token is expired. Use
// GetParametersForImport to get a new import token and public key, use the
// new public key to encrypt the key material, and then try the request again.
//
// * InvalidImportTokenException
// The request was rejected because the provided import token is invalid or
// is associated with a different KMS key.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ImportKeyMaterial
func (c *KMS) ImportKeyMaterial(input *ImportKeyMaterialInput) (*ImportKeyMaterialOutput, error) {
req, out := c.ImportKeyMaterialRequest(input)
return out, req.Send()
}
// ImportKeyMaterialWithContext is the same as ImportKeyMaterial with the addition of
// the ability to pass a context and additional request options.
//
// See ImportKeyMaterial for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ImportKeyMaterialWithContext(ctx aws.Context, input *ImportKeyMaterialInput, opts ...request.Option) (*ImportKeyMaterialOutput, error) {
req, out := c.ImportKeyMaterialRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opListAliases = "ListAliases"
// ListAliasesRequest generates a "aws/request.Request" representing the
// client's request for the ListAliases operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListAliases for more information on using the ListAliases
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListAliasesRequest method.
// req, resp := client.ListAliasesRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListAliases
func (c *KMS) ListAliasesRequest(input *ListAliasesInput) (req *request.Request, output *ListAliasesOutput) {
op := &request.Operation{
Name: opListAliases,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"Marker"},
OutputTokens: []string{"NextMarker"},
LimitToken: "Limit",
TruncationToken: "Truncated",
},
}
if input == nil {
input = &ListAliasesInput{}
}
output = &ListAliasesOutput{}
req = c.newRequest(op, input, output)
return
}
// ListAliases API operation for AWS Key Management Service.
//
// Gets a list of aliases in the caller's Amazon Web Services account and region.
// For more information about aliases, see CreateAlias.
//
// By default, the ListAliases operation returns all aliases in the account
// and region. To get only the aliases associated with a particular KMS key,
// use the KeyId parameter.
//
// The ListAliases response can include aliases that you created and associated
// with your customer managed keys, and aliases that Amazon Web Services created
// and associated with Amazon Web Services managed keys in your account. You
// can recognize Amazon Web Services aliases because their names have the format
// aws/, such as aws/dynamodb.
//
// The response might also include aliases that have no TargetKeyId field. These
// are predefined aliases that Amazon Web Services has created but has not yet
// associated with a KMS key. Aliases that Amazon Web Services creates in your
// account, including predefined aliases, do not count against your KMS aliases
// quota (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html#aliases-limit).
//
// Cross-account use: No. ListAliases does not return aliases in other Amazon
// Web Services accounts.
//
// Required permissions: kms:ListAliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// For details, see Controlling access to aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html#alias-access)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * CreateAlias
//
// * DeleteAlias
//
// * UpdateAlias
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListAliases for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListAliases
func (c *KMS) ListAliases(input *ListAliasesInput) (*ListAliasesOutput, error) {
req, out := c.ListAliasesRequest(input)
return out, req.Send()
}
// ListAliasesWithContext is the same as ListAliases with the addition of
// the ability to pass a context and additional request options.
//
// See ListAliases for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListAliasesWithContext(ctx aws.Context, input *ListAliasesInput, opts ...request.Option) (*ListAliasesOutput, error) {
req, out := c.ListAliasesRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListAliasesPages iterates over the pages of a ListAliases operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListAliases method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListAliases operation.
// pageNum := 0
// err := client.ListAliasesPages(params,
// func(page *kms.ListAliasesOutput, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *KMS) ListAliasesPages(input *ListAliasesInput, fn func(*ListAliasesOutput, bool) bool) error {
return c.ListAliasesPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListAliasesPagesWithContext same as ListAliasesPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListAliasesPagesWithContext(ctx aws.Context, input *ListAliasesInput, fn func(*ListAliasesOutput, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListAliasesInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListAliasesRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListAliasesOutput), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opListGrants = "ListGrants"
// ListGrantsRequest generates a "aws/request.Request" representing the
// client's request for the ListGrants operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListGrants for more information on using the ListGrants
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListGrantsRequest method.
// req, resp := client.ListGrantsRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListGrants
func (c *KMS) ListGrantsRequest(input *ListGrantsInput) (req *request.Request, output *ListGrantsResponse) {
op := &request.Operation{
Name: opListGrants,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"Marker"},
OutputTokens: []string{"NextMarker"},
LimitToken: "Limit",
TruncationToken: "Truncated",
},
}
if input == nil {
input = &ListGrantsInput{}
}
output = &ListGrantsResponse{}
req = c.newRequest(op, input, output)
return
}
// ListGrants API operation for AWS Key Management Service.
//
// Gets a list of all grants for the specified KMS key.
//
// You must specify the KMS key in all requests. You can filter the grant list
// by grant ID or grantee principal.
//
// For detailed information about grants, including grant terminology, see Grants
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)
// in the Key Management Service Developer Guide . For examples of working with
// grants in several programming languages, see Programming grants (https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html).
//
// The GranteePrincipal field in the ListGrants response usually contains the
// user or role designated as the grantee principal in the grant. However, when
// the grantee principal in the grant is an Amazon Web Services service, the
// GranteePrincipal field contains the service principal (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-services),
// which might represent several different grantee principals.
//
// Cross-account use: Yes. To perform this operation on a KMS key in a different
// Amazon Web Services account, specify the key ARN in the value of the KeyId
// parameter.
//
// Required permissions: kms:ListGrants (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * CreateGrant
//
// * ListRetirableGrants
//
// * RetireGrant
//
// * RevokeGrant
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListGrants for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// * InvalidGrantIdException
// The request was rejected because the specified GrantId is not valid.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListGrants
func (c *KMS) ListGrants(input *ListGrantsInput) (*ListGrantsResponse, error) {
req, out := c.ListGrantsRequest(input)
return out, req.Send()
}
// ListGrantsWithContext is the same as ListGrants with the addition of
// the ability to pass a context and additional request options.
//
// See ListGrants for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListGrantsWithContext(ctx aws.Context, input *ListGrantsInput, opts ...request.Option) (*ListGrantsResponse, error) {
req, out := c.ListGrantsRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListGrantsPages iterates over the pages of a ListGrants operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListGrants method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListGrants operation.
// pageNum := 0
// err := client.ListGrantsPages(params,
// func(page *kms.ListGrantsResponse, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *KMS) ListGrantsPages(input *ListGrantsInput, fn func(*ListGrantsResponse, bool) bool) error {
return c.ListGrantsPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListGrantsPagesWithContext same as ListGrantsPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListGrantsPagesWithContext(ctx aws.Context, input *ListGrantsInput, fn func(*ListGrantsResponse, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListGrantsInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListGrantsRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListGrantsResponse), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opListKeyPolicies = "ListKeyPolicies"
// ListKeyPoliciesRequest generates a "aws/request.Request" representing the
// client's request for the ListKeyPolicies operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListKeyPolicies for more information on using the ListKeyPolicies
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListKeyPoliciesRequest method.
// req, resp := client.ListKeyPoliciesRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListKeyPolicies
func (c *KMS) ListKeyPoliciesRequest(input *ListKeyPoliciesInput) (req *request.Request, output *ListKeyPoliciesOutput) {
op := &request.Operation{
Name: opListKeyPolicies,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"Marker"},
OutputTokens: []string{"NextMarker"},
LimitToken: "Limit",
TruncationToken: "Truncated",
},
}
if input == nil {
input = &ListKeyPoliciesInput{}
}
output = &ListKeyPoliciesOutput{}
req = c.newRequest(op, input, output)
return
}
// ListKeyPolicies API operation for AWS Key Management Service.
//
// Gets the names of the key policies that are attached to a KMS key. This operation
// is designed to get policy names that you can use in a GetKeyPolicy operation.
// However, the only valid policy name is default.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:ListKeyPolicies (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * GetKeyPolicy
//
// * PutKeyPolicy
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListKeyPolicies for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListKeyPolicies
func (c *KMS) ListKeyPolicies(input *ListKeyPoliciesInput) (*ListKeyPoliciesOutput, error) {
req, out := c.ListKeyPoliciesRequest(input)
return out, req.Send()
}
// ListKeyPoliciesWithContext is the same as ListKeyPolicies with the addition of
// the ability to pass a context and additional request options.
//
// See ListKeyPolicies for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListKeyPoliciesWithContext(ctx aws.Context, input *ListKeyPoliciesInput, opts ...request.Option) (*ListKeyPoliciesOutput, error) {
req, out := c.ListKeyPoliciesRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListKeyPoliciesPages iterates over the pages of a ListKeyPolicies operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListKeyPolicies method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListKeyPolicies operation.
// pageNum := 0
// err := client.ListKeyPoliciesPages(params,
// func(page *kms.ListKeyPoliciesOutput, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *KMS) ListKeyPoliciesPages(input *ListKeyPoliciesInput, fn func(*ListKeyPoliciesOutput, bool) bool) error {
return c.ListKeyPoliciesPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListKeyPoliciesPagesWithContext same as ListKeyPoliciesPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListKeyPoliciesPagesWithContext(ctx aws.Context, input *ListKeyPoliciesInput, fn func(*ListKeyPoliciesOutput, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListKeyPoliciesInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListKeyPoliciesRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListKeyPoliciesOutput), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opListKeys = "ListKeys"
// ListKeysRequest generates a "aws/request.Request" representing the
// client's request for the ListKeys operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListKeys for more information on using the ListKeys
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListKeysRequest method.
// req, resp := client.ListKeysRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListKeys
func (c *KMS) ListKeysRequest(input *ListKeysInput) (req *request.Request, output *ListKeysOutput) {
op := &request.Operation{
Name: opListKeys,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"Marker"},
OutputTokens: []string{"NextMarker"},
LimitToken: "Limit",
TruncationToken: "Truncated",
},
}
if input == nil {
input = &ListKeysInput{}
}
output = &ListKeysOutput{}
req = c.newRequest(op, input, output)
return
}
// ListKeys API operation for AWS Key Management Service.
//
// Gets a list of all KMS keys in the caller's Amazon Web Services account and
// Region.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:ListKeys (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations:
//
// * CreateKey
//
// * DescribeKey
//
// * ListAliases
//
// * ListResourceTags
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListKeys for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListKeys
func (c *KMS) ListKeys(input *ListKeysInput) (*ListKeysOutput, error) {
req, out := c.ListKeysRequest(input)
return out, req.Send()
}
// ListKeysWithContext is the same as ListKeys with the addition of
// the ability to pass a context and additional request options.
//
// See ListKeys for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListKeysWithContext(ctx aws.Context, input *ListKeysInput, opts ...request.Option) (*ListKeysOutput, error) {
req, out := c.ListKeysRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListKeysPages iterates over the pages of a ListKeys operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListKeys method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListKeys operation.
// pageNum := 0
// err := client.ListKeysPages(params,
// func(page *kms.ListKeysOutput, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *KMS) ListKeysPages(input *ListKeysInput, fn func(*ListKeysOutput, bool) bool) error {
return c.ListKeysPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListKeysPagesWithContext same as ListKeysPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListKeysPagesWithContext(ctx aws.Context, input *ListKeysInput, fn func(*ListKeysOutput, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListKeysInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListKeysRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListKeysOutput), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opListResourceTags = "ListResourceTags"
// ListResourceTagsRequest generates a "aws/request.Request" representing the
// client's request for the ListResourceTags operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListResourceTags for more information on using the ListResourceTags
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListResourceTagsRequest method.
// req, resp := client.ListResourceTagsRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListResourceTags
func (c *KMS) ListResourceTagsRequest(input *ListResourceTagsInput) (req *request.Request, output *ListResourceTagsOutput) {
op := &request.Operation{
Name: opListResourceTags,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ListResourceTagsInput{}
}
output = &ListResourceTagsOutput{}
req = c.newRequest(op, input, output)
return
}
// ListResourceTags API operation for AWS Key Management Service.
//
// Returns all tags on the specified KMS key.
//
// For general information about tags, including the format and syntax, see
// Tagging Amazon Web Services resources (https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html)
// in the Amazon Web Services General Reference. For information about using
// tags in KMS, see Tagging keys (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html).
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:ListResourceTags (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations:
//
// * CreateKey
//
// * ReplicateKey
//
// * TagResource
//
// * UntagResource
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListResourceTags for usage and error information.
//
// Returned Error Types:
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListResourceTags
func (c *KMS) ListResourceTags(input *ListResourceTagsInput) (*ListResourceTagsOutput, error) {
req, out := c.ListResourceTagsRequest(input)
return out, req.Send()
}
// ListResourceTagsWithContext is the same as ListResourceTags with the addition of
// the ability to pass a context and additional request options.
//
// See ListResourceTags for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListResourceTagsWithContext(ctx aws.Context, input *ListResourceTagsInput, opts ...request.Option) (*ListResourceTagsOutput, error) {
req, out := c.ListResourceTagsRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opListRetirableGrants = "ListRetirableGrants"
// ListRetirableGrantsRequest generates a "aws/request.Request" representing the
// client's request for the ListRetirableGrants operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListRetirableGrants for more information on using the ListRetirableGrants
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListRetirableGrantsRequest method.
// req, resp := client.ListRetirableGrantsRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListRetirableGrants
func (c *KMS) ListRetirableGrantsRequest(input *ListRetirableGrantsInput) (req *request.Request, output *ListGrantsResponse) {
op := &request.Operation{
Name: opListRetirableGrants,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ListRetirableGrantsInput{}
}
output = &ListGrantsResponse{}
req = c.newRequest(op, input, output)
return
}
// ListRetirableGrants API operation for AWS Key Management Service.
//
// Returns information about all grants in the Amazon Web Services account and
// Region that have the specified retiring principal.
//
// You can specify any principal in your Amazon Web Services account. The grants
// that are returned include grants for KMS keys in your Amazon Web Services
// account and other Amazon Web Services accounts. You might use this operation
// to determine which grants you may retire. To retire a grant, use the RetireGrant
// operation.
//
// For detailed information about grants, including grant terminology, see Grants
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)
// in the Key Management Service Developer Guide . For examples of working with
// grants in several programming languages, see Programming grants (https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html).
//
// Cross-account use: You must specify a principal in your Amazon Web Services
// account. However, this operation can return grants in any Amazon Web Services
// account. You do not need kms:ListRetirableGrants permission (or any other
// additional permission) in any Amazon Web Services account other than your
// own.
//
// Required permissions: kms:ListRetirableGrants (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy) in your Amazon Web Services account.
//
// Related operations:
//
// * CreateGrant
//
// * ListGrants
//
// * RetireGrant
//
// * RevokeGrant
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ListRetirableGrants for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidMarkerException
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ListRetirableGrants
func (c *KMS) ListRetirableGrants(input *ListRetirableGrantsInput) (*ListGrantsResponse, error) {
req, out := c.ListRetirableGrantsRequest(input)
return out, req.Send()
}
// ListRetirableGrantsWithContext is the same as ListRetirableGrants with the addition of
// the ability to pass a context and additional request options.
//
// See ListRetirableGrants for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ListRetirableGrantsWithContext(ctx aws.Context, input *ListRetirableGrantsInput, opts ...request.Option) (*ListGrantsResponse, error) {
req, out := c.ListRetirableGrantsRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opPutKeyPolicy = "PutKeyPolicy"
// PutKeyPolicyRequest generates a "aws/request.Request" representing the
// client's request for the PutKeyPolicy operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See PutKeyPolicy for more information on using the PutKeyPolicy
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the PutKeyPolicyRequest method.
// req, resp := client.PutKeyPolicyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/PutKeyPolicy
func (c *KMS) PutKeyPolicyRequest(input *PutKeyPolicyInput) (req *request.Request, output *PutKeyPolicyOutput) {
op := &request.Operation{
Name: opPutKeyPolicy,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &PutKeyPolicyInput{}
}
output = &PutKeyPolicyOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// PutKeyPolicy API operation for AWS Key Management Service.
//
// Attaches a key policy to the specified KMS key.
//
// For more information about key policies, see Key Policies (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)
// in the Key Management Service Developer Guide. For help writing and formatting
// a JSON policy document, see the IAM JSON Policy Reference (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html)
// in the Identity and Access Management User Guide . For examples of adding
// a key policy in multiple programming languages, see Setting a key policy
// (https://docs.aws.amazon.com/kms/latest/developerguide/programming-key-policies.html#put-policy)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:PutKeyPolicy (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: GetKeyPolicy
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation PutKeyPolicy for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * MalformedPolicyDocumentException
// The request was rejected because the specified policy is not syntactically
// or semantically correct.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/PutKeyPolicy
func (c *KMS) PutKeyPolicy(input *PutKeyPolicyInput) (*PutKeyPolicyOutput, error) {
req, out := c.PutKeyPolicyRequest(input)
return out, req.Send()
}
// PutKeyPolicyWithContext is the same as PutKeyPolicy with the addition of
// the ability to pass a context and additional request options.
//
// See PutKeyPolicy for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) PutKeyPolicyWithContext(ctx aws.Context, input *PutKeyPolicyInput, opts ...request.Option) (*PutKeyPolicyOutput, error) {
req, out := c.PutKeyPolicyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opReEncrypt = "ReEncrypt"
// ReEncryptRequest generates a "aws/request.Request" representing the
// client's request for the ReEncrypt operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ReEncrypt for more information on using the ReEncrypt
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ReEncryptRequest method.
// req, resp := client.ReEncryptRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ReEncrypt
func (c *KMS) ReEncryptRequest(input *ReEncryptInput) (req *request.Request, output *ReEncryptOutput) {
op := &request.Operation{
Name: opReEncrypt,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ReEncryptInput{}
}
output = &ReEncryptOutput{}
req = c.newRequest(op, input, output)
return
}
// ReEncrypt API operation for AWS Key Management Service.
//
// Decrypts ciphertext and then reencrypts it entirely within KMS. You can use
// this operation to change the KMS key under which data is encrypted, such
// as when you manually rotate (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html#rotate-keys-manually)
// a KMS key or change the KMS key that protects a ciphertext. You can also
// use it to reencrypt ciphertext under the same KMS key, such as to change
// the encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// of a ciphertext.
//
// The ReEncrypt operation can decrypt ciphertext that was encrypted by using
// a KMS key in an KMS operation, such as Encrypt or GenerateDataKey. It can
// also decrypt ciphertext that was encrypted by using the public key of an
// asymmetric KMS key (https://docs.aws.amazon.com/kms/latest/developerguide/symm-asymm-concepts.html#asymmetric-cmks)
// outside of KMS. However, it cannot decrypt ciphertext produced by other libraries,
// such as the Amazon Web Services Encryption SDK (https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/)
// or Amazon S3 client-side encryption (https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingClientSideEncryption.html).
// These libraries return a ciphertext format that is incompatible with KMS.
//
// When you use the ReEncrypt operation, you need to provide information for
// the decrypt operation and the subsequent encrypt operation.
//
// * If your ciphertext was encrypted under an asymmetric KMS key, you must
// use the SourceKeyId parameter to identify the KMS key that encrypted the
// ciphertext. You must also supply the encryption algorithm that was used.
// This information is required to decrypt the data.
//
// * If your ciphertext was encrypted under a symmetric encryption KMS key,
// the SourceKeyId parameter is optional. KMS can get this information from
// metadata that it adds to the symmetric ciphertext blob. This feature adds
// durability to your implementation by ensuring that authorized users can
// decrypt ciphertext decades after it was encrypted, even if they've lost
// track of the key ID. However, specifying the source KMS key is always
// recommended as a best practice. When you use the SourceKeyId parameter
// to specify a KMS key, KMS uses only the KMS key you specify. If the ciphertext
// was encrypted under a different KMS key, the ReEncrypt operation fails.
// This practice ensures that you use the KMS key that you intend.
//
// * To reencrypt the data, you must use the DestinationKeyId parameter specify
// the KMS key that re-encrypts the data after it is decrypted. If the destination
// KMS key is an asymmetric KMS key, you must also provide the encryption
// algorithm. The algorithm that you choose must be compatible with the KMS
// key. When you use an asymmetric KMS key to encrypt or reencrypt data,
// be sure to record the KMS key and encryption algorithm that you choose.
// You will be required to provide the same KMS key and encryption algorithm
// when you decrypt the data. If the KMS key and algorithm do not match the
// values used to encrypt the data, the decrypt operation fails. You are
// not required to supply the key ID and encryption algorithm when you decrypt
// with symmetric encryption KMS keys because KMS stores this information
// in the ciphertext blob. KMS cannot store metadata in ciphertext generated
// with asymmetric keys. The standard format for asymmetric key ciphertext
// does not include configurable fields.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. The source KMS key and destination KMS key can be
// in different Amazon Web Services accounts. Either or both KMS keys can be
// in a different account than the caller. To specify a KMS key in a different
// account, you must use its key ARN or alias ARN.
//
// Required permissions:
//
// * kms:ReEncryptFrom (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// permission on the source KMS key (key policy)
//
// * kms:ReEncryptTo (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// permission on the destination KMS key (key policy)
//
// To permit reencryption from or to a KMS key, include the "kms:ReEncrypt*"
// permission in your key policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html).
// This permission is automatically included in the key policy when you use
// the console to create a KMS key. But you must include it manually when you
// create a KMS key programmatically or when you use the PutKeyPolicy operation
// to set a key policy.
//
// Related operations:
//
// * Decrypt
//
// * Encrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyPair
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ReEncrypt for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidCiphertextException
// From the Decrypt or ReEncrypt operation, the request was rejected because
// the specified ciphertext, or additional authenticated data incorporated into
// the ciphertext, such as the encryption context, is corrupted, missing, or
// otherwise invalid.
//
// From the ImportKeyMaterial operation, the request was rejected because KMS
// could not decrypt the encrypted (wrapped) key material.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * IncorrectKeyException
// The request was rejected because the specified KMS key cannot decrypt the
// data. The KeyId in a Decrypt request and the SourceKeyId in a ReEncrypt request
// must identify the same KMS key that was used to encrypt the ciphertext.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ReEncrypt
func (c *KMS) ReEncrypt(input *ReEncryptInput) (*ReEncryptOutput, error) {
req, out := c.ReEncryptRequest(input)
return out, req.Send()
}
// ReEncryptWithContext is the same as ReEncrypt with the addition of
// the ability to pass a context and additional request options.
//
// See ReEncrypt for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ReEncryptWithContext(ctx aws.Context, input *ReEncryptInput, opts ...request.Option) (*ReEncryptOutput, error) {
req, out := c.ReEncryptRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opReplicateKey = "ReplicateKey"
// ReplicateKeyRequest generates a "aws/request.Request" representing the
// client's request for the ReplicateKey operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ReplicateKey for more information on using the ReplicateKey
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ReplicateKeyRequest method.
// req, resp := client.ReplicateKeyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ReplicateKey
func (c *KMS) ReplicateKeyRequest(input *ReplicateKeyInput) (req *request.Request, output *ReplicateKeyOutput) {
op := &request.Operation{
Name: opReplicateKey,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ReplicateKeyInput{}
}
output = &ReplicateKeyOutput{}
req = c.newRequest(op, input, output)
return
}
// ReplicateKey API operation for AWS Key Management Service.
//
// Replicates a multi-Region key into the specified Region. This operation creates
// a multi-Region replica key based on a multi-Region primary key in a different
// Region of the same Amazon Web Services partition. You can create multiple
// replicas of a primary key, but each must be in a different Region. To create
// a multi-Region primary key, use the CreateKey operation.
//
// This operation supports multi-Region keys, an KMS feature that lets you create
// multiple interoperable KMS keys in different Amazon Web Services Regions.
// Because these KMS keys have the same key ID, key material, and other metadata,
// you can use them interchangeably to encrypt data in one Amazon Web Services
// Region and decrypt it in a different Amazon Web Services Region without re-encrypting
// the data or making a cross-Region call. For more information about multi-Region
// keys, see Multi-Region keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
//
// A replica key is a fully-functional KMS key that can be used independently
// of its primary and peer replica keys. A primary key and its replica keys
// share properties that make them interoperable. They have the same key ID
// (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-id)
// and key material. They also have the same key spec (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-spec),
// key usage (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-usage),
// key material origin (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-origin),
// and automatic key rotation status (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html).
// KMS automatically synchronizes these shared properties among related multi-Region
// keys. All other properties of a replica key can differ, including its key
// policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html),
// tags (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html),
// aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html),
// and Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html).
// KMS pricing and quotas for KMS keys apply to each primary key and replica
// key.
//
// When this operation completes, the new replica key has a transient key state
// of Creating. This key state changes to Enabled (or PendingImport) after a
// few seconds when the process of creating the new replica key is complete.
// While the key state is Creating, you can manage key, but you cannot yet use
// it in cryptographic operations. If you are creating and using the replica
// key programmatically, retry on KMSInvalidStateException or call DescribeKey
// to check its KeyState value before using it. For details about the Creating
// key state, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// You cannot create more than one replica of a primary key in any Region. If
// the Region already includes a replica of the key you're trying to replicate,
// ReplicateKey returns an AlreadyExistsException error. If the key state of
// the existing replica is PendingDeletion, you can cancel the scheduled key
// deletion (CancelKeyDeletion) or wait for the key to be deleted. The new replica
// key you create will have the same shared properties (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html#mrk-sync-properties)
// as the original replica key.
//
// The CloudTrail log of a ReplicateKey operation records a ReplicateKey operation
// in the primary key's Region and a CreateKey operation in the replica key's
// Region.
//
// If you replicate a multi-Region primary key with imported key material, the
// replica key is created with no key material. You must import the same key
// material that you imported into the primary key. For details, see Importing
// key material into multi-Region keys (kms/latest/developerguide/multi-region-keys-import.html)
// in the Key Management Service Developer Guide.
//
// To convert a replica key to a primary key, use the UpdatePrimaryRegion operation.
//
// ReplicateKey uses different default values for the KeyPolicy and Tags parameters
// than those used in the KMS console. For details, see the parameter descriptions.
//
// Cross-account use: No. You cannot use this operation to create a replica
// key in a different Amazon Web Services account.
//
// Required permissions:
//
// * kms:ReplicateKey on the primary key (in the primary key's Region). Include
// this permission in the primary key's key policy.
//
// * kms:CreateKey in an IAM policy in the replica Region.
//
// * To use the Tags parameter, kms:TagResource in an IAM policy in the replica
// Region.
//
// Related operations
//
// * CreateKey
//
// * UpdatePrimaryRegion
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ReplicateKey for usage and error information.
//
// Returned Error Types:
// * AlreadyExistsException
// The request was rejected because it attempted to create a resource that already
// exists.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * MalformedPolicyDocumentException
// The request was rejected because the specified policy is not syntactically
// or semantically correct.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * TagException
// The request was rejected because one or more tags are not valid.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ReplicateKey
func (c *KMS) ReplicateKey(input *ReplicateKeyInput) (*ReplicateKeyOutput, error) {
req, out := c.ReplicateKeyRequest(input)
return out, req.Send()
}
// ReplicateKeyWithContext is the same as ReplicateKey with the addition of
// the ability to pass a context and additional request options.
//
// See ReplicateKey for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ReplicateKeyWithContext(ctx aws.Context, input *ReplicateKeyInput, opts ...request.Option) (*ReplicateKeyOutput, error) {
req, out := c.ReplicateKeyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opRetireGrant = "RetireGrant"
// RetireGrantRequest generates a "aws/request.Request" representing the
// client's request for the RetireGrant operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See RetireGrant for more information on using the RetireGrant
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the RetireGrantRequest method.
// req, resp := client.RetireGrantRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/RetireGrant
func (c *KMS) RetireGrantRequest(input *RetireGrantInput) (req *request.Request, output *RetireGrantOutput) {
op := &request.Operation{
Name: opRetireGrant,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &RetireGrantInput{}
}
output = &RetireGrantOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// RetireGrant API operation for AWS Key Management Service.
//
// Deletes a grant. Typically, you retire a grant when you no longer need its
// permissions. To identify the grant to retire, use a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token),
// or both the grant ID and a key identifier (key ID or key ARN) of the KMS
// key. The CreateGrant operation returns both values.
//
// This operation can be called by the retiring principal for a grant, by the
// grantee principal if the grant allows the RetireGrant operation, and by the
// Amazon Web Services account in which the grant is created. It can also be
// called by principals to whom permission for retiring a grant is delegated.
// For details, see Retiring and revoking grants (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#grant-delete)
// in the Key Management Service Developer Guide.
//
// For detailed information about grants, including grant terminology, see Grants
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)
// in the Key Management Service Developer Guide . For examples of working with
// grants in several programming languages, see Programming grants (https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html).
//
// Cross-account use: Yes. You can retire a grant on a KMS key in a different
// Amazon Web Services account.
//
// Required permissions::Permission to retire a grant is determined primarily
// by the grant. For details, see Retiring and revoking grants (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#grant-delete)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * CreateGrant
//
// * ListGrants
//
// * ListRetirableGrants
//
// * RevokeGrant
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation RetireGrant for usage and error information.
//
// Returned Error Types:
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InvalidGrantIdException
// The request was rejected because the specified GrantId is not valid.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/RetireGrant
func (c *KMS) RetireGrant(input *RetireGrantInput) (*RetireGrantOutput, error) {
req, out := c.RetireGrantRequest(input)
return out, req.Send()
}
// RetireGrantWithContext is the same as RetireGrant with the addition of
// the ability to pass a context and additional request options.
//
// See RetireGrant for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) RetireGrantWithContext(ctx aws.Context, input *RetireGrantInput, opts ...request.Option) (*RetireGrantOutput, error) {
req, out := c.RetireGrantRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opRevokeGrant = "RevokeGrant"
// RevokeGrantRequest generates a "aws/request.Request" representing the
// client's request for the RevokeGrant operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See RevokeGrant for more information on using the RevokeGrant
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the RevokeGrantRequest method.
// req, resp := client.RevokeGrantRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/RevokeGrant
func (c *KMS) RevokeGrantRequest(input *RevokeGrantInput) (req *request.Request, output *RevokeGrantOutput) {
op := &request.Operation{
Name: opRevokeGrant,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &RevokeGrantInput{}
}
output = &RevokeGrantOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// RevokeGrant API operation for AWS Key Management Service.
//
// Deletes the specified grant. You revoke a grant to terminate the permissions
// that the grant allows. For more information, see Retiring and revoking grants
// (https://docs.aws.amazon.com/kms/latest/developerguide/managing-grants.html#grant-delete)
// in the Key Management Service Developer Guide .
//
// When you create, retire, or revoke a grant, there might be a brief delay,
// usually less than five minutes, until the grant is available throughout KMS.
// This state is known as eventual consistency. For details, see Eventual consistency
// (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-eventual-consistency)
// in the Key Management Service Developer Guide .
//
// For detailed information about grants, including grant terminology, see Grants
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html)
// in the Key Management Service Developer Guide . For examples of working with
// grants in several programming languages, see Programming grants (https://docs.aws.amazon.com/kms/latest/developerguide/programming-grants.html).
//
// Cross-account use: Yes. To perform this operation on a KMS key in a different
// Amazon Web Services account, specify the key ARN in the value of the KeyId
// parameter.
//
// Required permissions: kms:RevokeGrant (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy).
//
// Related operations:
//
// * CreateGrant
//
// * ListGrants
//
// * ListRetirableGrants
//
// * RetireGrant
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation RevokeGrant for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidGrantIdException
// The request was rejected because the specified GrantId is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/RevokeGrant
func (c *KMS) RevokeGrant(input *RevokeGrantInput) (*RevokeGrantOutput, error) {
req, out := c.RevokeGrantRequest(input)
return out, req.Send()
}
// RevokeGrantWithContext is the same as RevokeGrant with the addition of
// the ability to pass a context and additional request options.
//
// See RevokeGrant for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) RevokeGrantWithContext(ctx aws.Context, input *RevokeGrantInput, opts ...request.Option) (*RevokeGrantOutput, error) {
req, out := c.RevokeGrantRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opScheduleKeyDeletion = "ScheduleKeyDeletion"
// ScheduleKeyDeletionRequest generates a "aws/request.Request" representing the
// client's request for the ScheduleKeyDeletion operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ScheduleKeyDeletion for more information on using the ScheduleKeyDeletion
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ScheduleKeyDeletionRequest method.
// req, resp := client.ScheduleKeyDeletionRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ScheduleKeyDeletion
func (c *KMS) ScheduleKeyDeletionRequest(input *ScheduleKeyDeletionInput) (req *request.Request, output *ScheduleKeyDeletionOutput) {
op := &request.Operation{
Name: opScheduleKeyDeletion,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &ScheduleKeyDeletionInput{}
}
output = &ScheduleKeyDeletionOutput{}
req = c.newRequest(op, input, output)
return
}
// ScheduleKeyDeletion API operation for AWS Key Management Service.
//
// Schedules the deletion of a KMS key. By default, KMS applies a waiting period
// of 30 days, but you can specify a waiting period of 7-30 days. When this
// operation is successful, the key state of the KMS key changes to PendingDeletion
// and the key can't be used in any cryptographic operations. It remains in
// this state for the duration of the waiting period. Before the waiting period
// ends, you can use CancelKeyDeletion to cancel the deletion of the KMS key.
// After the waiting period ends, KMS deletes the KMS key, its key material,
// and all KMS data associated with it, including all aliases that refer to
// it.
//
// Deleting a KMS key is a destructive and potentially dangerous operation.
// When a KMS key is deleted, all data that was encrypted under the KMS key
// is unrecoverable. (The only exception is a multi-Region replica key.) To
// prevent the use of a KMS key without deleting it, use DisableKey.
//
// If you schedule deletion of a KMS key from a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html),
// when the waiting period expires, ScheduleKeyDeletion deletes the KMS key
// from KMS. Then KMS makes a best effort to delete the key material from the
// associated CloudHSM cluster. However, you might need to manually delete the
// orphaned key material (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-orphaned-key)
// from the cluster and its backups.
//
// You can schedule the deletion of a multi-Region primary key and its replica
// keys at any time. However, KMS will not delete a multi-Region primary key
// with existing replica keys. If you schedule the deletion of a primary key
// with replicas, its key state changes to PendingReplicaDeletion and it cannot
// be replicated or used in cryptographic operations. This status can continue
// indefinitely. When the last of its replicas keys is deleted (not just scheduled),
// the key state of the primary key changes to PendingDeletion and its waiting
// period (PendingWindowInDays) begins. For details, see Deleting multi-Region
// keys (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-delete.html)
// in the Key Management Service Developer Guide.
//
// For more information about scheduling a KMS key for deletion, see Deleting
// KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/deleting-keys.html)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:ScheduleKeyDeletion (key policy)
//
// Related operations
//
// * CancelKeyDeletion
//
// * DisableKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation ScheduleKeyDeletion for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/ScheduleKeyDeletion
func (c *KMS) ScheduleKeyDeletion(input *ScheduleKeyDeletionInput) (*ScheduleKeyDeletionOutput, error) {
req, out := c.ScheduleKeyDeletionRequest(input)
return out, req.Send()
}
// ScheduleKeyDeletionWithContext is the same as ScheduleKeyDeletion with the addition of
// the ability to pass a context and additional request options.
//
// See ScheduleKeyDeletion for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) ScheduleKeyDeletionWithContext(ctx aws.Context, input *ScheduleKeyDeletionInput, opts ...request.Option) (*ScheduleKeyDeletionOutput, error) {
req, out := c.ScheduleKeyDeletionRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opSign = "Sign"
// SignRequest generates a "aws/request.Request" representing the
// client's request for the Sign operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See Sign for more information on using the Sign
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the SignRequest method.
// req, resp := client.SignRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Sign
func (c *KMS) SignRequest(input *SignInput) (req *request.Request, output *SignOutput) {
op := &request.Operation{
Name: opSign,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &SignInput{}
}
output = &SignOutput{}
req = c.newRequest(op, input, output)
return
}
// Sign API operation for AWS Key Management Service.
//
// Creates a digital signature (https://en.wikipedia.org/wiki/Digital_signature)
// for a message or message digest by using the private key in an asymmetric
// signing KMS key. To verify the signature, use the Verify operation, or use
// the public key in the same asymmetric KMS key outside of KMS. For information
// about asymmetric KMS keys, see Asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
// in the Key Management Service Developer Guide.
//
// Digital signatures are generated and verified by using asymmetric key pair,
// such as an RSA or ECC pair that is represented by an asymmetric KMS key.
// The key owner (or an authorized user) uses their private key to sign a message.
// Anyone with the public key can verify that the message was signed with that
// particular private key and that the message hasn't changed since it was signed.
//
// To use the Sign operation, provide the following information:
//
// * Use the KeyId parameter to identify an asymmetric KMS key with a KeyUsage
// value of SIGN_VERIFY. To get the KeyUsage value of a KMS key, use the
// DescribeKey operation. The caller must have kms:Sign permission on the
// KMS key.
//
// * Use the Message parameter to specify the message or message digest to
// sign. You can submit messages of up to 4096 bytes. To sign a larger message,
// generate a hash digest of the message, and then provide the hash digest
// in the Message parameter. To indicate whether the message is a full message
// or a digest, use the MessageType parameter.
//
// * Choose a signing algorithm that is compatible with the KMS key.
//
// When signing a message, be sure to record the KMS key and the signing algorithm.
// This information is required to verify the signature.
//
// To verify the signature that this operation generates, use the Verify operation.
// Or use the GetPublicKey operation to download the public key and then use
// the public key to verify the signature outside of KMS.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:Sign (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: Verify
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation Sign for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Sign
func (c *KMS) Sign(input *SignInput) (*SignOutput, error) {
req, out := c.SignRequest(input)
return out, req.Send()
}
// SignWithContext is the same as Sign with the addition of
// the ability to pass a context and additional request options.
//
// See Sign for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) SignWithContext(ctx aws.Context, input *SignInput, opts ...request.Option) (*SignOutput, error) {
req, out := c.SignRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opTagResource = "TagResource"
// TagResourceRequest generates a "aws/request.Request" representing the
// client's request for the TagResource operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See TagResource for more information on using the TagResource
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the TagResourceRequest method.
// req, resp := client.TagResourceRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/TagResource
func (c *KMS) TagResourceRequest(input *TagResourceInput) (req *request.Request, output *TagResourceOutput) {
op := &request.Operation{
Name: opTagResource,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &TagResourceInput{}
}
output = &TagResourceOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// TagResource API operation for AWS Key Management Service.
//
// Adds or edits tags on a customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk).
//
// Tagging or untagging a KMS key can allow or deny permission to the KMS key.
// For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// Each tag consists of a tag key and a tag value, both of which are case-sensitive
// strings. The tag value can be an empty (null) string. To add a tag, specify
// a new tag key and a tag value. To edit a tag, specify an existing tag key
// and a new tag value.
//
// You can use this operation to tag a customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk),
// but you cannot tag an Amazon Web Services managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk),
// an Amazon Web Services owned key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-owned-cmk),
// a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#keystore-concept),
// or an alias (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#alias-concept).
//
// You can also add tags to a KMS key while creating it (CreateKey) or replicating
// it (ReplicateKey).
//
// For information about using tags in KMS, see Tagging keys (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html).
// For general information about tags, including the format and syntax, see
// Tagging Amazon Web Services resources (https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html)
// in the Amazon Web Services General Reference.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:TagResource (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations
//
// * CreateKey
//
// * ListResourceTags
//
// * ReplicateKey
//
// * UntagResource
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation TagResource for usage and error information.
//
// Returned Error Types:
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * TagException
// The request was rejected because one or more tags are not valid.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/TagResource
func (c *KMS) TagResource(input *TagResourceInput) (*TagResourceOutput, error) {
req, out := c.TagResourceRequest(input)
return out, req.Send()
}
// TagResourceWithContext is the same as TagResource with the addition of
// the ability to pass a context and additional request options.
//
// See TagResource for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) TagResourceWithContext(ctx aws.Context, input *TagResourceInput, opts ...request.Option) (*TagResourceOutput, error) {
req, out := c.TagResourceRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opUntagResource = "UntagResource"
// UntagResourceRequest generates a "aws/request.Request" representing the
// client's request for the UntagResource operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See UntagResource for more information on using the UntagResource
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the UntagResourceRequest method.
// req, resp := client.UntagResourceRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UntagResource
func (c *KMS) UntagResourceRequest(input *UntagResourceInput) (req *request.Request, output *UntagResourceOutput) {
op := &request.Operation{
Name: opUntagResource,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &UntagResourceInput{}
}
output = &UntagResourceOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// UntagResource API operation for AWS Key Management Service.
//
// Deletes tags from a customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk).
// To delete a tag, specify the tag key and the KMS key.
//
// Tagging or untagging a KMS key can allow or deny permission to the KMS key.
// For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// When it succeeds, the UntagResource operation doesn't return any output.
// Also, if the specified tag key isn't found on the KMS key, it doesn't throw
// an exception or return a response. To confirm that the operation worked,
// use the ListResourceTags operation.
//
// For information about using tags in KMS, see Tagging keys (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html).
// For general information about tags, including the format and syntax, see
// Tagging Amazon Web Services resources (https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html)
// in the Amazon Web Services General Reference.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:UntagResource (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations
//
// * CreateKey
//
// * ListResourceTags
//
// * ReplicateKey
//
// * TagResource
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation UntagResource for usage and error information.
//
// Returned Error Types:
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * TagException
// The request was rejected because one or more tags are not valid.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UntagResource
func (c *KMS) UntagResource(input *UntagResourceInput) (*UntagResourceOutput, error) {
req, out := c.UntagResourceRequest(input)
return out, req.Send()
}
// UntagResourceWithContext is the same as UntagResource with the addition of
// the ability to pass a context and additional request options.
//
// See UntagResource for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) UntagResourceWithContext(ctx aws.Context, input *UntagResourceInput, opts ...request.Option) (*UntagResourceOutput, error) {
req, out := c.UntagResourceRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opUpdateAlias = "UpdateAlias"
// UpdateAliasRequest generates a "aws/request.Request" representing the
// client's request for the UpdateAlias operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See UpdateAlias for more information on using the UpdateAlias
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the UpdateAliasRequest method.
// req, resp := client.UpdateAliasRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateAlias
func (c *KMS) UpdateAliasRequest(input *UpdateAliasInput) (req *request.Request, output *UpdateAliasOutput) {
op := &request.Operation{
Name: opUpdateAlias,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &UpdateAliasInput{}
}
output = &UpdateAliasOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// UpdateAlias API operation for AWS Key Management Service.
//
// Associates an existing KMS alias with a different KMS key. Each alias is
// associated with only one KMS key at a time, although a KMS key can have multiple
// aliases. The alias and the KMS key must be in the same Amazon Web Services
// account and Region.
//
// Adding, deleting, or updating an alias can allow or deny permission to the
// KMS key. For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// The current and new KMS key must be the same type (both symmetric or both
// asymmetric), and they must have the same key usage (ENCRYPT_DECRYPT or SIGN_VERIFY).
// This restriction prevents errors in code that uses aliases. If you must assign
// an alias to a different type of KMS key, use DeleteAlias to delete the old
// alias and CreateAlias to create a new alias.
//
// You cannot use UpdateAlias to change an alias name. To change an alias name,
// use DeleteAlias to delete the old alias and CreateAlias to create a new alias.
//
// Because an alias is not a property of a KMS key, you can create, update,
// and delete the aliases of a KMS key without affecting the KMS key. Also,
// aliases do not appear in the response from the DescribeKey operation. To
// get the aliases of all KMS keys in the account, use the ListAliases operation.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions
//
// * kms:UpdateAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the alias (IAM policy).
//
// * kms:UpdateAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the current KMS key (key policy).
//
// * kms:UpdateAlias (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// on the new KMS key (key policy).
//
// For details, see Controlling access to aliases (https://docs.aws.amazon.com/kms/latest/developerguide/kms-alias.html#alias-access)
// in the Key Management Service Developer Guide.
//
// Related operations:
//
// * CreateAlias
//
// * DeleteAlias
//
// * ListAliases
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation UpdateAlias for usage and error information.
//
// Returned Error Types:
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * LimitExceededException
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateAlias
func (c *KMS) UpdateAlias(input *UpdateAliasInput) (*UpdateAliasOutput, error) {
req, out := c.UpdateAliasRequest(input)
return out, req.Send()
}
// UpdateAliasWithContext is the same as UpdateAlias with the addition of
// the ability to pass a context and additional request options.
//
// See UpdateAlias for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) UpdateAliasWithContext(ctx aws.Context, input *UpdateAliasInput, opts ...request.Option) (*UpdateAliasOutput, error) {
req, out := c.UpdateAliasRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opUpdateCustomKeyStore = "UpdateCustomKeyStore"
// UpdateCustomKeyStoreRequest generates a "aws/request.Request" representing the
// client's request for the UpdateCustomKeyStore operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See UpdateCustomKeyStore for more information on using the UpdateCustomKeyStore
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the UpdateCustomKeyStoreRequest method.
// req, resp := client.UpdateCustomKeyStoreRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateCustomKeyStore
func (c *KMS) UpdateCustomKeyStoreRequest(input *UpdateCustomKeyStoreInput) (req *request.Request, output *UpdateCustomKeyStoreOutput) {
op := &request.Operation{
Name: opUpdateCustomKeyStore,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &UpdateCustomKeyStoreInput{}
}
output = &UpdateCustomKeyStoreOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// UpdateCustomKeyStore API operation for AWS Key Management Service.
//
// Changes the properties of a custom key store. Use the CustomKeyStoreId parameter
// to identify the custom key store you want to edit. Use the remaining parameters
// to change the properties of the custom key store.
//
// You can only update a custom key store that is disconnected. To disconnect
// the custom key store, use DisconnectCustomKeyStore. To reconnect the custom
// key store after the update completes, use ConnectCustomKeyStore. To find
// the connection state of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// The CustomKeyStoreId parameter is required in all commands. Use the other
// parameters of UpdateCustomKeyStore to edit your key store settings.
//
// * Use the NewCustomKeyStoreName parameter to change the friendly name
// of the custom key store to the value that you specify.
//
// * Use the KeyStorePassword parameter tell KMS the current password of
// the kmsuser crypto user (CU) (https://docs.aws.amazon.com/kms/latest/developerguide/key-store-concepts.html#concept-kmsuser)
// in the associated CloudHSM cluster. You can use this parameter to fix
// connection failures (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-password)
// that occur when KMS cannot log into the associated cluster because the
// kmsuser password has changed. This value does not change the password
// in the CloudHSM cluster.
//
// * Use the CloudHsmClusterId parameter to associate the custom key store
// with a different, but related, CloudHSM cluster. You can use this parameter
// to repair a custom key store if its CloudHSM cluster becomes corrupted
// or is deleted, or when you need to create or restore a cluster from a
// backup.
//
// If the operation succeeds, it returns a JSON object with no properties.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
//
// Cross-account use: No. You cannot perform this operation on a custom key
// store in a different Amazon Web Services account.
//
// Required permissions: kms:UpdateCustomKeyStore (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (IAM policy)
//
// Related operations:
//
// * ConnectCustomKeyStore
//
// * CreateCustomKeyStore
//
// * DeleteCustomKeyStore
//
// * DescribeCustomKeyStores
//
// * DisconnectCustomKeyStore
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation UpdateCustomKeyStore for usage and error information.
//
// Returned Error Types:
// * CustomKeyStoreNotFoundException
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
//
// * CustomKeyStoreNameInUseException
// The request was rejected because the specified custom key store name is already
// assigned to another custom key store in the account. Try again with a custom
// key store name that is unique in the account.
//
// * CloudHsmClusterNotFoundException
// The request was rejected because KMS cannot find the CloudHSM cluster with
// the specified cluster ID. Retry the request with a different cluster ID.
//
// * CloudHsmClusterNotRelatedException
// The request was rejected because the specified CloudHSM cluster has a different
// cluster certificate than the original cluster. You cannot use the operation
// to specify an unrelated cluster.
//
// Specify a cluster that shares a backup history with the original cluster.
// This includes clusters that were created from a backup of the current cluster,
// and clusters that were created from the same backup that produced the current
// cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
//
// * CustomKeyStoreInvalidStateException
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * CloudHsmClusterNotActiveException
// The request was rejected because the CloudHSM cluster that is associated
// with the custom key store is not active. Initialize and activate the cluster
// and try the command again. For detailed instructions, see Getting Started
// (https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html)
// in the CloudHSM User Guide.
//
// * CloudHsmClusterInvalidConfigurationException
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateCustomKeyStore
func (c *KMS) UpdateCustomKeyStore(input *UpdateCustomKeyStoreInput) (*UpdateCustomKeyStoreOutput, error) {
req, out := c.UpdateCustomKeyStoreRequest(input)
return out, req.Send()
}
// UpdateCustomKeyStoreWithContext is the same as UpdateCustomKeyStore with the addition of
// the ability to pass a context and additional request options.
//
// See UpdateCustomKeyStore for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) UpdateCustomKeyStoreWithContext(ctx aws.Context, input *UpdateCustomKeyStoreInput, opts ...request.Option) (*UpdateCustomKeyStoreOutput, error) {
req, out := c.UpdateCustomKeyStoreRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opUpdateKeyDescription = "UpdateKeyDescription"
// UpdateKeyDescriptionRequest generates a "aws/request.Request" representing the
// client's request for the UpdateKeyDescription operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See UpdateKeyDescription for more information on using the UpdateKeyDescription
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the UpdateKeyDescriptionRequest method.
// req, resp := client.UpdateKeyDescriptionRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateKeyDescription
func (c *KMS) UpdateKeyDescriptionRequest(input *UpdateKeyDescriptionInput) (req *request.Request, output *UpdateKeyDescriptionOutput) {
op := &request.Operation{
Name: opUpdateKeyDescription,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &UpdateKeyDescriptionInput{}
}
output = &UpdateKeyDescriptionOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// UpdateKeyDescription API operation for AWS Key Management Service.
//
// Updates the description of a KMS key. To see the description of a KMS key,
// use DescribeKey.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: No. You cannot perform this operation on a KMS key in
// a different Amazon Web Services account.
//
// Required permissions: kms:UpdateKeyDescription (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations
//
// * CreateKey
//
// * DescribeKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation UpdateKeyDescription for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdateKeyDescription
func (c *KMS) UpdateKeyDescription(input *UpdateKeyDescriptionInput) (*UpdateKeyDescriptionOutput, error) {
req, out := c.UpdateKeyDescriptionRequest(input)
return out, req.Send()
}
// UpdateKeyDescriptionWithContext is the same as UpdateKeyDescription with the addition of
// the ability to pass a context and additional request options.
//
// See UpdateKeyDescription for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) UpdateKeyDescriptionWithContext(ctx aws.Context, input *UpdateKeyDescriptionInput, opts ...request.Option) (*UpdateKeyDescriptionOutput, error) {
req, out := c.UpdateKeyDescriptionRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opUpdatePrimaryRegion = "UpdatePrimaryRegion"
// UpdatePrimaryRegionRequest generates a "aws/request.Request" representing the
// client's request for the UpdatePrimaryRegion operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See UpdatePrimaryRegion for more information on using the UpdatePrimaryRegion
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the UpdatePrimaryRegionRequest method.
// req, resp := client.UpdatePrimaryRegionRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdatePrimaryRegion
func (c *KMS) UpdatePrimaryRegionRequest(input *UpdatePrimaryRegionInput) (req *request.Request, output *UpdatePrimaryRegionOutput) {
op := &request.Operation{
Name: opUpdatePrimaryRegion,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &UpdatePrimaryRegionInput{}
}
output = &UpdatePrimaryRegionOutput{}
req = c.newRequest(op, input, output)
req.Handlers.Unmarshal.Swap(jsonrpc.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// UpdatePrimaryRegion API operation for AWS Key Management Service.
//
// Changes the primary key of a multi-Region key.
//
// This operation changes the replica key in the specified Region to a primary
// key and changes the former primary key to a replica key. For example, suppose
// you have a primary key in us-east-1 and a replica key in eu-west-2. If you
// run UpdatePrimaryRegion with a PrimaryRegion value of eu-west-2, the primary
// key is now the key in eu-west-2, and the key in us-east-1 becomes a replica
// key. For details, see Updating the primary Region (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-manage.html#multi-region-update)
// in the Key Management Service Developer Guide.
//
// This operation supports multi-Region keys, an KMS feature that lets you create
// multiple interoperable KMS keys in different Amazon Web Services Regions.
// Because these KMS keys have the same key ID, key material, and other metadata,
// you can use them interchangeably to encrypt data in one Amazon Web Services
// Region and decrypt it in a different Amazon Web Services Region without re-encrypting
// the data or making a cross-Region call. For more information about multi-Region
// keys, see Multi-Region keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
//
// The primary key of a multi-Region key is the source for properties that are
// always shared by primary and replica keys, including the key material, key
// ID (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-id),
// key spec (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-spec),
// key usage (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-usage),
// key material origin (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-origin),
// and automatic key rotation (https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html).
// It's the only key that can be replicated. You cannot delete the primary key
// (https://docs.aws.amazon.com/kms/latest/APIReference/API_ScheduleKeyDeletion.html)
// until all replica keys are deleted.
//
// The key ID and primary Region that you specify uniquely identify the replica
// key that will become the primary key. The primary Region must already have
// a replica key. This operation does not create a KMS key in the specified
// Region. To find the replica keys, use the DescribeKey operation on the primary
// key or any replica key. To create a replica key, use the ReplicateKey operation.
//
// You can run this operation while using the affected multi-Region keys in
// cryptographic operations. This operation should not delay, interrupt, or
// cause failures in cryptographic operations.
//
// Even after this operation completes, the process of updating the primary
// Region might still be in progress for a few more seconds. Operations such
// as DescribeKey might display both the old and new primary keys as replicas.
// The old and new primary keys have a transient key state of Updating. The
// original key state is restored when the update is complete. While the key
// state is Updating, you can use the keys in cryptographic operations, but
// you cannot replicate the new primary key or perform certain management operations,
// such as enabling or disabling these keys. For details about the Updating
// key state, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// This operation does not return any output. To verify that primary key is
// changed, use the DescribeKey operation.
//
// Cross-account use: No. You cannot use this operation in a different Amazon
// Web Services account.
//
// Required permissions:
//
// * kms:UpdatePrimaryRegion on the current primary key (in the primary key's
// Region). Include this permission primary key's key policy.
//
// * kms:UpdatePrimaryRegion on the current replica key (in the replica key's
// Region). Include this permission in the replica key's key policy.
//
// Related operations
//
// * CreateKey
//
// * ReplicateKey
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation UpdatePrimaryRegion for usage and error information.
//
// Returned Error Types:
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * InvalidArnException
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * UnsupportedOperationException
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/UpdatePrimaryRegion
func (c *KMS) UpdatePrimaryRegion(input *UpdatePrimaryRegionInput) (*UpdatePrimaryRegionOutput, error) {
req, out := c.UpdatePrimaryRegionRequest(input)
return out, req.Send()
}
// UpdatePrimaryRegionWithContext is the same as UpdatePrimaryRegion with the addition of
// the ability to pass a context and additional request options.
//
// See UpdatePrimaryRegion for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) UpdatePrimaryRegionWithContext(ctx aws.Context, input *UpdatePrimaryRegionInput, opts ...request.Option) (*UpdatePrimaryRegionOutput, error) {
req, out := c.UpdatePrimaryRegionRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opVerify = "Verify"
// VerifyRequest generates a "aws/request.Request" representing the
// client's request for the Verify operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See Verify for more information on using the Verify
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the VerifyRequest method.
// req, resp := client.VerifyRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Verify
func (c *KMS) VerifyRequest(input *VerifyInput) (req *request.Request, output *VerifyOutput) {
op := &request.Operation{
Name: opVerify,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &VerifyInput{}
}
output = &VerifyOutput{}
req = c.newRequest(op, input, output)
return
}
// Verify API operation for AWS Key Management Service.
//
// Verifies a digital signature that was generated by the Sign operation.
//
// Verification confirms that an authorized user signed the message with the
// specified KMS key and signing algorithm, and the message hasn't changed since
// it was signed. If the signature is verified, the value of the SignatureValid
// field in the response is True. If the signature verification fails, the Verify
// operation fails with an KMSInvalidSignatureException exception.
//
// A digital signature is generated by using the private key in an asymmetric
// KMS key. The signature is verified by using the public key in the same asymmetric
// KMS key. For information about asymmetric KMS keys, see Asymmetric KMS keys
// (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html)
// in the Key Management Service Developer Guide.
//
// To verify a digital signature, you can use the Verify operation. Specify
// the same asymmetric KMS key, message, and signing algorithm that were used
// to produce the signature.
//
// You can also verify the digital signature by using the public key of the
// KMS key outside of KMS. Use the GetPublicKey operation to download the public
// key in the asymmetric KMS key and then use the public key to verify the signature
// outside of KMS. The advantage of using the Verify operation is that it is
// performed within KMS. As a result, it's easy to call, the operation is performed
// within the FIPS boundary, it is logged in CloudTrail, and you can use key
// policy and IAM policy to determine who is authorized to use the KMS key to
// verify signatures.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:Verify (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: Sign
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation Verify for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * DependencyTimeoutException
// The system timed out while trying to fulfill the request. The request can
// be retried.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// * KMSInvalidSignatureException
// The request was rejected because the signature verification failed. Signature
// verification fails when it cannot confirm that signature was produced by
// signing the specified message with the specified KMS key and signing algorithm.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/Verify
func (c *KMS) Verify(input *VerifyInput) (*VerifyOutput, error) {
req, out := c.VerifyRequest(input)
return out, req.Send()
}
// VerifyWithContext is the same as Verify with the addition of
// the ability to pass a context and additional request options.
//
// See Verify for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) VerifyWithContext(ctx aws.Context, input *VerifyInput, opts ...request.Option) (*VerifyOutput, error) {
req, out := c.VerifyRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opVerifyMac = "VerifyMac"
// VerifyMacRequest generates a "aws/request.Request" representing the
// client's request for the VerifyMac operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See VerifyMac for more information on using the VerifyMac
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the VerifyMacRequest method.
// req, resp := client.VerifyMacRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/VerifyMac
func (c *KMS) VerifyMacRequest(input *VerifyMacInput) (req *request.Request, output *VerifyMacOutput) {
op := &request.Operation{
Name: opVerifyMac,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &VerifyMacInput{}
}
output = &VerifyMacOutput{}
req = c.newRequest(op, input, output)
return
}
// VerifyMac API operation for AWS Key Management Service.
//
// Verifies the hash-based message authentication code (HMAC) for a specified
// message, HMAC KMS key, and MAC algorithm. To verify the HMAC, VerifyMac computes
// an HMAC using the message, HMAC KMS key, and MAC algorithm that you specify,
// and compares the computed HMAC to the HMAC that you specify. If the HMACs
// are identical, the verification succeeds; otherwise, it fails.
//
// Verification indicates that the message hasn't changed since the HMAC was
// calculated, and the specified key was used to generate and verify the HMAC.
//
// This operation is part of KMS support for HMAC KMS keys. For details, see
// HMAC keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html)
// in the Key Management Service Developer Guide.
//
// The KMS key that you use for this operation must be in a compatible key state.
// For details, see Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
//
// Cross-account use: Yes. To perform this operation with a KMS key in a different
// Amazon Web Services account, specify the key ARN or alias ARN in the value
// of the KeyId parameter.
//
// Required permissions: kms:VerifyMac (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// (key policy)
//
// Related operations: GenerateMac
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Key Management Service's
// API operation VerifyMac for usage and error information.
//
// Returned Error Types:
// * NotFoundException
// The request was rejected because the specified entity or resource could not
// be found.
//
// * DisabledException
// The request was rejected because the specified KMS key is not enabled.
//
// * KeyUnavailableException
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
//
// * InvalidKeyUsageException
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
//
// * InvalidGrantTokenException
// The request was rejected because the specified grant token is not valid.
//
// * InternalException
// The request was rejected because an internal exception occurred. The request
// can be retried.
//
// * KMSInvalidMacException
// The request was rejected because the HMAC verification failed. HMAC verification
// fails when the HMAC computed by using the specified message, HMAC KMS key,
// and MAC algorithm does not match the HMAC specified in the request.
//
// * InvalidStateException
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01/VerifyMac
func (c *KMS) VerifyMac(input *VerifyMacInput) (*VerifyMacOutput, error) {
req, out := c.VerifyMacRequest(input)
return out, req.Send()
}
// VerifyMacWithContext is the same as VerifyMac with the addition of
// the ability to pass a context and additional request options.
//
// See VerifyMac for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *KMS) VerifyMacWithContext(ctx aws.Context, input *VerifyMacInput, opts ...request.Option) (*VerifyMacOutput, error) {
req, out := c.VerifyMacRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// Contains information about an alias.
type AliasListEntry struct {
_ struct{} `type:"structure"`
// String that contains the key ARN.
AliasArn *string `min:"20" type:"string"`
// String that contains the alias. This value begins with alias/.
AliasName *string `min:"1" type:"string"`
// Date and time that the alias was most recently created in the account and
// Region. Formatted as Unix time.
CreationDate *time.Time `type:"timestamp"`
// Date and time that the alias was most recently associated with a KMS key
// in the account and Region. Formatted as Unix time.
LastUpdatedDate *time.Time `type:"timestamp"`
// String that contains the key identifier of the KMS key associated with the
// alias.
TargetKeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AliasListEntry) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AliasListEntry) GoString() string {
return s.String()
}
// SetAliasArn sets the AliasArn field's value.
func (s *AliasListEntry) SetAliasArn(v string) *AliasListEntry {
s.AliasArn = &v
return s
}
// SetAliasName sets the AliasName field's value.
func (s *AliasListEntry) SetAliasName(v string) *AliasListEntry {
s.AliasName = &v
return s
}
// SetCreationDate sets the CreationDate field's value.
func (s *AliasListEntry) SetCreationDate(v time.Time) *AliasListEntry {
s.CreationDate = &v
return s
}
// SetLastUpdatedDate sets the LastUpdatedDate field's value.
func (s *AliasListEntry) SetLastUpdatedDate(v time.Time) *AliasListEntry {
s.LastUpdatedDate = &v
return s
}
// SetTargetKeyId sets the TargetKeyId field's value.
func (s *AliasListEntry) SetTargetKeyId(v string) *AliasListEntry {
s.TargetKeyId = &v
return s
}
// The request was rejected because it attempted to create a resource that already
// exists.
type AlreadyExistsException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AlreadyExistsException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AlreadyExistsException) GoString() string {
return s.String()
}
func newErrorAlreadyExistsException(v protocol.ResponseMetadata) error {
return &AlreadyExistsException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *AlreadyExistsException) Code() string {
return "AlreadyExistsException"
}
// Message returns the exception's message.
func (s *AlreadyExistsException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *AlreadyExistsException) OrigErr() error {
return nil
}
func (s *AlreadyExistsException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *AlreadyExistsException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *AlreadyExistsException) RequestID() string {
return s.RespMetadata.RequestID
}
type CancelKeyDeletionInput struct {
_ struct{} `type:"structure"`
// Identifies the KMS key whose deletion is being canceled.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CancelKeyDeletionInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CancelKeyDeletionInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *CancelKeyDeletionInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "CancelKeyDeletionInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *CancelKeyDeletionInput) SetKeyId(v string) *CancelKeyDeletionInput {
s.KeyId = &v
return s
}
type CancelKeyDeletionOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key whose deletion is canceled.
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CancelKeyDeletionOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CancelKeyDeletionOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *CancelKeyDeletionOutput) SetKeyId(v string) *CancelKeyDeletionOutput {
s.KeyId = &v
return s
}
// The request was rejected because the specified CloudHSM cluster is already
// associated with a custom key store or it shares a backup history with a cluster
// that is associated with a custom key store. Each custom key store must be
// associated with a different CloudHSM cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
type CloudHsmClusterInUseException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterInUseException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterInUseException) GoString() string {
return s.String()
}
func newErrorCloudHsmClusterInUseException(v protocol.ResponseMetadata) error {
return &CloudHsmClusterInUseException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CloudHsmClusterInUseException) Code() string {
return "CloudHsmClusterInUseException"
}
// Message returns the exception's message.
func (s *CloudHsmClusterInUseException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CloudHsmClusterInUseException) OrigErr() error {
return nil
}
func (s *CloudHsmClusterInUseException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CloudHsmClusterInUseException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CloudHsmClusterInUseException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
type CloudHsmClusterInvalidConfigurationException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterInvalidConfigurationException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterInvalidConfigurationException) GoString() string {
return s.String()
}
func newErrorCloudHsmClusterInvalidConfigurationException(v protocol.ResponseMetadata) error {
return &CloudHsmClusterInvalidConfigurationException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CloudHsmClusterInvalidConfigurationException) Code() string {
return "CloudHsmClusterInvalidConfigurationException"
}
// Message returns the exception's message.
func (s *CloudHsmClusterInvalidConfigurationException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CloudHsmClusterInvalidConfigurationException) OrigErr() error {
return nil
}
func (s *CloudHsmClusterInvalidConfigurationException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CloudHsmClusterInvalidConfigurationException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CloudHsmClusterInvalidConfigurationException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the CloudHSM cluster that is associated
// with the custom key store is not active. Initialize and activate the cluster
// and try the command again. For detailed instructions, see Getting Started
// (https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html)
// in the CloudHSM User Guide.
type CloudHsmClusterNotActiveException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotActiveException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotActiveException) GoString() string {
return s.String()
}
func newErrorCloudHsmClusterNotActiveException(v protocol.ResponseMetadata) error {
return &CloudHsmClusterNotActiveException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CloudHsmClusterNotActiveException) Code() string {
return "CloudHsmClusterNotActiveException"
}
// Message returns the exception's message.
func (s *CloudHsmClusterNotActiveException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CloudHsmClusterNotActiveException) OrigErr() error {
return nil
}
func (s *CloudHsmClusterNotActiveException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CloudHsmClusterNotActiveException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CloudHsmClusterNotActiveException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because KMS cannot find the CloudHSM cluster with
// the specified cluster ID. Retry the request with a different cluster ID.
type CloudHsmClusterNotFoundException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotFoundException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotFoundException) GoString() string {
return s.String()
}
func newErrorCloudHsmClusterNotFoundException(v protocol.ResponseMetadata) error {
return &CloudHsmClusterNotFoundException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CloudHsmClusterNotFoundException) Code() string {
return "CloudHsmClusterNotFoundException"
}
// Message returns the exception's message.
func (s *CloudHsmClusterNotFoundException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CloudHsmClusterNotFoundException) OrigErr() error {
return nil
}
func (s *CloudHsmClusterNotFoundException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CloudHsmClusterNotFoundException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CloudHsmClusterNotFoundException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the specified CloudHSM cluster has a different
// cluster certificate than the original cluster. You cannot use the operation
// to specify an unrelated cluster.
//
// Specify a cluster that shares a backup history with the original cluster.
// This includes clusters that were created from a backup of the current cluster,
// and clusters that were created from the same backup that produced the current
// cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
type CloudHsmClusterNotRelatedException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotRelatedException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CloudHsmClusterNotRelatedException) GoString() string {
return s.String()
}
func newErrorCloudHsmClusterNotRelatedException(v protocol.ResponseMetadata) error {
return &CloudHsmClusterNotRelatedException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CloudHsmClusterNotRelatedException) Code() string {
return "CloudHsmClusterNotRelatedException"
}
// Message returns the exception's message.
func (s *CloudHsmClusterNotRelatedException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CloudHsmClusterNotRelatedException) OrigErr() error {
return nil
}
func (s *CloudHsmClusterNotRelatedException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CloudHsmClusterNotRelatedException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CloudHsmClusterNotRelatedException) RequestID() string {
return s.RespMetadata.RequestID
}
type ConnectCustomKeyStoreInput struct {
_ struct{} `type:"structure"`
// Enter the key store ID of the custom key store that you want to connect.
// To find the ID of a custom key store, use the DescribeCustomKeyStores operation.
//
// CustomKeyStoreId is a required field
CustomKeyStoreId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ConnectCustomKeyStoreInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ConnectCustomKeyStoreInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ConnectCustomKeyStoreInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ConnectCustomKeyStoreInput"}
if s.CustomKeyStoreId == nil {
invalidParams.Add(request.NewErrParamRequired("CustomKeyStoreId"))
}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *ConnectCustomKeyStoreInput) SetCustomKeyStoreId(v string) *ConnectCustomKeyStoreInput {
s.CustomKeyStoreId = &v
return s
}
type ConnectCustomKeyStoreOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ConnectCustomKeyStoreOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ConnectCustomKeyStoreOutput) GoString() string {
return s.String()
}
type CreateAliasInput struct {
_ struct{} `type:"structure"`
// Specifies the alias name. This value must begin with alias/ followed by a
// name, such as alias/ExampleAlias.
//
// The AliasName value must be string of 1-256 characters. It can contain only
// alphanumeric characters, forward slashes (/), underscores (_), and dashes
// (-). The alias name cannot begin with alias/aws/. The alias/aws/ prefix is
// reserved for Amazon Web Services managed keys (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk).
//
// AliasName is a required field
AliasName *string `min:"1" type:"string" required:"true"`
// Associates the alias with the specified customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk).
// The KMS key must be in the same Amazon Web Services Region.
//
// A valid key ID is required. If you supply a null or empty string value, this
// operation returns an error.
//
// For help finding the key ID and ARN, see Finding the Key ID and ARN (https://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html#find-cmk-id-arn)
// in the Key Management Service Developer Guide .
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// TargetKeyId is a required field
TargetKeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateAliasInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateAliasInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *CreateAliasInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "CreateAliasInput"}
if s.AliasName == nil {
invalidParams.Add(request.NewErrParamRequired("AliasName"))
}
if s.AliasName != nil && len(*s.AliasName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("AliasName", 1))
}
if s.TargetKeyId == nil {
invalidParams.Add(request.NewErrParamRequired("TargetKeyId"))
}
if s.TargetKeyId != nil && len(*s.TargetKeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("TargetKeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAliasName sets the AliasName field's value.
func (s *CreateAliasInput) SetAliasName(v string) *CreateAliasInput {
s.AliasName = &v
return s
}
// SetTargetKeyId sets the TargetKeyId field's value.
func (s *CreateAliasInput) SetTargetKeyId(v string) *CreateAliasInput {
s.TargetKeyId = &v
return s
}
type CreateAliasOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateAliasOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateAliasOutput) GoString() string {
return s.String()
}
type CreateCustomKeyStoreInput struct {
_ struct{} `type:"structure"`
// Identifies the CloudHSM cluster for the custom key store. Enter the cluster
// ID of any active CloudHSM cluster that is not already associated with a custom
// key store. To find the cluster ID, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
//
// CloudHsmClusterId is a required field
CloudHsmClusterId *string `min:"19" type:"string" required:"true"`
// Specifies a friendly name for the custom key store. The name must be unique
// in your Amazon Web Services account.
//
// CustomKeyStoreName is a required field
CustomKeyStoreName *string `min:"1" type:"string" required:"true"`
// Enter the password of the kmsuser crypto user (CU) account (https://docs.aws.amazon.com/kms/latest/developerguide/key-store-concepts.html#concept-kmsuser)
// in the specified CloudHSM cluster. KMS logs into the cluster as this user
// to manage key material on your behalf.
//
// The password must be a string of 7 to 32 characters. Its value is case sensitive.
//
// This parameter tells KMS the kmsuser account password; it does not change
// the password in the CloudHSM cluster.
//
// KeyStorePassword is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by CreateCustomKeyStoreInput's
// String and GoString methods.
//
// KeyStorePassword is a required field
KeyStorePassword *string `min:"7" type:"string" required:"true" sensitive:"true"`
// Enter the content of the trust anchor certificate for the cluster. This is
// the content of the customerCA.crt file that you created when you initialized
// the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html).
//
// TrustAnchorCertificate is a required field
TrustAnchorCertificate *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateCustomKeyStoreInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateCustomKeyStoreInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *CreateCustomKeyStoreInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "CreateCustomKeyStoreInput"}
if s.CloudHsmClusterId == nil {
invalidParams.Add(request.NewErrParamRequired("CloudHsmClusterId"))
}
if s.CloudHsmClusterId != nil && len(*s.CloudHsmClusterId) < 19 {
invalidParams.Add(request.NewErrParamMinLen("CloudHsmClusterId", 19))
}
if s.CustomKeyStoreName == nil {
invalidParams.Add(request.NewErrParamRequired("CustomKeyStoreName"))
}
if s.CustomKeyStoreName != nil && len(*s.CustomKeyStoreName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreName", 1))
}
if s.KeyStorePassword == nil {
invalidParams.Add(request.NewErrParamRequired("KeyStorePassword"))
}
if s.KeyStorePassword != nil && len(*s.KeyStorePassword) < 7 {
invalidParams.Add(request.NewErrParamMinLen("KeyStorePassword", 7))
}
if s.TrustAnchorCertificate == nil {
invalidParams.Add(request.NewErrParamRequired("TrustAnchorCertificate"))
}
if s.TrustAnchorCertificate != nil && len(*s.TrustAnchorCertificate) < 1 {
invalidParams.Add(request.NewErrParamMinLen("TrustAnchorCertificate", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCloudHsmClusterId sets the CloudHsmClusterId field's value.
func (s *CreateCustomKeyStoreInput) SetCloudHsmClusterId(v string) *CreateCustomKeyStoreInput {
s.CloudHsmClusterId = &v
return s
}
// SetCustomKeyStoreName sets the CustomKeyStoreName field's value.
func (s *CreateCustomKeyStoreInput) SetCustomKeyStoreName(v string) *CreateCustomKeyStoreInput {
s.CustomKeyStoreName = &v
return s
}
// SetKeyStorePassword sets the KeyStorePassword field's value.
func (s *CreateCustomKeyStoreInput) SetKeyStorePassword(v string) *CreateCustomKeyStoreInput {
s.KeyStorePassword = &v
return s
}
// SetTrustAnchorCertificate sets the TrustAnchorCertificate field's value.
func (s *CreateCustomKeyStoreInput) SetTrustAnchorCertificate(v string) *CreateCustomKeyStoreInput {
s.TrustAnchorCertificate = &v
return s
}
type CreateCustomKeyStoreOutput struct {
_ struct{} `type:"structure"`
// A unique identifier for the new custom key store.
CustomKeyStoreId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateCustomKeyStoreOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateCustomKeyStoreOutput) GoString() string {
return s.String()
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *CreateCustomKeyStoreOutput) SetCustomKeyStoreId(v string) *CreateCustomKeyStoreOutput {
s.CustomKeyStoreId = &v
return s
}
type CreateGrantInput struct {
_ struct{} `type:"structure"`
// Specifies a grant constraint.
//
// KMS supports the EncryptionContextEquals and EncryptionContextSubset grant
// constraints. Each constraint value can include up to 8 encryption context
// pairs. The encryption context value in each constraint cannot exceed 384
// characters. For information about grant constraints, see Using grant constraints
// (https://docs.aws.amazon.com/kms/latest/developerguide/create-grant-overview.html#grant-constraints)
// in the Key Management Service Developer Guide. For more information about
// encryption context, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide .
//
// The encryption context grant constraints allow the permissions in the grant
// only when the encryption context in the request matches (EncryptionContextEquals)
// or includes (EncryptionContextSubset) the encryption context specified in
// this structure.
//
// The encryption context grant constraints are supported only on grant operations
// (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
// that include an EncryptionContext parameter, such as cryptographic operations
// on symmetric encryption KMS keys. Grants with grant constraints can include
// the DescribeKey and RetireGrant operations, but the constraint doesn't apply
// to these operations. If a grant with a grant constraint includes the CreateGrant
// operation, the constraint requires that any grants created with the CreateGrant
// permission have an equally strict or stricter encryption context constraint.
//
// You cannot use an encryption context grant constraint for cryptographic operations
// with asymmetric KMS keys or HMAC KMS keys. These keys don't support an encryption
// context.
Constraints *GrantConstraints `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// The identity that gets the permissions specified in the grant.
//
// To specify the principal, use the Amazon Resource Name (ARN) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// of an Amazon Web Services principal. Valid Amazon Web Services principals
// include Amazon Web Services accounts (root), IAM users, IAM roles, federated
// users, and assumed role users. For examples of the ARN syntax to use for
// specifying a principal, see Amazon Web Services Identity and Access Management
// (IAM) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-iam)
// in the Example ARNs section of the Amazon Web Services General Reference.
//
// GranteePrincipal is a required field
GranteePrincipal *string `min:"1" type:"string" required:"true"`
// Identifies the KMS key for the grant. The grant gives principals permission
// to use this KMS key.
//
// Specify the key ID or key ARN of the KMS key. To specify a KMS key in a different
// Amazon Web Services account, you must use the key ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// A friendly name for the grant. Use this value to prevent the unintended creation
// of duplicate grants when retrying this request.
//
// When this value is absent, all CreateGrant requests result in a new grant
// with a unique GrantId even if all the supplied parameters are identical.
// This can result in unintended duplicates when you retry the CreateGrant request.
//
// When this value is present, you can retry a CreateGrant request with identical
// parameters; if the grant already exists, the original GrantId is returned
// without creating a new grant. Note that the returned grant token is unique
// with every CreateGrant request, even when a duplicate GrantId is returned.
// All grant tokens for the same grant ID can be used interchangeably.
Name *string `min:"1" type:"string"`
// A list of operations that the grant permits.
//
// This list must include only operations that are permitted in a grant. Also,
// the operation must be supported on the KMS key. For example, you cannot create
// a grant for a symmetric encryption KMS key that allows the Sign operation,
// or a grant for an asymmetric KMS key that allows the GenerateDataKey operation.
// If you try, KMS returns a ValidationError exception. For details, see Grant
// operations (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-grant-operations)
// in the Key Management Service Developer Guide.
//
// Operations is a required field
Operations []*string `type:"list" required:"true" enum:"GrantOperation"`
// The principal that has permission to use the RetireGrant operation to retire
// the grant.
//
// To specify the principal, use the Amazon Resource Name (ARN) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// of an Amazon Web Services principal. Valid Amazon Web Services principals
// include Amazon Web Services accounts (root), IAM users, federated users,
// and assumed role users. For examples of the ARN syntax to use for specifying
// a principal, see Amazon Web Services Identity and Access Management (IAM)
// (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-iam)
// in the Example ARNs section of the Amazon Web Services General Reference.
//
// The grant determines the retiring principal. Other principals might have
// permission to retire the grant or revoke the grant. For details, see RevokeGrant
// and Retiring and revoking grants (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#grant-delete)
// in the Key Management Service Developer Guide.
RetiringPrincipal *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateGrantInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateGrantInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *CreateGrantInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "CreateGrantInput"}
if s.GranteePrincipal == nil {
invalidParams.Add(request.NewErrParamRequired("GranteePrincipal"))
}
if s.GranteePrincipal != nil && len(*s.GranteePrincipal) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GranteePrincipal", 1))
}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Name != nil && len(*s.Name) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Name", 1))
}
if s.Operations == nil {
invalidParams.Add(request.NewErrParamRequired("Operations"))
}
if s.RetiringPrincipal != nil && len(*s.RetiringPrincipal) < 1 {
invalidParams.Add(request.NewErrParamMinLen("RetiringPrincipal", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetConstraints sets the Constraints field's value.
func (s *CreateGrantInput) SetConstraints(v *GrantConstraints) *CreateGrantInput {
s.Constraints = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *CreateGrantInput) SetGrantTokens(v []*string) *CreateGrantInput {
s.GrantTokens = v
return s
}
// SetGranteePrincipal sets the GranteePrincipal field's value.
func (s *CreateGrantInput) SetGranteePrincipal(v string) *CreateGrantInput {
s.GranteePrincipal = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *CreateGrantInput) SetKeyId(v string) *CreateGrantInput {
s.KeyId = &v
return s
}
// SetName sets the Name field's value.
func (s *CreateGrantInput) SetName(v string) *CreateGrantInput {
s.Name = &v
return s
}
// SetOperations sets the Operations field's value.
func (s *CreateGrantInput) SetOperations(v []*string) *CreateGrantInput {
s.Operations = v
return s
}
// SetRetiringPrincipal sets the RetiringPrincipal field's value.
func (s *CreateGrantInput) SetRetiringPrincipal(v string) *CreateGrantInput {
s.RetiringPrincipal = &v
return s
}
type CreateGrantOutput struct {
_ struct{} `type:"structure"`
// The unique identifier for the grant.
//
// You can use the GrantId in a ListGrants, RetireGrant, or RevokeGrant operation.
GrantId *string `min:"1" type:"string"`
// The grant token.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantToken *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateGrantOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateGrantOutput) GoString() string {
return s.String()
}
// SetGrantId sets the GrantId field's value.
func (s *CreateGrantOutput) SetGrantId(v string) *CreateGrantOutput {
s.GrantId = &v
return s
}
// SetGrantToken sets the GrantToken field's value.
func (s *CreateGrantOutput) SetGrantToken(v string) *CreateGrantOutput {
s.GrantToken = &v
return s
}
type CreateKeyInput struct {
_ struct{} `type:"structure"`
// A flag to indicate whether to bypass the key policy lockout safety check.
//
// Setting this value to true increases the risk that the KMS key becomes unmanageable.
// Do not set this value to true indiscriminately.
//
// For more information, refer to the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section in the Key Management Service Developer Guide .
//
// Use this parameter only when you include a policy in the request and you
// intend to prevent the principal that is making the request from making a
// subsequent PutKeyPolicy request on the KMS key.
//
// The default value is false.
BypassPolicyLockoutSafetyCheck *bool `type:"boolean"`
// Creates the KMS key in the specified custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// and the key material in its associated CloudHSM cluster. To create a KMS
// key in a custom key store, you must also specify the Origin parameter with
// a value of AWS_CLOUDHSM. The CloudHSM cluster that is associated with the
// custom key store must have at least two active HSMs, each in a different
// Availability Zone in the Region.
//
// This parameter is valid only for symmetric encryption KMS keys in a single
// Region. You cannot create any other type of KMS key in a custom key store.
//
// To find the ID of a custom key store, use the DescribeCustomKeyStores operation.
//
// The response includes the custom key store ID and the ID of the CloudHSM
// cluster.
//
// This operation is part of the Custom Key Store feature (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// feature in KMS, which combines the convenience and extensive integration
// of KMS with the isolation and control of a single-tenant key store.
CustomKeyStoreId *string `min:"1" type:"string"`
// Instead, use the KeySpec parameter.
//
// The KeySpec and CustomerMasterKeySpec parameters work the same way. Only
// the names differ. We recommend that you use KeySpec parameter in your code.
// However, to avoid breaking changes, KMS will support both parameters.
//
// Deprecated: This parameter has been deprecated. Instead, use the KeySpec parameter.
CustomerMasterKeySpec *string `deprecated:"true" type:"string" enum:"CustomerMasterKeySpec"`
// A description of the KMS key.
//
// Use a description that helps you decide whether the KMS key is appropriate
// for a task. The default value is an empty string (no description).
//
// To set or change the description after the key is created, use UpdateKeyDescription.
Description *string `type:"string"`
// Specifies the type of KMS key to create. The default value, SYMMETRIC_DEFAULT,
// creates a KMS key with a 256-bit symmetric key for encryption and decryption.
// For help choosing a key spec for your KMS key, see Choosing a KMS key type
// (https://docs.aws.amazon.com/kms/latest/developerguide/key-types.html#symm-asymm-choose)
// in the Key Management Service Developer Guide .
//
// The KeySpec determines whether the KMS key contains a symmetric key or an
// asymmetric key pair. It also determines the algorithms that the KMS key supports.
// You can't change the KeySpec after the KMS key is created. To further restrict
// the algorithms that can be used with the KMS key, use a condition key in
// its key policy or IAM policy. For more information, see kms:EncryptionAlgorithm
// (https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-encryption-algorithm),
// kms:MacAlgorithm (https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-mac-algorithm)
// or kms:Signing Algorithm (https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-signing-algorithm)
// in the Key Management Service Developer Guide .
//
// Amazon Web Services services that are integrated with KMS (http://aws.amazon.com/kms/features/#AWS_Service_Integration)
// use symmetric encryption KMS keys to protect your data. These services do
// not support asymmetric KMS keys or HMAC KMS keys.
//
// KMS supports the following key specs for KMS keys:
//
// * Symmetric encryption key (default) SYMMETRIC_DEFAULT (AES-256-GCM)
//
// * HMAC keys (symmetric) HMAC_224 HMAC_256 HMAC_384 HMAC_512
//
// * Asymmetric RSA key pairs RSA_2048 RSA_3072 RSA_4096
//
// * Asymmetric NIST-recommended elliptic curve key pairs ECC_NIST_P256 (secp256r1)
// ECC_NIST_P384 (secp384r1) ECC_NIST_P521 (secp521r1)
//
// * Other asymmetric elliptic curve key pairs ECC_SECG_P256K1 (secp256k1),
// commonly used for cryptocurrencies.
KeySpec *string `type:"string" enum:"KeySpec"`
// Determines the cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// for which you can use the KMS key. The default value is ENCRYPT_DECRYPT.
// This parameter is optional when you are creating a symmetric encryption KMS
// key; otherwise, it is required. You can't change the KeyUsage value after
// the KMS key is created.
//
// Select only one valid value.
//
// * For symmetric encryption KMS keys, omit the parameter or specify ENCRYPT_DECRYPT.
//
// * For HMAC KMS keys (symmetric), specify GENERATE_VERIFY_MAC.
//
// * For asymmetric KMS keys with RSA key material, specify ENCRYPT_DECRYPT
// or SIGN_VERIFY.
//
// * For asymmetric KMS keys with ECC key material, specify SIGN_VERIFY.
KeyUsage *string `type:"string" enum:"KeyUsageType"`
// Creates a multi-Region primary key that you can replicate into other Amazon
// Web Services Regions. You cannot change this value after you create the KMS
// key.
//
// For a multi-Region key, set this parameter to True. For a single-Region KMS
// key, omit this parameter or set it to False. The default value is False.
//
// This operation supports multi-Region keys, an KMS feature that lets you create
// multiple interoperable KMS keys in different Amazon Web Services Regions.
// Because these KMS keys have the same key ID, key material, and other metadata,
// you can use them interchangeably to encrypt data in one Amazon Web Services
// Region and decrypt it in a different Amazon Web Services Region without re-encrypting
// the data or making a cross-Region call. For more information about multi-Region
// keys, see Multi-Region keys in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
//
// This value creates a primary key, not a replica. To create a replica key,
// use the ReplicateKey operation.
//
// You can create a symmetric or asymmetric multi-Region key, and you can create
// a multi-Region key with imported key material. However, you cannot create
// a multi-Region key in a custom key store.
MultiRegion *bool `type:"boolean"`
// The source of the key material for the KMS key. You cannot change the origin
// after you create the KMS key. The default is AWS_KMS, which means that KMS
// creates the key material.
//
// To create a KMS key with no key material (for imported key material), set
// the value to EXTERNAL. For more information about importing key material
// into KMS, see Importing Key Material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)
// in the Key Management Service Developer Guide. This value is valid only for
// symmetric encryption KMS keys.
//
// To create a KMS key in an KMS custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// and create its key material in the associated CloudHSM cluster, set this
// value to AWS_CLOUDHSM. You must also use the CustomKeyStoreId parameter to
// identify the custom key store. This value is valid only for symmetric encryption
// KMS keys.
Origin *string `type:"string" enum:"OriginType"`
// The key policy to attach to the KMS key.
//
// If you provide a key policy, it must meet the following criteria:
//
// * If you don't set BypassPolicyLockoutSafetyCheck to true, the key policy
// must allow the principal that is making the CreateKey request to make
// a subsequent PutKeyPolicy request on the KMS key. This reduces the risk
// that the KMS key becomes unmanageable. For more information, refer to
// the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section of the Key Management Service Developer Guide .
//
// * Each statement in the key policy must contain one or more principals.
// The principals in the key policy must exist and be visible to KMS. When
// you create a new Amazon Web Services principal (for example, an IAM user
// or role), you might need to enforce a delay before including the new principal
// in a key policy because the new principal might not be immediately visible
// to KMS. For more information, see Changes that I make are not always immediately
// visible (https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency)
// in the Amazon Web Services Identity and Access Management User Guide.
//
// If you do not provide a key policy, KMS attaches a default key policy to
// the KMS key. For more information, see Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default)
// in the Key Management Service Developer Guide.
//
// The key policy size quota is 32 kilobytes (32768 bytes).
//
// For help writing and formatting a JSON policy document, see the IAM JSON
// Policy Reference (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies.html)
// in the Identity and Access Management User Guide .
Policy *string `min:"1" type:"string"`
// Assigns one or more tags to the KMS key. Use this parameter to tag the KMS
// key when it is created. To tag an existing KMS key, use the TagResource operation.
//
// Tagging or untagging a KMS key can allow or deny permission to the KMS key.
// For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// To use this parameter, you must have kms:TagResource (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// permission in an IAM policy.
//
// Each tag consists of a tag key and a tag value. Both the tag key and the
// tag value are required, but the tag value can be an empty (null) string.
// You cannot have more than one tag on a KMS key with the same tag key. If
// you specify an existing tag key with a different tag value, KMS replaces
// the current tag value with the specified one.
//
// When you add tags to an Amazon Web Services resource, Amazon Web Services
// generates a cost allocation report with usage and costs aggregated by tags.
// Tags can also be used to control access to a KMS key. For details, see Tagging
// Keys (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html).
Tags []*Tag `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *CreateKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "CreateKeyInput"}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.Tags != nil {
for i, v := range s.Tags {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetBypassPolicyLockoutSafetyCheck sets the BypassPolicyLockoutSafetyCheck field's value.
func (s *CreateKeyInput) SetBypassPolicyLockoutSafetyCheck(v bool) *CreateKeyInput {
s.BypassPolicyLockoutSafetyCheck = &v
return s
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *CreateKeyInput) SetCustomKeyStoreId(v string) *CreateKeyInput {
s.CustomKeyStoreId = &v
return s
}
// SetCustomerMasterKeySpec sets the CustomerMasterKeySpec field's value.
func (s *CreateKeyInput) SetCustomerMasterKeySpec(v string) *CreateKeyInput {
s.CustomerMasterKeySpec = &v
return s
}
// SetDescription sets the Description field's value.
func (s *CreateKeyInput) SetDescription(v string) *CreateKeyInput {
s.Description = &v
return s
}
// SetKeySpec sets the KeySpec field's value.
func (s *CreateKeyInput) SetKeySpec(v string) *CreateKeyInput {
s.KeySpec = &v
return s
}
// SetKeyUsage sets the KeyUsage field's value.
func (s *CreateKeyInput) SetKeyUsage(v string) *CreateKeyInput {
s.KeyUsage = &v
return s
}
// SetMultiRegion sets the MultiRegion field's value.
func (s *CreateKeyInput) SetMultiRegion(v bool) *CreateKeyInput {
s.MultiRegion = &v
return s
}
// SetOrigin sets the Origin field's value.
func (s *CreateKeyInput) SetOrigin(v string) *CreateKeyInput {
s.Origin = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *CreateKeyInput) SetPolicy(v string) *CreateKeyInput {
s.Policy = &v
return s
}
// SetTags sets the Tags field's value.
func (s *CreateKeyInput) SetTags(v []*Tag) *CreateKeyInput {
s.Tags = v
return s
}
type CreateKeyOutput struct {
_ struct{} `type:"structure"`
// Metadata associated with the KMS key.
KeyMetadata *KeyMetadata `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CreateKeyOutput) GoString() string {
return s.String()
}
// SetKeyMetadata sets the KeyMetadata field's value.
func (s *CreateKeyOutput) SetKeyMetadata(v *KeyMetadata) *CreateKeyOutput {
s.KeyMetadata = v
return s
}
// The request was rejected because the custom key store contains KMS keys.
// After verifying that you do not need to use the KMS keys, use the ScheduleKeyDeletion
// operation to delete the KMS keys. After they are deleted, you can delete
// the custom key store.
type CustomKeyStoreHasCMKsException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreHasCMKsException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreHasCMKsException) GoString() string {
return s.String()
}
func newErrorCustomKeyStoreHasCMKsException(v protocol.ResponseMetadata) error {
return &CustomKeyStoreHasCMKsException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CustomKeyStoreHasCMKsException) Code() string {
return "CustomKeyStoreHasCMKsException"
}
// Message returns the exception's message.
func (s *CustomKeyStoreHasCMKsException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CustomKeyStoreHasCMKsException) OrigErr() error {
return nil
}
func (s *CustomKeyStoreHasCMKsException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CustomKeyStoreHasCMKsException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CustomKeyStoreHasCMKsException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
type CustomKeyStoreInvalidStateException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreInvalidStateException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreInvalidStateException) GoString() string {
return s.String()
}
func newErrorCustomKeyStoreInvalidStateException(v protocol.ResponseMetadata) error {
return &CustomKeyStoreInvalidStateException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CustomKeyStoreInvalidStateException) Code() string {
return "CustomKeyStoreInvalidStateException"
}
// Message returns the exception's message.
func (s *CustomKeyStoreInvalidStateException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CustomKeyStoreInvalidStateException) OrigErr() error {
return nil
}
func (s *CustomKeyStoreInvalidStateException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CustomKeyStoreInvalidStateException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CustomKeyStoreInvalidStateException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the specified custom key store name is already
// assigned to another custom key store in the account. Try again with a custom
// key store name that is unique in the account.
type CustomKeyStoreNameInUseException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreNameInUseException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreNameInUseException) GoString() string {
return s.String()
}
func newErrorCustomKeyStoreNameInUseException(v protocol.ResponseMetadata) error {
return &CustomKeyStoreNameInUseException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CustomKeyStoreNameInUseException) Code() string {
return "CustomKeyStoreNameInUseException"
}
// Message returns the exception's message.
func (s *CustomKeyStoreNameInUseException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CustomKeyStoreNameInUseException) OrigErr() error {
return nil
}
func (s *CustomKeyStoreNameInUseException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CustomKeyStoreNameInUseException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CustomKeyStoreNameInUseException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
type CustomKeyStoreNotFoundException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreNotFoundException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoreNotFoundException) GoString() string {
return s.String()
}
func newErrorCustomKeyStoreNotFoundException(v protocol.ResponseMetadata) error {
return &CustomKeyStoreNotFoundException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *CustomKeyStoreNotFoundException) Code() string {
return "CustomKeyStoreNotFoundException"
}
// Message returns the exception's message.
func (s *CustomKeyStoreNotFoundException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *CustomKeyStoreNotFoundException) OrigErr() error {
return nil
}
func (s *CustomKeyStoreNotFoundException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *CustomKeyStoreNotFoundException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *CustomKeyStoreNotFoundException) RequestID() string {
return s.RespMetadata.RequestID
}
// Contains information about each custom key store in the custom key store
// list.
type CustomKeyStoresListEntry struct {
_ struct{} `type:"structure"`
// A unique identifier for the CloudHSM cluster that is associated with the
// custom key store.
CloudHsmClusterId *string `min:"19" type:"string"`
// Describes the connection error. This field appears in the response only when
// the ConnectionState is FAILED. For help resolving these errors, see How to
// Fix a Connection Failure (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-failed)
// in Key Management Service Developer Guide.
//
// Valid values are:
//
// * CLUSTER_NOT_FOUND - KMS cannot find the CloudHSM cluster with the specified
// cluster ID.
//
// * INSUFFICIENT_CLOUDHSM_HSMS - The associated CloudHSM cluster does not
// contain any active HSMs. To connect a custom key store to its CloudHSM
// cluster, the cluster must contain at least one active HSM.
//
// * INTERNAL_ERROR - KMS could not complete the request due to an internal
// error. Retry the request. For ConnectCustomKeyStore requests, disconnect
// the custom key store before trying to connect again.
//
// * INVALID_CREDENTIALS - KMS does not have the correct password for the
// kmsuser crypto user in the CloudHSM cluster. Before you can connect your
// custom key store to its CloudHSM cluster, you must change the kmsuser
// account password and update the key store password value for the custom
// key store.
//
// * NETWORK_ERRORS - Network errors are preventing KMS from connecting to
// the custom key store.
//
// * SUBNET_NOT_FOUND - A subnet in the CloudHSM cluster configuration was
// deleted. If KMS cannot find all of the subnets in the cluster configuration,
// attempts to connect the custom key store to the CloudHSM cluster fail.
// To fix this error, create a cluster from a recent backup and associate
// it with your custom key store. (This process creates a new cluster configuration
// with a VPC and private subnets.) For details, see How to Fix a Connection
// Failure (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#fix-keystore-failed)
// in the Key Management Service Developer Guide.
//
// * USER_LOCKED_OUT - The kmsuser CU account is locked out of the associated
// CloudHSM cluster due to too many failed password attempts. Before you
// can connect your custom key store to its CloudHSM cluster, you must change
// the kmsuser account password and update the key store password value for
// the custom key store.
//
// * USER_LOGGED_IN - The kmsuser CU account is logged into the the associated
// CloudHSM cluster. This prevents KMS from rotating the kmsuser account
// password and logging into the cluster. Before you can connect your custom
// key store to its CloudHSM cluster, you must log the kmsuser CU out of
// the cluster. If you changed the kmsuser password to log into the cluster,
// you must also and update the key store password value for the custom key
// store. For help, see How to Log Out and Reconnect (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html#login-kmsuser-2)
// in the Key Management Service Developer Guide.
//
// * USER_NOT_FOUND - KMS cannot find a kmsuser CU account in the associated
// CloudHSM cluster. Before you can connect your custom key store to its
// CloudHSM cluster, you must create a kmsuser CU account in the cluster,
// and then update the key store password value for the custom key store.
ConnectionErrorCode *string `type:"string" enum:"ConnectionErrorCodeType"`
// Indicates whether the custom key store is connected to its CloudHSM cluster.
//
// You can create and use KMS keys in your custom key stores only when its connection
// state is CONNECTED.
//
// The value is DISCONNECTED if the key store has never been connected or you
// use the DisconnectCustomKeyStore operation to disconnect it. If the value
// is CONNECTED but you are having trouble using the custom key store, make
// sure that its associated CloudHSM cluster is active and contains at least
// one active HSM.
//
// A value of FAILED indicates that an attempt to connect was unsuccessful.
// The ConnectionErrorCode field in the response indicates the cause of the
// failure. For help resolving a connection failure, see Troubleshooting a Custom
// Key Store (https://docs.aws.amazon.com/kms/latest/developerguide/fix-keystore.html)
// in the Key Management Service Developer Guide.
ConnectionState *string `type:"string" enum:"ConnectionStateType"`
// The date and time when the custom key store was created.
CreationDate *time.Time `type:"timestamp"`
// A unique identifier for the custom key store.
CustomKeyStoreId *string `min:"1" type:"string"`
// The user-specified friendly name for the custom key store.
CustomKeyStoreName *string `min:"1" type:"string"`
// The trust anchor certificate of the associated CloudHSM cluster. When you
// initialize the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html#sign-csr),
// you create this certificate and save it in the customerCA.crt file.
TrustAnchorCertificate *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoresListEntry) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s CustomKeyStoresListEntry) GoString() string {
return s.String()
}
// SetCloudHsmClusterId sets the CloudHsmClusterId field's value.
func (s *CustomKeyStoresListEntry) SetCloudHsmClusterId(v string) *CustomKeyStoresListEntry {
s.CloudHsmClusterId = &v
return s
}
// SetConnectionErrorCode sets the ConnectionErrorCode field's value.
func (s *CustomKeyStoresListEntry) SetConnectionErrorCode(v string) *CustomKeyStoresListEntry {
s.ConnectionErrorCode = &v
return s
}
// SetConnectionState sets the ConnectionState field's value.
func (s *CustomKeyStoresListEntry) SetConnectionState(v string) *CustomKeyStoresListEntry {
s.ConnectionState = &v
return s
}
// SetCreationDate sets the CreationDate field's value.
func (s *CustomKeyStoresListEntry) SetCreationDate(v time.Time) *CustomKeyStoresListEntry {
s.CreationDate = &v
return s
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *CustomKeyStoresListEntry) SetCustomKeyStoreId(v string) *CustomKeyStoresListEntry {
s.CustomKeyStoreId = &v
return s
}
// SetCustomKeyStoreName sets the CustomKeyStoreName field's value.
func (s *CustomKeyStoresListEntry) SetCustomKeyStoreName(v string) *CustomKeyStoresListEntry {
s.CustomKeyStoreName = &v
return s
}
// SetTrustAnchorCertificate sets the TrustAnchorCertificate field's value.
func (s *CustomKeyStoresListEntry) SetTrustAnchorCertificate(v string) *CustomKeyStoresListEntry {
s.TrustAnchorCertificate = &v
return s
}
type DecryptInput struct {
_ struct{} `type:"structure"`
// Ciphertext to be decrypted. The blob includes metadata.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
//
// CiphertextBlob is a required field
CiphertextBlob []byte `min:"1" type:"blob" required:"true"`
// Specifies the encryption algorithm that will be used to decrypt the ciphertext.
// Specify the same algorithm that was used to encrypt the data. If you specify
// a different algorithm, the Decrypt operation fails.
//
// This parameter is required only when the ciphertext was encrypted under an
// asymmetric KMS key. The default value, SYMMETRIC_DEFAULT, represents the
// only supported algorithm that is valid for symmetric encryption KMS keys.
EncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// Specifies the encryption context to use when decrypting the data. An encryption
// context is valid only for cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// with a symmetric encryption KMS key. The standard asymmetric encryption algorithms
// and HMAC algorithms that KMS uses do not support an encryption context.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the KMS key that KMS uses to decrypt the ciphertext.
//
// Enter a key ID of the KMS key that was used to encrypt the ciphertext. If
// you identify a different KMS key, the Decrypt operation throws an IncorrectKeyException.
//
// This parameter is required only when the ciphertext was encrypted under an
// asymmetric KMS key. If you used a symmetric encryption KMS key, KMS can get
// the KMS key from metadata that it adds to the symmetric ciphertext blob.
// However, it is always recommended as a best practice. This practice ensures
// that you use the KMS key that you intend.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecryptInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecryptInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DecryptInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DecryptInput"}
if s.CiphertextBlob == nil {
invalidParams.Add(request.NewErrParamRequired("CiphertextBlob"))
}
if s.CiphertextBlob != nil && len(s.CiphertextBlob) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CiphertextBlob", 1))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *DecryptInput) SetCiphertextBlob(v []byte) *DecryptInput {
s.CiphertextBlob = v
return s
}
// SetEncryptionAlgorithm sets the EncryptionAlgorithm field's value.
func (s *DecryptInput) SetEncryptionAlgorithm(v string) *DecryptInput {
s.EncryptionAlgorithm = &v
return s
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *DecryptInput) SetEncryptionContext(v map[string]*string) *DecryptInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *DecryptInput) SetGrantTokens(v []*string) *DecryptInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *DecryptInput) SetKeyId(v string) *DecryptInput {
s.KeyId = &v
return s
}
type DecryptOutput struct {
_ struct{} `type:"structure"`
// The encryption algorithm that was used to decrypt the ciphertext.
EncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that was used to decrypt the ciphertext.
KeyId *string `min:"1" type:"string"`
// Decrypted plaintext data. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
//
// Plaintext is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by DecryptOutput's
// String and GoString methods.
//
// Plaintext is automatically base64 encoded/decoded by the SDK.
Plaintext []byte `min:"1" type:"blob" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecryptOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecryptOutput) GoString() string {
return s.String()
}
// SetEncryptionAlgorithm sets the EncryptionAlgorithm field's value.
func (s *DecryptOutput) SetEncryptionAlgorithm(v string) *DecryptOutput {
s.EncryptionAlgorithm = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *DecryptOutput) SetKeyId(v string) *DecryptOutput {
s.KeyId = &v
return s
}
// SetPlaintext sets the Plaintext field's value.
func (s *DecryptOutput) SetPlaintext(v []byte) *DecryptOutput {
s.Plaintext = v
return s
}
type DeleteAliasInput struct {
_ struct{} `type:"structure"`
// The alias to be deleted. The alias name must begin with alias/ followed by
// the alias name, such as alias/ExampleAlias.
//
// AliasName is a required field
AliasName *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteAliasInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteAliasInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DeleteAliasInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DeleteAliasInput"}
if s.AliasName == nil {
invalidParams.Add(request.NewErrParamRequired("AliasName"))
}
if s.AliasName != nil && len(*s.AliasName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("AliasName", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAliasName sets the AliasName field's value.
func (s *DeleteAliasInput) SetAliasName(v string) *DeleteAliasInput {
s.AliasName = &v
return s
}
type DeleteAliasOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteAliasOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteAliasOutput) GoString() string {
return s.String()
}
type DeleteCustomKeyStoreInput struct {
_ struct{} `type:"structure"`
// Enter the ID of the custom key store you want to delete. To find the ID of
// a custom key store, use the DescribeCustomKeyStores operation.
//
// CustomKeyStoreId is a required field
CustomKeyStoreId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteCustomKeyStoreInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteCustomKeyStoreInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DeleteCustomKeyStoreInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DeleteCustomKeyStoreInput"}
if s.CustomKeyStoreId == nil {
invalidParams.Add(request.NewErrParamRequired("CustomKeyStoreId"))
}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *DeleteCustomKeyStoreInput) SetCustomKeyStoreId(v string) *DeleteCustomKeyStoreInput {
s.CustomKeyStoreId = &v
return s
}
type DeleteCustomKeyStoreOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteCustomKeyStoreOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteCustomKeyStoreOutput) GoString() string {
return s.String()
}
type DeleteImportedKeyMaterialInput struct {
_ struct{} `type:"structure"`
// Identifies the KMS key from which you are deleting imported key material.
// The Origin of the KMS key must be EXTERNAL.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteImportedKeyMaterialInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteImportedKeyMaterialInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DeleteImportedKeyMaterialInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DeleteImportedKeyMaterialInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *DeleteImportedKeyMaterialInput) SetKeyId(v string) *DeleteImportedKeyMaterialInput {
s.KeyId = &v
return s
}
type DeleteImportedKeyMaterialOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteImportedKeyMaterialOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DeleteImportedKeyMaterialOutput) GoString() string {
return s.String()
}
// The system timed out while trying to fulfill the request. The request can
// be retried.
type DependencyTimeoutException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DependencyTimeoutException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DependencyTimeoutException) GoString() string {
return s.String()
}
func newErrorDependencyTimeoutException(v protocol.ResponseMetadata) error {
return &DependencyTimeoutException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *DependencyTimeoutException) Code() string {
return "DependencyTimeoutException"
}
// Message returns the exception's message.
func (s *DependencyTimeoutException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *DependencyTimeoutException) OrigErr() error {
return nil
}
func (s *DependencyTimeoutException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *DependencyTimeoutException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *DependencyTimeoutException) RequestID() string {
return s.RespMetadata.RequestID
}
type DescribeCustomKeyStoresInput struct {
_ struct{} `type:"structure"`
// Gets only information about the specified custom key store. Enter the key
// store ID.
//
// By default, this operation gets information about all custom key stores in
// the account and Region. To limit the output to a particular custom key store,
// you can use either the CustomKeyStoreId or CustomKeyStoreName parameter,
// but not both.
CustomKeyStoreId *string `min:"1" type:"string"`
// Gets only information about the specified custom key store. Enter the friendly
// name of the custom key store.
//
// By default, this operation gets information about all custom key stores in
// the account and Region. To limit the output to a particular custom key store,
// you can use either the CustomKeyStoreId or CustomKeyStoreName parameter,
// but not both.
CustomKeyStoreName *string `min:"1" type:"string"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeCustomKeyStoresInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeCustomKeyStoresInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DescribeCustomKeyStoresInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DescribeCustomKeyStoresInput"}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if s.CustomKeyStoreName != nil && len(*s.CustomKeyStoreName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreName", 1))
}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *DescribeCustomKeyStoresInput) SetCustomKeyStoreId(v string) *DescribeCustomKeyStoresInput {
s.CustomKeyStoreId = &v
return s
}
// SetCustomKeyStoreName sets the CustomKeyStoreName field's value.
func (s *DescribeCustomKeyStoresInput) SetCustomKeyStoreName(v string) *DescribeCustomKeyStoresInput {
s.CustomKeyStoreName = &v
return s
}
// SetLimit sets the Limit field's value.
func (s *DescribeCustomKeyStoresInput) SetLimit(v int64) *DescribeCustomKeyStoresInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *DescribeCustomKeyStoresInput) SetMarker(v string) *DescribeCustomKeyStoresInput {
s.Marker = &v
return s
}
type DescribeCustomKeyStoresOutput struct {
_ struct{} `type:"structure"`
// Contains metadata about each custom key store.
CustomKeyStores []*CustomKeyStoresListEntry `type:"list"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
NextMarker *string `min:"1" type:"string"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeCustomKeyStoresOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeCustomKeyStoresOutput) GoString() string {
return s.String()
}
// SetCustomKeyStores sets the CustomKeyStores field's value.
func (s *DescribeCustomKeyStoresOutput) SetCustomKeyStores(v []*CustomKeyStoresListEntry) *DescribeCustomKeyStoresOutput {
s.CustomKeyStores = v
return s
}
// SetNextMarker sets the NextMarker field's value.
func (s *DescribeCustomKeyStoresOutput) SetNextMarker(v string) *DescribeCustomKeyStoresOutput {
s.NextMarker = &v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *DescribeCustomKeyStoresOutput) SetTruncated(v bool) *DescribeCustomKeyStoresOutput {
s.Truncated = &v
return s
}
type DescribeKeyInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Describes the specified KMS key.
//
// If you specify a predefined Amazon Web Services alias (an Amazon Web Services
// alias with no key ID), KMS associates the alias with an Amazon Web Services
// managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html##aws-managed-cmk)
// and returns its KeyId and Arn in the response.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DescribeKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DescribeKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *DescribeKeyInput) SetGrantTokens(v []*string) *DescribeKeyInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *DescribeKeyInput) SetKeyId(v string) *DescribeKeyInput {
s.KeyId = &v
return s
}
type DescribeKeyOutput struct {
_ struct{} `type:"structure"`
// Metadata associated with the key.
KeyMetadata *KeyMetadata `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DescribeKeyOutput) GoString() string {
return s.String()
}
// SetKeyMetadata sets the KeyMetadata field's value.
func (s *DescribeKeyOutput) SetKeyMetadata(v *KeyMetadata) *DescribeKeyOutput {
s.KeyMetadata = v
return s
}
type DisableKeyInput struct {
_ struct{} `type:"structure"`
// Identifies the KMS key to disable.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DisableKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DisableKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *DisableKeyInput) SetKeyId(v string) *DisableKeyInput {
s.KeyId = &v
return s
}
type DisableKeyOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyOutput) GoString() string {
return s.String()
}
type DisableKeyRotationInput struct {
_ struct{} `type:"structure"`
// Identifies a symmetric encryption KMS key. You cannot enable or disable automatic
// rotation of asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html#asymmetric-cmks),
// HMAC KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html),
// KMS keys with imported key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html),
// or KMS keys in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyRotationInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyRotationInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DisableKeyRotationInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DisableKeyRotationInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *DisableKeyRotationInput) SetKeyId(v string) *DisableKeyRotationInput {
s.KeyId = &v
return s
}
type DisableKeyRotationOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyRotationOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisableKeyRotationOutput) GoString() string {
return s.String()
}
// The request was rejected because the specified KMS key is not enabled.
type DisabledException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisabledException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisabledException) GoString() string {
return s.String()
}
func newErrorDisabledException(v protocol.ResponseMetadata) error {
return &DisabledException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *DisabledException) Code() string {
return "DisabledException"
}
// Message returns the exception's message.
func (s *DisabledException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *DisabledException) OrigErr() error {
return nil
}
func (s *DisabledException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *DisabledException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *DisabledException) RequestID() string {
return s.RespMetadata.RequestID
}
type DisconnectCustomKeyStoreInput struct {
_ struct{} `type:"structure"`
// Enter the ID of the custom key store you want to disconnect. To find the
// ID of a custom key store, use the DescribeCustomKeyStores operation.
//
// CustomKeyStoreId is a required field
CustomKeyStoreId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisconnectCustomKeyStoreInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisconnectCustomKeyStoreInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DisconnectCustomKeyStoreInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DisconnectCustomKeyStoreInput"}
if s.CustomKeyStoreId == nil {
invalidParams.Add(request.NewErrParamRequired("CustomKeyStoreId"))
}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *DisconnectCustomKeyStoreInput) SetCustomKeyStoreId(v string) *DisconnectCustomKeyStoreInput {
s.CustomKeyStoreId = &v
return s
}
type DisconnectCustomKeyStoreOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisconnectCustomKeyStoreOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DisconnectCustomKeyStoreOutput) GoString() string {
return s.String()
}
type EnableKeyInput struct {
_ struct{} `type:"structure"`
// Identifies the KMS key to enable.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *EnableKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "EnableKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *EnableKeyInput) SetKeyId(v string) *EnableKeyInput {
s.KeyId = &v
return s
}
type EnableKeyOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyOutput) GoString() string {
return s.String()
}
type EnableKeyRotationInput struct {
_ struct{} `type:"structure"`
// Identifies a symmetric encryption KMS key. You cannot enable automatic rotation
// of asymmetric KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/symmetric-asymmetric.html),
// HMAC KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html),
// KMS keys with imported key material (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html),
// or KMS keys in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// To enable or disable automatic rotation of a set of related multi-Region
// keys (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-manage.html#multi-region-rotate),
// set the property on the primary key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyRotationInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyRotationInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *EnableKeyRotationInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "EnableKeyRotationInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *EnableKeyRotationInput) SetKeyId(v string) *EnableKeyRotationInput {
s.KeyId = &v
return s
}
type EnableKeyRotationOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyRotationOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EnableKeyRotationOutput) GoString() string {
return s.String()
}
type EncryptInput struct {
_ struct{} `type:"structure"`
// Specifies the encryption algorithm that KMS will use to encrypt the plaintext
// message. The algorithm must be compatible with the KMS key that you specify.
//
// This parameter is required only for asymmetric KMS keys. The default value,
// SYMMETRIC_DEFAULT, is the algorithm used for symmetric encryption KMS keys.
// If you are using an asymmetric KMS key, we recommend RSAES_OAEP_SHA_256.
EncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// Specifies the encryption context that will be used to encrypt the data. An
// encryption context is valid only for cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// with a symmetric encryption KMS key. The standard asymmetric encryption algorithms
// and HMAC algorithms that KMS uses do not support an encryption context.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Identifies the KMS key to use in the encryption operation. The KMS key must
// have a KeyUsage of ENCRYPT_DECRYPT. To find the KeyUsage of a KMS key, use
// the DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Data to be encrypted.
//
// Plaintext is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by EncryptInput's
// String and GoString methods.
//
// Plaintext is automatically base64 encoded/decoded by the SDK.
//
// Plaintext is a required field
Plaintext []byte `min:"1" type:"blob" required:"true" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EncryptInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EncryptInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *EncryptInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "EncryptInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Plaintext == nil {
invalidParams.Add(request.NewErrParamRequired("Plaintext"))
}
if s.Plaintext != nil && len(s.Plaintext) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Plaintext", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptionAlgorithm sets the EncryptionAlgorithm field's value.
func (s *EncryptInput) SetEncryptionAlgorithm(v string) *EncryptInput {
s.EncryptionAlgorithm = &v
return s
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *EncryptInput) SetEncryptionContext(v map[string]*string) *EncryptInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *EncryptInput) SetGrantTokens(v []*string) *EncryptInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *EncryptInput) SetKeyId(v string) *EncryptInput {
s.KeyId = &v
return s
}
// SetPlaintext sets the Plaintext field's value.
func (s *EncryptInput) SetPlaintext(v []byte) *EncryptInput {
s.Plaintext = v
return s
}
type EncryptOutput struct {
_ struct{} `type:"structure"`
// The encrypted plaintext. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
CiphertextBlob []byte `min:"1" type:"blob"`
// The encryption algorithm that was used to encrypt the plaintext.
EncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that was used to encrypt the plaintext.
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EncryptOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s EncryptOutput) GoString() string {
return s.String()
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *EncryptOutput) SetCiphertextBlob(v []byte) *EncryptOutput {
s.CiphertextBlob = v
return s
}
// SetEncryptionAlgorithm sets the EncryptionAlgorithm field's value.
func (s *EncryptOutput) SetEncryptionAlgorithm(v string) *EncryptOutput {
s.EncryptionAlgorithm = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *EncryptOutput) SetKeyId(v string) *EncryptOutput {
s.KeyId = &v
return s
}
// The request was rejected because the specified import token is expired. Use
// GetParametersForImport to get a new import token and public key, use the
// new public key to encrypt the key material, and then try the request again.
type ExpiredImportTokenException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ExpiredImportTokenException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ExpiredImportTokenException) GoString() string {
return s.String()
}
func newErrorExpiredImportTokenException(v protocol.ResponseMetadata) error {
return &ExpiredImportTokenException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *ExpiredImportTokenException) Code() string {
return "ExpiredImportTokenException"
}
// Message returns the exception's message.
func (s *ExpiredImportTokenException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *ExpiredImportTokenException) OrigErr() error {
return nil
}
func (s *ExpiredImportTokenException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *ExpiredImportTokenException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *ExpiredImportTokenException) RequestID() string {
return s.RespMetadata.RequestID
}
type GenerateDataKeyInput struct {
_ struct{} `type:"structure"`
// Specifies the encryption context that will be used when encrypting the data
// key.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the symmetric encryption KMS key that encrypts the data key. You
// cannot specify an asymmetric KMS key or a KMS key in a custom key store.
// To get the type and origin of your KMS key, use the DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Specifies the length of the data key. Use AES_128 to generate a 128-bit symmetric
// key, or AES_256 to generate a 256-bit symmetric key.
//
// You must specify either the KeySpec or the NumberOfBytes parameter (but not
// both) in every GenerateDataKey request.
KeySpec *string `type:"string" enum:"DataKeySpec"`
// Specifies the length of the data key in bytes. For example, use the value
// 64 to generate a 512-bit data key (64 bytes is 512 bits). For 128-bit (16-byte)
// and 256-bit (32-byte) data keys, use the KeySpec parameter.
//
// You must specify either the KeySpec or the NumberOfBytes parameter (but not
// both) in every GenerateDataKey request.
NumberOfBytes *int64 `min:"1" type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateDataKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateDataKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.NumberOfBytes != nil && *s.NumberOfBytes < 1 {
invalidParams.Add(request.NewErrParamMinValue("NumberOfBytes", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *GenerateDataKeyInput) SetEncryptionContext(v map[string]*string) *GenerateDataKeyInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GenerateDataKeyInput) SetGrantTokens(v []*string) *GenerateDataKeyInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyInput) SetKeyId(v string) *GenerateDataKeyInput {
s.KeyId = &v
return s
}
// SetKeySpec sets the KeySpec field's value.
func (s *GenerateDataKeyInput) SetKeySpec(v string) *GenerateDataKeyInput {
s.KeySpec = &v
return s
}
// SetNumberOfBytes sets the NumberOfBytes field's value.
func (s *GenerateDataKeyInput) SetNumberOfBytes(v int64) *GenerateDataKeyInput {
s.NumberOfBytes = &v
return s
}
type GenerateDataKeyOutput struct {
_ struct{} `type:"structure"`
// The encrypted copy of the data key. When you use the HTTP API or the Amazon
// Web Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
CiphertextBlob []byte `min:"1" type:"blob"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that encrypted the data key.
KeyId *string `min:"1" type:"string"`
// The plaintext data key. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded. Use
// this data key to encrypt your data outside of KMS. Then, remove it from memory
// as soon as possible.
//
// Plaintext is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GenerateDataKeyOutput's
// String and GoString methods.
//
// Plaintext is automatically base64 encoded/decoded by the SDK.
Plaintext []byte `min:"1" type:"blob" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyOutput) GoString() string {
return s.String()
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *GenerateDataKeyOutput) SetCiphertextBlob(v []byte) *GenerateDataKeyOutput {
s.CiphertextBlob = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyOutput) SetKeyId(v string) *GenerateDataKeyOutput {
s.KeyId = &v
return s
}
// SetPlaintext sets the Plaintext field's value.
func (s *GenerateDataKeyOutput) SetPlaintext(v []byte) *GenerateDataKeyOutput {
s.Plaintext = v
return s
}
type GenerateDataKeyPairInput struct {
_ struct{} `type:"structure"`
// Specifies the encryption context that will be used when encrypting the private
// key in the data key pair.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the symmetric encryption KMS key that encrypts the private key
// in the data key pair. You cannot specify an asymmetric KMS key or a KMS key
// in a custom key store. To get the type and origin of your KMS key, use the
// DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Determines the type of data key pair that is generated.
//
// The KMS rule that restricts the use of asymmetric RSA KMS keys to encrypt
// and decrypt or to sign and verify (but not both), and the rule that permits
// you to use ECC KMS keys only to sign and verify, are not effective on data
// key pairs, which are used outside of KMS.
//
// KeyPairSpec is a required field
KeyPairSpec *string `type:"string" required:"true" enum:"DataKeyPairSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateDataKeyPairInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateDataKeyPairInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.KeyPairSpec == nil {
invalidParams.Add(request.NewErrParamRequired("KeyPairSpec"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *GenerateDataKeyPairInput) SetEncryptionContext(v map[string]*string) *GenerateDataKeyPairInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GenerateDataKeyPairInput) SetGrantTokens(v []*string) *GenerateDataKeyPairInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyPairInput) SetKeyId(v string) *GenerateDataKeyPairInput {
s.KeyId = &v
return s
}
// SetKeyPairSpec sets the KeyPairSpec field's value.
func (s *GenerateDataKeyPairInput) SetKeyPairSpec(v string) *GenerateDataKeyPairInput {
s.KeyPairSpec = &v
return s
}
type GenerateDataKeyPairOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that encrypted the private key.
KeyId *string `min:"1" type:"string"`
// The type of data key pair that was generated.
KeyPairSpec *string `type:"string" enum:"DataKeyPairSpec"`
// The encrypted copy of the private key. When you use the HTTP API or the Amazon
// Web Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// PrivateKeyCiphertextBlob is automatically base64 encoded/decoded by the SDK.
PrivateKeyCiphertextBlob []byte `min:"1" type:"blob"`
// The plaintext copy of the private key. When you use the HTTP API or the Amazon
// Web Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
//
// PrivateKeyPlaintext is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GenerateDataKeyPairOutput's
// String and GoString methods.
//
// PrivateKeyPlaintext is automatically base64 encoded/decoded by the SDK.
PrivateKeyPlaintext []byte `min:"1" type:"blob" sensitive:"true"`
// The public key (in plaintext). When you use the HTTP API or the Amazon Web
// Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// PublicKey is automatically base64 encoded/decoded by the SDK.
PublicKey []byte `min:"1" type:"blob"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyPairOutput) SetKeyId(v string) *GenerateDataKeyPairOutput {
s.KeyId = &v
return s
}
// SetKeyPairSpec sets the KeyPairSpec field's value.
func (s *GenerateDataKeyPairOutput) SetKeyPairSpec(v string) *GenerateDataKeyPairOutput {
s.KeyPairSpec = &v
return s
}
// SetPrivateKeyCiphertextBlob sets the PrivateKeyCiphertextBlob field's value.
func (s *GenerateDataKeyPairOutput) SetPrivateKeyCiphertextBlob(v []byte) *GenerateDataKeyPairOutput {
s.PrivateKeyCiphertextBlob = v
return s
}
// SetPrivateKeyPlaintext sets the PrivateKeyPlaintext field's value.
func (s *GenerateDataKeyPairOutput) SetPrivateKeyPlaintext(v []byte) *GenerateDataKeyPairOutput {
s.PrivateKeyPlaintext = v
return s
}
// SetPublicKey sets the PublicKey field's value.
func (s *GenerateDataKeyPairOutput) SetPublicKey(v []byte) *GenerateDataKeyPairOutput {
s.PublicKey = v
return s
}
type GenerateDataKeyPairWithoutPlaintextInput struct {
_ struct{} `type:"structure"`
// Specifies the encryption context that will be used when encrypting the private
// key in the data key pair.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the symmetric encryption KMS key that encrypts the private key
// in the data key pair. You cannot specify an asymmetric KMS key or a KMS key
// in a custom key store. To get the type and origin of your KMS key, use the
// DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Determines the type of data key pair that is generated.
//
// The KMS rule that restricts the use of asymmetric RSA KMS keys to encrypt
// and decrypt or to sign and verify (but not both), and the rule that permits
// you to use ECC KMS keys only to sign and verify, are not effective on data
// key pairs, which are used outside of KMS.
//
// KeyPairSpec is a required field
KeyPairSpec *string `type:"string" required:"true" enum:"DataKeyPairSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairWithoutPlaintextInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairWithoutPlaintextInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateDataKeyPairWithoutPlaintextInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateDataKeyPairWithoutPlaintextInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.KeyPairSpec == nil {
invalidParams.Add(request.NewErrParamRequired("KeyPairSpec"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *GenerateDataKeyPairWithoutPlaintextInput) SetEncryptionContext(v map[string]*string) *GenerateDataKeyPairWithoutPlaintextInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GenerateDataKeyPairWithoutPlaintextInput) SetGrantTokens(v []*string) *GenerateDataKeyPairWithoutPlaintextInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyPairWithoutPlaintextInput) SetKeyId(v string) *GenerateDataKeyPairWithoutPlaintextInput {
s.KeyId = &v
return s
}
// SetKeyPairSpec sets the KeyPairSpec field's value.
func (s *GenerateDataKeyPairWithoutPlaintextInput) SetKeyPairSpec(v string) *GenerateDataKeyPairWithoutPlaintextInput {
s.KeyPairSpec = &v
return s
}
type GenerateDataKeyPairWithoutPlaintextOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that encrypted the private key.
KeyId *string `min:"1" type:"string"`
// The type of data key pair that was generated.
KeyPairSpec *string `type:"string" enum:"DataKeyPairSpec"`
// The encrypted copy of the private key. When you use the HTTP API or the Amazon
// Web Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// PrivateKeyCiphertextBlob is automatically base64 encoded/decoded by the SDK.
PrivateKeyCiphertextBlob []byte `min:"1" type:"blob"`
// The public key (in plaintext). When you use the HTTP API or the Amazon Web
// Services CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// PublicKey is automatically base64 encoded/decoded by the SDK.
PublicKey []byte `min:"1" type:"blob"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairWithoutPlaintextOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyPairWithoutPlaintextOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyPairWithoutPlaintextOutput) SetKeyId(v string) *GenerateDataKeyPairWithoutPlaintextOutput {
s.KeyId = &v
return s
}
// SetKeyPairSpec sets the KeyPairSpec field's value.
func (s *GenerateDataKeyPairWithoutPlaintextOutput) SetKeyPairSpec(v string) *GenerateDataKeyPairWithoutPlaintextOutput {
s.KeyPairSpec = &v
return s
}
// SetPrivateKeyCiphertextBlob sets the PrivateKeyCiphertextBlob field's value.
func (s *GenerateDataKeyPairWithoutPlaintextOutput) SetPrivateKeyCiphertextBlob(v []byte) *GenerateDataKeyPairWithoutPlaintextOutput {
s.PrivateKeyCiphertextBlob = v
return s
}
// SetPublicKey sets the PublicKey field's value.
func (s *GenerateDataKeyPairWithoutPlaintextOutput) SetPublicKey(v []byte) *GenerateDataKeyPairWithoutPlaintextOutput {
s.PublicKey = v
return s
}
type GenerateDataKeyWithoutPlaintextInput struct {
_ struct{} `type:"structure"`
// Specifies the encryption context that will be used when encrypting the data
// key.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
EncryptionContext map[string]*string `type:"map"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the symmetric encryption KMS key that encrypts the data key. You
// cannot specify an asymmetric KMS key or a KMS key in a custom key store.
// To get the type and origin of your KMS key, use the DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The length of the data key. Use AES_128 to generate a 128-bit symmetric key,
// or AES_256 to generate a 256-bit symmetric key.
KeySpec *string `type:"string" enum:"DataKeySpec"`
// The length of the data key in bytes. For example, use the value 64 to generate
// a 512-bit data key (64 bytes is 512 bits). For common key lengths (128-bit
// and 256-bit symmetric keys), we recommend that you use the KeySpec field
// instead of this one.
NumberOfBytes *int64 `min:"1" type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyWithoutPlaintextInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyWithoutPlaintextInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateDataKeyWithoutPlaintextInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateDataKeyWithoutPlaintextInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.NumberOfBytes != nil && *s.NumberOfBytes < 1 {
invalidParams.Add(request.NewErrParamMinValue("NumberOfBytes", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptionContext sets the EncryptionContext field's value.
func (s *GenerateDataKeyWithoutPlaintextInput) SetEncryptionContext(v map[string]*string) *GenerateDataKeyWithoutPlaintextInput {
s.EncryptionContext = v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GenerateDataKeyWithoutPlaintextInput) SetGrantTokens(v []*string) *GenerateDataKeyWithoutPlaintextInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyWithoutPlaintextInput) SetKeyId(v string) *GenerateDataKeyWithoutPlaintextInput {
s.KeyId = &v
return s
}
// SetKeySpec sets the KeySpec field's value.
func (s *GenerateDataKeyWithoutPlaintextInput) SetKeySpec(v string) *GenerateDataKeyWithoutPlaintextInput {
s.KeySpec = &v
return s
}
// SetNumberOfBytes sets the NumberOfBytes field's value.
func (s *GenerateDataKeyWithoutPlaintextInput) SetNumberOfBytes(v int64) *GenerateDataKeyWithoutPlaintextInput {
s.NumberOfBytes = &v
return s
}
type GenerateDataKeyWithoutPlaintextOutput struct {
_ struct{} `type:"structure"`
// The encrypted data key. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
CiphertextBlob []byte `min:"1" type:"blob"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that encrypted the data key.
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyWithoutPlaintextOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateDataKeyWithoutPlaintextOutput) GoString() string {
return s.String()
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *GenerateDataKeyWithoutPlaintextOutput) SetCiphertextBlob(v []byte) *GenerateDataKeyWithoutPlaintextOutput {
s.CiphertextBlob = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateDataKeyWithoutPlaintextOutput) SetKeyId(v string) *GenerateDataKeyWithoutPlaintextOutput {
s.KeyId = &v
return s
}
type GenerateMacInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// The HMAC KMS key to use in the operation. The MAC algorithm computes the
// HMAC for the message and the key as described in RFC 2104 (https://datatracker.ietf.org/doc/html/rfc2104).
//
// To identify an HMAC KMS key, use the DescribeKey operation and see the KeySpec
// field in the response.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The MAC algorithm used in the operation.
//
// The algorithm must be compatible with the HMAC KMS key that you specify.
// To find the MAC algorithms that your HMAC KMS key supports, use the DescribeKey
// operation and see the MacAlgorithms field in the DescribeKey response.
//
// MacAlgorithm is a required field
MacAlgorithm *string `type:"string" required:"true" enum:"MacAlgorithmSpec"`
// The message to be hashed. Specify a message of up to 4,096 bytes.
//
// GenerateMac and VerifyMac do not provide special handling for message digests.
// If you generate an HMAC for a hash digest of a message, you must verify the
// HMAC of the same hash digest.
//
// Message is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GenerateMacInput's
// String and GoString methods.
//
// Message is automatically base64 encoded/decoded by the SDK.
//
// Message is a required field
Message []byte `min:"1" type:"blob" required:"true" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateMacInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateMacInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateMacInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateMacInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.MacAlgorithm == nil {
invalidParams.Add(request.NewErrParamRequired("MacAlgorithm"))
}
if s.Message == nil {
invalidParams.Add(request.NewErrParamRequired("Message"))
}
if s.Message != nil && len(s.Message) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Message", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GenerateMacInput) SetGrantTokens(v []*string) *GenerateMacInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateMacInput) SetKeyId(v string) *GenerateMacInput {
s.KeyId = &v
return s
}
// SetMacAlgorithm sets the MacAlgorithm field's value.
func (s *GenerateMacInput) SetMacAlgorithm(v string) *GenerateMacInput {
s.MacAlgorithm = &v
return s
}
// SetMessage sets the Message field's value.
func (s *GenerateMacInput) SetMessage(v []byte) *GenerateMacInput {
s.Message = v
return s
}
type GenerateMacOutput struct {
_ struct{} `type:"structure"`
// The HMAC KMS key used in the operation.
KeyId *string `min:"1" type:"string"`
// The hash-based message authentication code (HMAC) for the given message,
// key, and MAC algorithm.
// Mac is automatically base64 encoded/decoded by the SDK.
Mac []byte `min:"1" type:"blob"`
// The MAC algorithm that was used to generate the HMAC.
MacAlgorithm *string `type:"string" enum:"MacAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateMacOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateMacOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *GenerateMacOutput) SetKeyId(v string) *GenerateMacOutput {
s.KeyId = &v
return s
}
// SetMac sets the Mac field's value.
func (s *GenerateMacOutput) SetMac(v []byte) *GenerateMacOutput {
s.Mac = v
return s
}
// SetMacAlgorithm sets the MacAlgorithm field's value.
func (s *GenerateMacOutput) SetMacAlgorithm(v string) *GenerateMacOutput {
s.MacAlgorithm = &v
return s
}
type GenerateRandomInput struct {
_ struct{} `type:"structure"`
// Generates the random byte string in the CloudHSM cluster that is associated
// with the specified custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html).
// To find the ID of a custom key store, use the DescribeCustomKeyStores operation.
CustomKeyStoreId *string `min:"1" type:"string"`
// The length of the byte string.
NumberOfBytes *int64 `min:"1" type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateRandomInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateRandomInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GenerateRandomInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GenerateRandomInput"}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if s.NumberOfBytes != nil && *s.NumberOfBytes < 1 {
invalidParams.Add(request.NewErrParamMinValue("NumberOfBytes", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *GenerateRandomInput) SetCustomKeyStoreId(v string) *GenerateRandomInput {
s.CustomKeyStoreId = &v
return s
}
// SetNumberOfBytes sets the NumberOfBytes field's value.
func (s *GenerateRandomInput) SetNumberOfBytes(v int64) *GenerateRandomInput {
s.NumberOfBytes = &v
return s
}
type GenerateRandomOutput struct {
_ struct{} `type:"structure"`
// The random byte string. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
//
// Plaintext is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GenerateRandomOutput's
// String and GoString methods.
//
// Plaintext is automatically base64 encoded/decoded by the SDK.
Plaintext []byte `min:"1" type:"blob" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateRandomOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GenerateRandomOutput) GoString() string {
return s.String()
}
// SetPlaintext sets the Plaintext field's value.
func (s *GenerateRandomOutput) SetPlaintext(v []byte) *GenerateRandomOutput {
s.Plaintext = v
return s
}
type GetKeyPolicyInput struct {
_ struct{} `type:"structure"`
// Gets the key policy for the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Specifies the name of the key policy. The only valid name is default. To
// get the names of key policies, use ListKeyPolicies.
//
// PolicyName is a required field
PolicyName *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyPolicyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyPolicyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetKeyPolicyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetKeyPolicyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.PolicyName == nil {
invalidParams.Add(request.NewErrParamRequired("PolicyName"))
}
if s.PolicyName != nil && len(*s.PolicyName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("PolicyName", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *GetKeyPolicyInput) SetKeyId(v string) *GetKeyPolicyInput {
s.KeyId = &v
return s
}
// SetPolicyName sets the PolicyName field's value.
func (s *GetKeyPolicyInput) SetPolicyName(v string) *GetKeyPolicyInput {
s.PolicyName = &v
return s
}
type GetKeyPolicyOutput struct {
_ struct{} `type:"structure"`
// A key policy document in JSON format.
Policy *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyPolicyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyPolicyOutput) GoString() string {
return s.String()
}
// SetPolicy sets the Policy field's value.
func (s *GetKeyPolicyOutput) SetPolicy(v string) *GetKeyPolicyOutput {
s.Policy = &v
return s
}
type GetKeyRotationStatusInput struct {
_ struct{} `type:"structure"`
// Gets the rotation status for the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key. To specify a KMS key in a different
// Amazon Web Services account, you must use the key ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyRotationStatusInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyRotationStatusInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetKeyRotationStatusInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetKeyRotationStatusInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *GetKeyRotationStatusInput) SetKeyId(v string) *GetKeyRotationStatusInput {
s.KeyId = &v
return s
}
type GetKeyRotationStatusOutput struct {
_ struct{} `type:"structure"`
// A Boolean value that specifies whether key rotation is enabled.
KeyRotationEnabled *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyRotationStatusOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetKeyRotationStatusOutput) GoString() string {
return s.String()
}
// SetKeyRotationEnabled sets the KeyRotationEnabled field's value.
func (s *GetKeyRotationStatusOutput) SetKeyRotationEnabled(v bool) *GetKeyRotationStatusOutput {
s.KeyRotationEnabled = &v
return s
}
type GetParametersForImportInput struct {
_ struct{} `type:"structure"`
// The identifier of the symmetric encryption KMS key into which you will import
// key material. The Origin of the KMS key must be EXTERNAL.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The algorithm you will use to encrypt the key material before importing it
// with ImportKeyMaterial. For more information, see Encrypt the Key Material
// (https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys-encrypt-key-material.html)
// in the Key Management Service Developer Guide.
//
// WrappingAlgorithm is a required field
WrappingAlgorithm *string `type:"string" required:"true" enum:"AlgorithmSpec"`
// The type of wrapping key (public key) to return in the response. Only 2048-bit
// RSA public keys are supported.
//
// WrappingKeySpec is a required field
WrappingKeySpec *string `type:"string" required:"true" enum:"WrappingKeySpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetParametersForImportInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetParametersForImportInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetParametersForImportInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetParametersForImportInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.WrappingAlgorithm == nil {
invalidParams.Add(request.NewErrParamRequired("WrappingAlgorithm"))
}
if s.WrappingKeySpec == nil {
invalidParams.Add(request.NewErrParamRequired("WrappingKeySpec"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *GetParametersForImportInput) SetKeyId(v string) *GetParametersForImportInput {
s.KeyId = &v
return s
}
// SetWrappingAlgorithm sets the WrappingAlgorithm field's value.
func (s *GetParametersForImportInput) SetWrappingAlgorithm(v string) *GetParametersForImportInput {
s.WrappingAlgorithm = &v
return s
}
// SetWrappingKeySpec sets the WrappingKeySpec field's value.
func (s *GetParametersForImportInput) SetWrappingKeySpec(v string) *GetParametersForImportInput {
s.WrappingKeySpec = &v
return s
}
type GetParametersForImportOutput struct {
_ struct{} `type:"structure"`
// The import token to send in a subsequent ImportKeyMaterial request.
// ImportToken is automatically base64 encoded/decoded by the SDK.
ImportToken []byte `min:"1" type:"blob"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key to use in a subsequent ImportKeyMaterial request. This is
// the same KMS key specified in the GetParametersForImport request.
KeyId *string `min:"1" type:"string"`
// The time at which the import token and public key are no longer valid. After
// this time, you cannot use them to make an ImportKeyMaterial request and you
// must send another GetParametersForImport request to get new ones.
ParametersValidTo *time.Time `type:"timestamp"`
// The public key to use to encrypt the key material before importing it with
// ImportKeyMaterial.
//
// PublicKey is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GetParametersForImportOutput's
// String and GoString methods.
//
// PublicKey is automatically base64 encoded/decoded by the SDK.
PublicKey []byte `min:"1" type:"blob" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetParametersForImportOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetParametersForImportOutput) GoString() string {
return s.String()
}
// SetImportToken sets the ImportToken field's value.
func (s *GetParametersForImportOutput) SetImportToken(v []byte) *GetParametersForImportOutput {
s.ImportToken = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GetParametersForImportOutput) SetKeyId(v string) *GetParametersForImportOutput {
s.KeyId = &v
return s
}
// SetParametersValidTo sets the ParametersValidTo field's value.
func (s *GetParametersForImportOutput) SetParametersValidTo(v time.Time) *GetParametersForImportOutput {
s.ParametersValidTo = &v
return s
}
// SetPublicKey sets the PublicKey field's value.
func (s *GetParametersForImportOutput) SetPublicKey(v []byte) *GetParametersForImportOutput {
s.PublicKey = v
return s
}
type GetPublicKeyInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Identifies the asymmetric KMS key that includes the public key.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetPublicKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetPublicKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetPublicKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetPublicKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *GetPublicKeyInput) SetGrantTokens(v []*string) *GetPublicKeyInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GetPublicKeyInput) SetKeyId(v string) *GetPublicKeyInput {
s.KeyId = &v
return s
}
type GetPublicKeyOutput struct {
_ struct{} `type:"structure"`
// Instead, use the KeySpec field in the GetPublicKey response.
//
// The KeySpec and CustomerMasterKeySpec fields have the same value. We recommend
// that you use the KeySpec field in your code. However, to avoid breaking changes,
// KMS will support both fields.
//
// Deprecated: This field has been deprecated. Instead, use the KeySpec field.
CustomerMasterKeySpec *string `deprecated:"true" type:"string" enum:"CustomerMasterKeySpec"`
// The encryption algorithms that KMS supports for this key.
//
// This information is critical. If a public key encrypts data outside of KMS
// by using an unsupported encryption algorithm, the ciphertext cannot be decrypted.
//
// This field appears in the response only when the KeyUsage of the public key
// is ENCRYPT_DECRYPT.
EncryptionAlgorithms []*string `type:"list" enum:"EncryptionAlgorithmSpec"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the asymmetric KMS key from which the public key was downloaded.
KeyId *string `min:"1" type:"string"`
// The type of the of the public key that was downloaded.
KeySpec *string `type:"string" enum:"KeySpec"`
// The permitted use of the public key. Valid values are ENCRYPT_DECRYPT or
// SIGN_VERIFY.
//
// This information is critical. If a public key with SIGN_VERIFY key usage
// encrypts data outside of KMS, the ciphertext cannot be decrypted.
KeyUsage *string `type:"string" enum:"KeyUsageType"`
// The exported public key.
//
// The value is a DER-encoded X.509 public key, also known as SubjectPublicKeyInfo
// (SPKI), as defined in RFC 5280 (https://tools.ietf.org/html/rfc5280). When
// you use the HTTP API or the Amazon Web Services CLI, the value is Base64-encoded.
// Otherwise, it is not Base64-encoded.
// PublicKey is automatically base64 encoded/decoded by the SDK.
PublicKey []byte `min:"1" type:"blob"`
// The signing algorithms that KMS supports for this key.
//
// This field appears in the response only when the KeyUsage of the public key
// is SIGN_VERIFY.
SigningAlgorithms []*string `type:"list" enum:"SigningAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetPublicKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetPublicKeyOutput) GoString() string {
return s.String()
}
// SetCustomerMasterKeySpec sets the CustomerMasterKeySpec field's value.
func (s *GetPublicKeyOutput) SetCustomerMasterKeySpec(v string) *GetPublicKeyOutput {
s.CustomerMasterKeySpec = &v
return s
}
// SetEncryptionAlgorithms sets the EncryptionAlgorithms field's value.
func (s *GetPublicKeyOutput) SetEncryptionAlgorithms(v []*string) *GetPublicKeyOutput {
s.EncryptionAlgorithms = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GetPublicKeyOutput) SetKeyId(v string) *GetPublicKeyOutput {
s.KeyId = &v
return s
}
// SetKeySpec sets the KeySpec field's value.
func (s *GetPublicKeyOutput) SetKeySpec(v string) *GetPublicKeyOutput {
s.KeySpec = &v
return s
}
// SetKeyUsage sets the KeyUsage field's value.
func (s *GetPublicKeyOutput) SetKeyUsage(v string) *GetPublicKeyOutput {
s.KeyUsage = &v
return s
}
// SetPublicKey sets the PublicKey field's value.
func (s *GetPublicKeyOutput) SetPublicKey(v []byte) *GetPublicKeyOutput {
s.PublicKey = v
return s
}
// SetSigningAlgorithms sets the SigningAlgorithms field's value.
func (s *GetPublicKeyOutput) SetSigningAlgorithms(v []*string) *GetPublicKeyOutput {
s.SigningAlgorithms = v
return s
}
// Use this structure to allow cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// in the grant only when the operation request includes the specified encryption
// context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context).
//
// KMS applies the grant constraints only to cryptographic operations that support
// an encryption context, that is, all cryptographic operations with a symmetric
// encryption KMS key (https://docs.aws.amazon.com/kms/latest/developerguide/symm-asymm-concepts.html#symmetric-cmks).
// Grant constraints are not applied to operations that do not support an encryption
// context, such as cryptographic operations with HMAC KMS keys or asymmetric
// KMS keys, and management operations, such as DescribeKey or RetireGrant.
//
// In a cryptographic operation, the encryption context in the decryption operation
// must be an exact, case-sensitive match for the keys and values in the encryption
// context of the encryption operation. Only the order of the pairs can vary.
//
// However, in a grant constraint, the key in each key-value pair is not case
// sensitive, but the value is case sensitive.
//
// To avoid confusion, do not use multiple encryption context pairs that differ
// only by case. To require a fully case-sensitive encryption context, use the
// kms:EncryptionContext: and kms:EncryptionContextKeys conditions in an IAM
// or key policy. For details, see kms:EncryptionContext: (https://docs.aws.amazon.com/kms/latest/developerguide/policy-conditions.html#conditions-kms-encryption-context)
// in the Key Management Service Developer Guide .
type GrantConstraints struct {
_ struct{} `type:"structure"`
// A list of key-value pairs that must match the encryption context in the cryptographic
// operation (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// request. The grant allows the operation only when the encryption context
// in the request is the same as the encryption context specified in this constraint.
EncryptionContextEquals map[string]*string `type:"map"`
// A list of key-value pairs that must be included in the encryption context
// of the cryptographic operation (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// request. The grant allows the cryptographic operation only when the encryption
// context in the request includes the key-value pairs specified in this constraint,
// although it can include additional key-value pairs.
EncryptionContextSubset map[string]*string `type:"map"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GrantConstraints) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GrantConstraints) GoString() string {
return s.String()
}
// SetEncryptionContextEquals sets the EncryptionContextEquals field's value.
func (s *GrantConstraints) SetEncryptionContextEquals(v map[string]*string) *GrantConstraints {
s.EncryptionContextEquals = v
return s
}
// SetEncryptionContextSubset sets the EncryptionContextSubset field's value.
func (s *GrantConstraints) SetEncryptionContextSubset(v map[string]*string) *GrantConstraints {
s.EncryptionContextSubset = v
return s
}
// Contains information about a grant.
type GrantListEntry struct {
_ struct{} `type:"structure"`
// A list of key-value pairs that must be present in the encryption context
// of certain subsequent operations that the grant allows.
Constraints *GrantConstraints `type:"structure"`
// The date and time when the grant was created.
CreationDate *time.Time `type:"timestamp"`
// The unique identifier for the grant.
GrantId *string `min:"1" type:"string"`
// The identity that gets the permissions in the grant.
//
// The GranteePrincipal field in the ListGrants response usually contains the
// user or role designated as the grantee principal in the grant. However, when
// the grantee principal in the grant is an Amazon Web Services service, the
// GranteePrincipal field contains the service principal (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html#principal-services),
// which might represent several different grantee principals.
GranteePrincipal *string `min:"1" type:"string"`
// The Amazon Web Services account under which the grant was issued.
IssuingAccount *string `min:"1" type:"string"`
// The unique identifier for the KMS key to which the grant applies.
KeyId *string `min:"1" type:"string"`
// The friendly name that identifies the grant. If a name was provided in the
// CreateGrant request, that name is returned. Otherwise this value is null.
Name *string `min:"1" type:"string"`
// The list of operations permitted by the grant.
Operations []*string `type:"list" enum:"GrantOperation"`
// The principal that can retire the grant.
RetiringPrincipal *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GrantListEntry) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GrantListEntry) GoString() string {
return s.String()
}
// SetConstraints sets the Constraints field's value.
func (s *GrantListEntry) SetConstraints(v *GrantConstraints) *GrantListEntry {
s.Constraints = v
return s
}
// SetCreationDate sets the CreationDate field's value.
func (s *GrantListEntry) SetCreationDate(v time.Time) *GrantListEntry {
s.CreationDate = &v
return s
}
// SetGrantId sets the GrantId field's value.
func (s *GrantListEntry) SetGrantId(v string) *GrantListEntry {
s.GrantId = &v
return s
}
// SetGranteePrincipal sets the GranteePrincipal field's value.
func (s *GrantListEntry) SetGranteePrincipal(v string) *GrantListEntry {
s.GranteePrincipal = &v
return s
}
// SetIssuingAccount sets the IssuingAccount field's value.
func (s *GrantListEntry) SetIssuingAccount(v string) *GrantListEntry {
s.IssuingAccount = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *GrantListEntry) SetKeyId(v string) *GrantListEntry {
s.KeyId = &v
return s
}
// SetName sets the Name field's value.
func (s *GrantListEntry) SetName(v string) *GrantListEntry {
s.Name = &v
return s
}
// SetOperations sets the Operations field's value.
func (s *GrantListEntry) SetOperations(v []*string) *GrantListEntry {
s.Operations = v
return s
}
// SetRetiringPrincipal sets the RetiringPrincipal field's value.
func (s *GrantListEntry) SetRetiringPrincipal(v string) *GrantListEntry {
s.RetiringPrincipal = &v
return s
}
type ImportKeyMaterialInput struct {
_ struct{} `type:"structure"`
// The encrypted key material to import. The key material must be encrypted
// with the public wrapping key that GetParametersForImport returned, using
// the wrapping algorithm that you specified in the same GetParametersForImport
// request.
// EncryptedKeyMaterial is automatically base64 encoded/decoded by the SDK.
//
// EncryptedKeyMaterial is a required field
EncryptedKeyMaterial []byte `min:"1" type:"blob" required:"true"`
// Specifies whether the key material expires. The default is KEY_MATERIAL_EXPIRES,
// in which case you must include the ValidTo parameter. When this parameter
// is set to KEY_MATERIAL_DOES_NOT_EXPIRE, you must omit the ValidTo parameter.
ExpirationModel *string `type:"string" enum:"ExpirationModelType"`
// The import token that you received in the response to a previous GetParametersForImport
// request. It must be from the same response that contained the public key
// that you used to encrypt the key material.
// ImportToken is automatically base64 encoded/decoded by the SDK.
//
// ImportToken is a required field
ImportToken []byte `min:"1" type:"blob" required:"true"`
// The identifier of the symmetric encryption KMS key that receives the imported
// key material. This must be the same KMS key specified in the KeyID parameter
// of the corresponding GetParametersForImport request. The Origin of the KMS
// key must be EXTERNAL. You cannot perform this operation on an asymmetric
// KMS key, an HMAC KMS key, a KMS key in a custom key store, or on a KMS key
// in a different Amazon Web Services account
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The time at which the imported key material expires. When the key material
// expires, KMS deletes the key material and the KMS key becomes unusable. You
// must omit this parameter when the ExpirationModel parameter is set to KEY_MATERIAL_DOES_NOT_EXPIRE.
// Otherwise it is required.
ValidTo *time.Time `type:"timestamp"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ImportKeyMaterialInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ImportKeyMaterialInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ImportKeyMaterialInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ImportKeyMaterialInput"}
if s.EncryptedKeyMaterial == nil {
invalidParams.Add(request.NewErrParamRequired("EncryptedKeyMaterial"))
}
if s.EncryptedKeyMaterial != nil && len(s.EncryptedKeyMaterial) < 1 {
invalidParams.Add(request.NewErrParamMinLen("EncryptedKeyMaterial", 1))
}
if s.ImportToken == nil {
invalidParams.Add(request.NewErrParamRequired("ImportToken"))
}
if s.ImportToken != nil && len(s.ImportToken) < 1 {
invalidParams.Add(request.NewErrParamMinLen("ImportToken", 1))
}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncryptedKeyMaterial sets the EncryptedKeyMaterial field's value.
func (s *ImportKeyMaterialInput) SetEncryptedKeyMaterial(v []byte) *ImportKeyMaterialInput {
s.EncryptedKeyMaterial = v
return s
}
// SetExpirationModel sets the ExpirationModel field's value.
func (s *ImportKeyMaterialInput) SetExpirationModel(v string) *ImportKeyMaterialInput {
s.ExpirationModel = &v
return s
}
// SetImportToken sets the ImportToken field's value.
func (s *ImportKeyMaterialInput) SetImportToken(v []byte) *ImportKeyMaterialInput {
s.ImportToken = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *ImportKeyMaterialInput) SetKeyId(v string) *ImportKeyMaterialInput {
s.KeyId = &v
return s
}
// SetValidTo sets the ValidTo field's value.
func (s *ImportKeyMaterialInput) SetValidTo(v time.Time) *ImportKeyMaterialInput {
s.ValidTo = &v
return s
}
type ImportKeyMaterialOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ImportKeyMaterialOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ImportKeyMaterialOutput) GoString() string {
return s.String()
}
// The request was rejected because the specified KMS key cannot decrypt the
// data. The KeyId in a Decrypt request and the SourceKeyId in a ReEncrypt request
// must identify the same KMS key that was used to encrypt the ciphertext.
type IncorrectKeyException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectKeyException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectKeyException) GoString() string {
return s.String()
}
func newErrorIncorrectKeyException(v protocol.ResponseMetadata) error {
return &IncorrectKeyException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *IncorrectKeyException) Code() string {
return "IncorrectKeyException"
}
// Message returns the exception's message.
func (s *IncorrectKeyException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *IncorrectKeyException) OrigErr() error {
return nil
}
func (s *IncorrectKeyException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *IncorrectKeyException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *IncorrectKeyException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the key material in the request is, expired,
// invalid, or is not the same key material that was previously imported into
// this KMS key.
type IncorrectKeyMaterialException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectKeyMaterialException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectKeyMaterialException) GoString() string {
return s.String()
}
func newErrorIncorrectKeyMaterialException(v protocol.ResponseMetadata) error {
return &IncorrectKeyMaterialException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *IncorrectKeyMaterialException) Code() string {
return "IncorrectKeyMaterialException"
}
// Message returns the exception's message.
func (s *IncorrectKeyMaterialException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *IncorrectKeyMaterialException) OrigErr() error {
return nil
}
func (s *IncorrectKeyMaterialException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *IncorrectKeyMaterialException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *IncorrectKeyMaterialException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the trust anchor certificate in the request
// is not the trust anchor certificate for the specified CloudHSM cluster.
//
// When you initialize the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html#sign-csr),
// you create the trust anchor certificate and save it in the customerCA.crt
// file.
type IncorrectTrustAnchorException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectTrustAnchorException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s IncorrectTrustAnchorException) GoString() string {
return s.String()
}
func newErrorIncorrectTrustAnchorException(v protocol.ResponseMetadata) error {
return &IncorrectTrustAnchorException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *IncorrectTrustAnchorException) Code() string {
return "IncorrectTrustAnchorException"
}
// Message returns the exception's message.
func (s *IncorrectTrustAnchorException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *IncorrectTrustAnchorException) OrigErr() error {
return nil
}
func (s *IncorrectTrustAnchorException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *IncorrectTrustAnchorException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *IncorrectTrustAnchorException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because an internal exception occurred. The request
// can be retried.
type InternalException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InternalException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InternalException) GoString() string {
return s.String()
}
func newErrorInternalException(v protocol.ResponseMetadata) error {
return &InternalException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InternalException) Code() string {
return "KMSInternalException"
}
// Message returns the exception's message.
func (s *InternalException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InternalException) OrigErr() error {
return nil
}
func (s *InternalException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InternalException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InternalException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the specified alias name is not valid.
type InvalidAliasNameException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidAliasNameException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidAliasNameException) GoString() string {
return s.String()
}
func newErrorInvalidAliasNameException(v protocol.ResponseMetadata) error {
return &InvalidAliasNameException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidAliasNameException) Code() string {
return "InvalidAliasNameException"
}
// Message returns the exception's message.
func (s *InvalidAliasNameException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidAliasNameException) OrigErr() error {
return nil
}
func (s *InvalidAliasNameException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidAliasNameException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidAliasNameException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
type InvalidArnException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidArnException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidArnException) GoString() string {
return s.String()
}
func newErrorInvalidArnException(v protocol.ResponseMetadata) error {
return &InvalidArnException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidArnException) Code() string {
return "InvalidArnException"
}
// Message returns the exception's message.
func (s *InvalidArnException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidArnException) OrigErr() error {
return nil
}
func (s *InvalidArnException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidArnException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidArnException) RequestID() string {
return s.RespMetadata.RequestID
}
// From the Decrypt or ReEncrypt operation, the request was rejected because
// the specified ciphertext, or additional authenticated data incorporated into
// the ciphertext, such as the encryption context, is corrupted, missing, or
// otherwise invalid.
//
// From the ImportKeyMaterial operation, the request was rejected because KMS
// could not decrypt the encrypted (wrapped) key material.
type InvalidCiphertextException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidCiphertextException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidCiphertextException) GoString() string {
return s.String()
}
func newErrorInvalidCiphertextException(v protocol.ResponseMetadata) error {
return &InvalidCiphertextException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidCiphertextException) Code() string {
return "InvalidCiphertextException"
}
// Message returns the exception's message.
func (s *InvalidCiphertextException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidCiphertextException) OrigErr() error {
return nil
}
func (s *InvalidCiphertextException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidCiphertextException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidCiphertextException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the specified GrantId is not valid.
type InvalidGrantIdException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidGrantIdException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidGrantIdException) GoString() string {
return s.String()
}
func newErrorInvalidGrantIdException(v protocol.ResponseMetadata) error {
return &InvalidGrantIdException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidGrantIdException) Code() string {
return "InvalidGrantIdException"
}
// Message returns the exception's message.
func (s *InvalidGrantIdException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidGrantIdException) OrigErr() error {
return nil
}
func (s *InvalidGrantIdException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidGrantIdException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidGrantIdException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the specified grant token is not valid.
type InvalidGrantTokenException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidGrantTokenException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidGrantTokenException) GoString() string {
return s.String()
}
func newErrorInvalidGrantTokenException(v protocol.ResponseMetadata) error {
return &InvalidGrantTokenException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidGrantTokenException) Code() string {
return "InvalidGrantTokenException"
}
// Message returns the exception's message.
func (s *InvalidGrantTokenException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidGrantTokenException) OrigErr() error {
return nil
}
func (s *InvalidGrantTokenException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidGrantTokenException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidGrantTokenException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the provided import token is invalid or
// is associated with a different KMS key.
type InvalidImportTokenException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidImportTokenException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidImportTokenException) GoString() string {
return s.String()
}
func newErrorInvalidImportTokenException(v protocol.ResponseMetadata) error {
return &InvalidImportTokenException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidImportTokenException) Code() string {
return "InvalidImportTokenException"
}
// Message returns the exception's message.
func (s *InvalidImportTokenException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidImportTokenException) OrigErr() error {
return nil
}
func (s *InvalidImportTokenException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidImportTokenException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidImportTokenException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
type InvalidKeyUsageException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidKeyUsageException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidKeyUsageException) GoString() string {
return s.String()
}
func newErrorInvalidKeyUsageException(v protocol.ResponseMetadata) error {
return &InvalidKeyUsageException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidKeyUsageException) Code() string {
return "InvalidKeyUsageException"
}
// Message returns the exception's message.
func (s *InvalidKeyUsageException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidKeyUsageException) OrigErr() error {
return nil
}
func (s *InvalidKeyUsageException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidKeyUsageException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidKeyUsageException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
type InvalidMarkerException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidMarkerException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidMarkerException) GoString() string {
return s.String()
}
func newErrorInvalidMarkerException(v protocol.ResponseMetadata) error {
return &InvalidMarkerException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidMarkerException) Code() string {
return "InvalidMarkerException"
}
// Message returns the exception's message.
func (s *InvalidMarkerException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidMarkerException) OrigErr() error {
return nil
}
func (s *InvalidMarkerException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidMarkerException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidMarkerException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
type InvalidStateException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidStateException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidStateException) GoString() string {
return s.String()
}
func newErrorInvalidStateException(v protocol.ResponseMetadata) error {
return &InvalidStateException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidStateException) Code() string {
return "KMSInvalidStateException"
}
// Message returns the exception's message.
func (s *InvalidStateException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidStateException) OrigErr() error {
return nil
}
func (s *InvalidStateException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidStateException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidStateException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the HMAC verification failed. HMAC verification
// fails when the HMAC computed by using the specified message, HMAC KMS key,
// and MAC algorithm does not match the HMAC specified in the request.
type KMSInvalidMacException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KMSInvalidMacException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KMSInvalidMacException) GoString() string {
return s.String()
}
func newErrorKMSInvalidMacException(v protocol.ResponseMetadata) error {
return &KMSInvalidMacException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *KMSInvalidMacException) Code() string {
return "KMSInvalidMacException"
}
// Message returns the exception's message.
func (s *KMSInvalidMacException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *KMSInvalidMacException) OrigErr() error {
return nil
}
func (s *KMSInvalidMacException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *KMSInvalidMacException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *KMSInvalidMacException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because the signature verification failed. Signature
// verification fails when it cannot confirm that signature was produced by
// signing the specified message with the specified KMS key and signing algorithm.
type KMSInvalidSignatureException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KMSInvalidSignatureException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KMSInvalidSignatureException) GoString() string {
return s.String()
}
func newErrorKMSInvalidSignatureException(v protocol.ResponseMetadata) error {
return &KMSInvalidSignatureException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *KMSInvalidSignatureException) Code() string {
return "KMSInvalidSignatureException"
}
// Message returns the exception's message.
func (s *KMSInvalidSignatureException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *KMSInvalidSignatureException) OrigErr() error {
return nil
}
func (s *KMSInvalidSignatureException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *KMSInvalidSignatureException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *KMSInvalidSignatureException) RequestID() string {
return s.RespMetadata.RequestID
}
// Contains information about each entry in the key list.
type KeyListEntry struct {
_ struct{} `type:"structure"`
// ARN of the key.
KeyArn *string `min:"20" type:"string"`
// Unique identifier of the key.
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyListEntry) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyListEntry) GoString() string {
return s.String()
}
// SetKeyArn sets the KeyArn field's value.
func (s *KeyListEntry) SetKeyArn(v string) *KeyListEntry {
s.KeyArn = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *KeyListEntry) SetKeyId(v string) *KeyListEntry {
s.KeyId = &v
return s
}
// Contains metadata about a KMS key.
//
// This data type is used as a response element for the CreateKey and DescribeKey
// operations.
type KeyMetadata struct {
_ struct{} `type:"structure"`
// The twelve-digit account ID of the Amazon Web Services account that owns
// the KMS key.
AWSAccountId *string `type:"string"`
// The Amazon Resource Name (ARN) of the KMS key. For examples, see Key Management
// Service (KMS) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-kms)
// in the Example ARNs section of the Amazon Web Services General Reference.
Arn *string `min:"20" type:"string"`
// The cluster ID of the CloudHSM cluster that contains the key material for
// the KMS key. When you create a KMS key in a custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html),
// KMS creates the key material for the KMS key in the associated CloudHSM cluster.
// This value is present only when the KMS key is created in a custom key store.
CloudHsmClusterId *string `min:"19" type:"string"`
// The date and time when the KMS key was created.
CreationDate *time.Time `type:"timestamp"`
// A unique identifier for the custom key store (https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)
// that contains the KMS key. This value is present only when the KMS key is
// created in a custom key store.
CustomKeyStoreId *string `min:"1" type:"string"`
// Instead, use the KeySpec field.
//
// The KeySpec and CustomerMasterKeySpec fields have the same value. We recommend
// that you use the KeySpec field in your code. However, to avoid breaking changes,
// KMS will support both fields.
//
// Deprecated: This field has been deprecated. Instead, use the KeySpec field.
CustomerMasterKeySpec *string `deprecated:"true" type:"string" enum:"CustomerMasterKeySpec"`
// The date and time after which KMS deletes this KMS key. This value is present
// only when the KMS key is scheduled for deletion, that is, when its KeyState
// is PendingDeletion.
//
// When the primary key in a multi-Region key is scheduled for deletion but
// still has replica keys, its key state is PendingReplicaDeletion and the length
// of its waiting period is displayed in the PendingDeletionWindowInDays field.
DeletionDate *time.Time `type:"timestamp"`
// The description of the KMS key.
Description *string `type:"string"`
// Specifies whether the KMS key is enabled. When KeyState is Enabled this value
// is true, otherwise it is false.
Enabled *bool `type:"boolean"`
// The encryption algorithms that the KMS key supports. You cannot use the KMS
// key with other encryption algorithms within KMS.
//
// This value is present only when the KeyUsage of the KMS key is ENCRYPT_DECRYPT.
EncryptionAlgorithms []*string `type:"list" enum:"EncryptionAlgorithmSpec"`
// Specifies whether the KMS key's key material expires. This value is present
// only when Origin is EXTERNAL, otherwise this value is omitted.
ExpirationModel *string `type:"string" enum:"ExpirationModelType"`
// The globally unique identifier for the KMS key.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The manager of the KMS key. KMS keys in your Amazon Web Services account
// are either customer managed or Amazon Web Services managed. For more information
// about the difference, see KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys)
// in the Key Management Service Developer Guide.
KeyManager *string `type:"string" enum:"KeyManagerType"`
// Describes the type of key material in the KMS key.
KeySpec *string `type:"string" enum:"KeySpec"`
// The current status of the KMS key.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
KeyState *string `type:"string" enum:"KeyState"`
// The cryptographic operations (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)
// for which you can use the KMS key.
KeyUsage *string `type:"string" enum:"KeyUsageType"`
// The message authentication code (MAC) algorithm that the HMAC KMS key supports.
//
// This value is present only when the KeyUsage of the KMS key is GENERATE_VERIFY_MAC.
MacAlgorithms []*string `type:"list" enum:"MacAlgorithmSpec"`
// Indicates whether the KMS key is a multi-Region (True) or regional (False)
// key. This value is True for multi-Region primary and replica keys and False
// for regional KMS keys.
//
// For more information about multi-Region keys, see Multi-Region keys in KMS
// (https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)
// in the Key Management Service Developer Guide.
MultiRegion *bool `type:"boolean"`
// Lists the primary and replica keys in same multi-Region key. This field is
// present only when the value of the MultiRegion field is True.
//
// For more information about any listed KMS key, use the DescribeKey operation.
//
// * MultiRegionKeyType indicates whether the KMS key is a PRIMARY or REPLICA
// key.
//
// * PrimaryKey displays the key ARN and Region of the primary key. This
// field displays the current KMS key if it is the primary key.
//
// * ReplicaKeys displays the key ARNs and Regions of all replica keys. This
// field includes the current KMS key if it is a replica key.
MultiRegionConfiguration *MultiRegionConfiguration `type:"structure"`
// The source of the key material for the KMS key. When this value is AWS_KMS,
// KMS created the key material. When this value is EXTERNAL, the key material
// was imported or the KMS key doesn't have any key material. When this value
// is AWS_CLOUDHSM, the key material was created in the CloudHSM cluster associated
// with a custom key store.
Origin *string `type:"string" enum:"OriginType"`
// The waiting period before the primary key in a multi-Region key is deleted.
// This waiting period begins when the last of its replica keys is deleted.
// This value is present only when the KeyState of the KMS key is PendingReplicaDeletion.
// That indicates that the KMS key is the primary key in a multi-Region key,
// it is scheduled for deletion, and it still has existing replica keys.
//
// When a single-Region KMS key or a multi-Region replica key is scheduled for
// deletion, its deletion date is displayed in the DeletionDate field. However,
// when the primary key in a multi-Region key is scheduled for deletion, its
// waiting period doesn't begin until all of its replica keys are deleted. This
// value displays that waiting period. When the last replica key in the multi-Region
// key is deleted, the KeyState of the scheduled primary key changes from PendingReplicaDeletion
// to PendingDeletion and the deletion date appears in the DeletionDate field.
PendingDeletionWindowInDays *int64 `min:"1" type:"integer"`
// The signing algorithms that the KMS key supports. You cannot use the KMS
// key with other signing algorithms within KMS.
//
// This field appears only when the KeyUsage of the KMS key is SIGN_VERIFY.
SigningAlgorithms []*string `type:"list" enum:"SigningAlgorithmSpec"`
// The time at which the imported key material expires. When the key material
// expires, KMS deletes the key material and the KMS key becomes unusable. This
// value is present only for KMS keys whose Origin is EXTERNAL and whose ExpirationModel
// is KEY_MATERIAL_EXPIRES, otherwise this value is omitted.
ValidTo *time.Time `type:"timestamp"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyMetadata) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyMetadata) GoString() string {
return s.String()
}
// SetAWSAccountId sets the AWSAccountId field's value.
func (s *KeyMetadata) SetAWSAccountId(v string) *KeyMetadata {
s.AWSAccountId = &v
return s
}
// SetArn sets the Arn field's value.
func (s *KeyMetadata) SetArn(v string) *KeyMetadata {
s.Arn = &v
return s
}
// SetCloudHsmClusterId sets the CloudHsmClusterId field's value.
func (s *KeyMetadata) SetCloudHsmClusterId(v string) *KeyMetadata {
s.CloudHsmClusterId = &v
return s
}
// SetCreationDate sets the CreationDate field's value.
func (s *KeyMetadata) SetCreationDate(v time.Time) *KeyMetadata {
s.CreationDate = &v
return s
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *KeyMetadata) SetCustomKeyStoreId(v string) *KeyMetadata {
s.CustomKeyStoreId = &v
return s
}
// SetCustomerMasterKeySpec sets the CustomerMasterKeySpec field's value.
func (s *KeyMetadata) SetCustomerMasterKeySpec(v string) *KeyMetadata {
s.CustomerMasterKeySpec = &v
return s
}
// SetDeletionDate sets the DeletionDate field's value.
func (s *KeyMetadata) SetDeletionDate(v time.Time) *KeyMetadata {
s.DeletionDate = &v
return s
}
// SetDescription sets the Description field's value.
func (s *KeyMetadata) SetDescription(v string) *KeyMetadata {
s.Description = &v
return s
}
// SetEnabled sets the Enabled field's value.
func (s *KeyMetadata) SetEnabled(v bool) *KeyMetadata {
s.Enabled = &v
return s
}
// SetEncryptionAlgorithms sets the EncryptionAlgorithms field's value.
func (s *KeyMetadata) SetEncryptionAlgorithms(v []*string) *KeyMetadata {
s.EncryptionAlgorithms = v
return s
}
// SetExpirationModel sets the ExpirationModel field's value.
func (s *KeyMetadata) SetExpirationModel(v string) *KeyMetadata {
s.ExpirationModel = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *KeyMetadata) SetKeyId(v string) *KeyMetadata {
s.KeyId = &v
return s
}
// SetKeyManager sets the KeyManager field's value.
func (s *KeyMetadata) SetKeyManager(v string) *KeyMetadata {
s.KeyManager = &v
return s
}
// SetKeySpec sets the KeySpec field's value.
func (s *KeyMetadata) SetKeySpec(v string) *KeyMetadata {
s.KeySpec = &v
return s
}
// SetKeyState sets the KeyState field's value.
func (s *KeyMetadata) SetKeyState(v string) *KeyMetadata {
s.KeyState = &v
return s
}
// SetKeyUsage sets the KeyUsage field's value.
func (s *KeyMetadata) SetKeyUsage(v string) *KeyMetadata {
s.KeyUsage = &v
return s
}
// SetMacAlgorithms sets the MacAlgorithms field's value.
func (s *KeyMetadata) SetMacAlgorithms(v []*string) *KeyMetadata {
s.MacAlgorithms = v
return s
}
// SetMultiRegion sets the MultiRegion field's value.
func (s *KeyMetadata) SetMultiRegion(v bool) *KeyMetadata {
s.MultiRegion = &v
return s
}
// SetMultiRegionConfiguration sets the MultiRegionConfiguration field's value.
func (s *KeyMetadata) SetMultiRegionConfiguration(v *MultiRegionConfiguration) *KeyMetadata {
s.MultiRegionConfiguration = v
return s
}
// SetOrigin sets the Origin field's value.
func (s *KeyMetadata) SetOrigin(v string) *KeyMetadata {
s.Origin = &v
return s
}
// SetPendingDeletionWindowInDays sets the PendingDeletionWindowInDays field's value.
func (s *KeyMetadata) SetPendingDeletionWindowInDays(v int64) *KeyMetadata {
s.PendingDeletionWindowInDays = &v
return s
}
// SetSigningAlgorithms sets the SigningAlgorithms field's value.
func (s *KeyMetadata) SetSigningAlgorithms(v []*string) *KeyMetadata {
s.SigningAlgorithms = v
return s
}
// SetValidTo sets the ValidTo field's value.
func (s *KeyMetadata) SetValidTo(v time.Time) *KeyMetadata {
s.ValidTo = &v
return s
}
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
type KeyUnavailableException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyUnavailableException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s KeyUnavailableException) GoString() string {
return s.String()
}
func newErrorKeyUnavailableException(v protocol.ResponseMetadata) error {
return &KeyUnavailableException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *KeyUnavailableException) Code() string {
return "KeyUnavailableException"
}
// Message returns the exception's message.
func (s *KeyUnavailableException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *KeyUnavailableException) OrigErr() error {
return nil
}
func (s *KeyUnavailableException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *KeyUnavailableException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *KeyUnavailableException) RequestID() string {
return s.RespMetadata.RequestID
}
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
type LimitExceededException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LimitExceededException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LimitExceededException) GoString() string {
return s.String()
}
func newErrorLimitExceededException(v protocol.ResponseMetadata) error {
return &LimitExceededException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *LimitExceededException) Code() string {
return "LimitExceededException"
}
// Message returns the exception's message.
func (s *LimitExceededException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *LimitExceededException) OrigErr() error {
return nil
}
func (s *LimitExceededException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *LimitExceededException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *LimitExceededException) RequestID() string {
return s.RespMetadata.RequestID
}
type ListAliasesInput struct {
_ struct{} `type:"structure"`
// Lists only aliases that are associated with the specified KMS key. Enter
// a KMS key in your Amazon Web Services account.
//
// This parameter is optional. If you omit it, ListAliases returns all aliases
// in the account and Region.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
KeyId *string `min:"1" type:"string"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 100, inclusive. If you do not include a value, it defaults to 50.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAliasesInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAliasesInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListAliasesInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListAliasesInput"}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *ListAliasesInput) SetKeyId(v string) *ListAliasesInput {
s.KeyId = &v
return s
}
// SetLimit sets the Limit field's value.
func (s *ListAliasesInput) SetLimit(v int64) *ListAliasesInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListAliasesInput) SetMarker(v string) *ListAliasesInput {
s.Marker = &v
return s
}
type ListAliasesOutput struct {
_ struct{} `type:"structure"`
// A list of aliases.
Aliases []*AliasListEntry `type:"list"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
NextMarker *string `min:"1" type:"string"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAliasesOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAliasesOutput) GoString() string {
return s.String()
}
// SetAliases sets the Aliases field's value.
func (s *ListAliasesOutput) SetAliases(v []*AliasListEntry) *ListAliasesOutput {
s.Aliases = v
return s
}
// SetNextMarker sets the NextMarker field's value.
func (s *ListAliasesOutput) SetNextMarker(v string) *ListAliasesOutput {
s.NextMarker = &v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *ListAliasesOutput) SetTruncated(v bool) *ListAliasesOutput {
s.Truncated = &v
return s
}
type ListGrantsInput struct {
_ struct{} `type:"structure"`
// Returns only the grant with the specified grant ID. The grant ID uniquely
// identifies the grant.
GrantId *string `min:"1" type:"string"`
// Returns only grants where the specified principal is the grantee principal
// for the grant.
GranteePrincipal *string `min:"1" type:"string"`
// Returns only grants for the specified KMS key. This parameter is required.
//
// Specify the key ID or key ARN of the KMS key. To specify a KMS key in a different
// Amazon Web Services account, you must use the key ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 100, inclusive. If you do not include a value, it defaults to 50.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListGrantsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListGrantsInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListGrantsInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListGrantsInput"}
if s.GrantId != nil && len(*s.GrantId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GrantId", 1))
}
if s.GranteePrincipal != nil && len(*s.GranteePrincipal) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GranteePrincipal", 1))
}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantId sets the GrantId field's value.
func (s *ListGrantsInput) SetGrantId(v string) *ListGrantsInput {
s.GrantId = &v
return s
}
// SetGranteePrincipal sets the GranteePrincipal field's value.
func (s *ListGrantsInput) SetGranteePrincipal(v string) *ListGrantsInput {
s.GranteePrincipal = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *ListGrantsInput) SetKeyId(v string) *ListGrantsInput {
s.KeyId = &v
return s
}
// SetLimit sets the Limit field's value.
func (s *ListGrantsInput) SetLimit(v int64) *ListGrantsInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListGrantsInput) SetMarker(v string) *ListGrantsInput {
s.Marker = &v
return s
}
type ListGrantsResponse struct {
_ struct{} `type:"structure"`
// A list of grants.
Grants []*GrantListEntry `type:"list"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
NextMarker *string `min:"1" type:"string"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListGrantsResponse) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListGrantsResponse) GoString() string {
return s.String()
}
// SetGrants sets the Grants field's value.
func (s *ListGrantsResponse) SetGrants(v []*GrantListEntry) *ListGrantsResponse {
s.Grants = v
return s
}
// SetNextMarker sets the NextMarker field's value.
func (s *ListGrantsResponse) SetNextMarker(v string) *ListGrantsResponse {
s.NextMarker = &v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *ListGrantsResponse) SetTruncated(v bool) *ListGrantsResponse {
s.Truncated = &v
return s
}
type ListKeyPoliciesInput struct {
_ struct{} `type:"structure"`
// Gets the names of key policies for the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 1000, inclusive. If you do not include a value, it defaults to 100.
//
// Only one policy can be attached to a key.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeyPoliciesInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeyPoliciesInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListKeyPoliciesInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListKeyPoliciesInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *ListKeyPoliciesInput) SetKeyId(v string) *ListKeyPoliciesInput {
s.KeyId = &v
return s
}
// SetLimit sets the Limit field's value.
func (s *ListKeyPoliciesInput) SetLimit(v int64) *ListKeyPoliciesInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListKeyPoliciesInput) SetMarker(v string) *ListKeyPoliciesInput {
s.Marker = &v
return s
}
type ListKeyPoliciesOutput struct {
_ struct{} `type:"structure"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
NextMarker *string `min:"1" type:"string"`
// A list of key policy names. The only valid value is default.
PolicyNames []*string `type:"list"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeyPoliciesOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeyPoliciesOutput) GoString() string {
return s.String()
}
// SetNextMarker sets the NextMarker field's value.
func (s *ListKeyPoliciesOutput) SetNextMarker(v string) *ListKeyPoliciesOutput {
s.NextMarker = &v
return s
}
// SetPolicyNames sets the PolicyNames field's value.
func (s *ListKeyPoliciesOutput) SetPolicyNames(v []*string) *ListKeyPoliciesOutput {
s.PolicyNames = v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *ListKeyPoliciesOutput) SetTruncated(v bool) *ListKeyPoliciesOutput {
s.Truncated = &v
return s
}
type ListKeysInput struct {
_ struct{} `type:"structure"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 1000, inclusive. If you do not include a value, it defaults to 100.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeysInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeysInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListKeysInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListKeysInput"}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetLimit sets the Limit field's value.
func (s *ListKeysInput) SetLimit(v int64) *ListKeysInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListKeysInput) SetMarker(v string) *ListKeysInput {
s.Marker = &v
return s
}
type ListKeysOutput struct {
_ struct{} `type:"structure"`
// A list of KMS keys.
Keys []*KeyListEntry `type:"list"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
NextMarker *string `min:"1" type:"string"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeysOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListKeysOutput) GoString() string {
return s.String()
}
// SetKeys sets the Keys field's value.
func (s *ListKeysOutput) SetKeys(v []*KeyListEntry) *ListKeysOutput {
s.Keys = v
return s
}
// SetNextMarker sets the NextMarker field's value.
func (s *ListKeysOutput) SetNextMarker(v string) *ListKeysOutput {
s.NextMarker = &v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *ListKeysOutput) SetTruncated(v bool) *ListKeysOutput {
s.Truncated = &v
return s
}
type ListResourceTagsInput struct {
_ struct{} `type:"structure"`
// Gets tags on the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 50, inclusive. If you do not include a value, it defaults to 50.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
//
// Do not attempt to construct this value. Use only the value of NextMarker
// from the truncated response you just received.
Marker *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListResourceTagsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListResourceTagsInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListResourceTagsInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListResourceTagsInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *ListResourceTagsInput) SetKeyId(v string) *ListResourceTagsInput {
s.KeyId = &v
return s
}
// SetLimit sets the Limit field's value.
func (s *ListResourceTagsInput) SetLimit(v int64) *ListResourceTagsInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListResourceTagsInput) SetMarker(v string) *ListResourceTagsInput {
s.Marker = &v
return s
}
type ListResourceTagsOutput struct {
_ struct{} `type:"structure"`
// When Truncated is true, this element is present and contains the value to
// use for the Marker parameter in a subsequent request.
//
// Do not assume or infer any information from this value.
NextMarker *string `min:"1" type:"string"`
// A list of tags. Each tag consists of a tag key and a tag value.
//
// Tagging or untagging a KMS key can allow or deny permission to the KMS key.
// For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
Tags []*Tag `type:"list"`
// A flag that indicates whether there are more items in the list. When this
// value is true, the list in this response is truncated. To get more items,
// pass the value of the NextMarker element in thisresponse to the Marker parameter
// in a subsequent request.
Truncated *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListResourceTagsOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListResourceTagsOutput) GoString() string {
return s.String()
}
// SetNextMarker sets the NextMarker field's value.
func (s *ListResourceTagsOutput) SetNextMarker(v string) *ListResourceTagsOutput {
s.NextMarker = &v
return s
}
// SetTags sets the Tags field's value.
func (s *ListResourceTagsOutput) SetTags(v []*Tag) *ListResourceTagsOutput {
s.Tags = v
return s
}
// SetTruncated sets the Truncated field's value.
func (s *ListResourceTagsOutput) SetTruncated(v bool) *ListResourceTagsOutput {
s.Truncated = &v
return s
}
type ListRetirableGrantsInput struct {
_ struct{} `type:"structure"`
// Use this parameter to specify the maximum number of items to return. When
// this value is present, KMS does not return more than the specified number
// of items, but it might return fewer.
//
// This value is optional. If you include a value, it must be between 1 and
// 100, inclusive. If you do not include a value, it defaults to 50.
Limit *int64 `min:"1" type:"integer"`
// Use this parameter in a subsequent request after you receive a response with
// truncated results. Set it to the value of NextMarker from the truncated response
// you just received.
Marker *string `min:"1" type:"string"`
// The retiring principal for which to list grants. Enter a principal in your
// Amazon Web Services account.
//
// To specify the retiring principal, use the Amazon Resource Name (ARN) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// of an Amazon Web Services principal. Valid Amazon Web Services principals
// include Amazon Web Services accounts (root), IAM users, federated users,
// and assumed role users. For examples of the ARN syntax for specifying a principal,
// see Amazon Web Services Identity and Access Management (IAM) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-iam)
// in the Example ARNs section of the Amazon Web Services General Reference.
//
// RetiringPrincipal is a required field
RetiringPrincipal *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListRetirableGrantsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListRetirableGrantsInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListRetirableGrantsInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListRetirableGrantsInput"}
if s.Limit != nil && *s.Limit < 1 {
invalidParams.Add(request.NewErrParamMinValue("Limit", 1))
}
if s.Marker != nil && len(*s.Marker) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Marker", 1))
}
if s.RetiringPrincipal == nil {
invalidParams.Add(request.NewErrParamRequired("RetiringPrincipal"))
}
if s.RetiringPrincipal != nil && len(*s.RetiringPrincipal) < 1 {
invalidParams.Add(request.NewErrParamMinLen("RetiringPrincipal", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetLimit sets the Limit field's value.
func (s *ListRetirableGrantsInput) SetLimit(v int64) *ListRetirableGrantsInput {
s.Limit = &v
return s
}
// SetMarker sets the Marker field's value.
func (s *ListRetirableGrantsInput) SetMarker(v string) *ListRetirableGrantsInput {
s.Marker = &v
return s
}
// SetRetiringPrincipal sets the RetiringPrincipal field's value.
func (s *ListRetirableGrantsInput) SetRetiringPrincipal(v string) *ListRetirableGrantsInput {
s.RetiringPrincipal = &v
return s
}
// The request was rejected because the specified policy is not syntactically
// or semantically correct.
type MalformedPolicyDocumentException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MalformedPolicyDocumentException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MalformedPolicyDocumentException) GoString() string {
return s.String()
}
func newErrorMalformedPolicyDocumentException(v protocol.ResponseMetadata) error {
return &MalformedPolicyDocumentException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *MalformedPolicyDocumentException) Code() string {
return "MalformedPolicyDocumentException"
}
// Message returns the exception's message.
func (s *MalformedPolicyDocumentException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *MalformedPolicyDocumentException) OrigErr() error {
return nil
}
func (s *MalformedPolicyDocumentException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *MalformedPolicyDocumentException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *MalformedPolicyDocumentException) RequestID() string {
return s.RespMetadata.RequestID
}
// Describes the configuration of this multi-Region key. This field appears
// only when the KMS key is a primary or replica of a multi-Region key.
//
// For more information about any listed KMS key, use the DescribeKey operation.
type MultiRegionConfiguration struct {
_ struct{} `type:"structure"`
// Indicates whether the KMS key is a PRIMARY or REPLICA key.
MultiRegionKeyType *string `type:"string" enum:"MultiRegionKeyType"`
// Displays the key ARN and Region of the primary key. This field includes the
// current KMS key if it is the primary key.
PrimaryKey *MultiRegionKey `type:"structure"`
// displays the key ARNs and Regions of all replica keys. This field includes
// the current KMS key if it is a replica key.
ReplicaKeys []*MultiRegionKey `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MultiRegionConfiguration) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MultiRegionConfiguration) GoString() string {
return s.String()
}
// SetMultiRegionKeyType sets the MultiRegionKeyType field's value.
func (s *MultiRegionConfiguration) SetMultiRegionKeyType(v string) *MultiRegionConfiguration {
s.MultiRegionKeyType = &v
return s
}
// SetPrimaryKey sets the PrimaryKey field's value.
func (s *MultiRegionConfiguration) SetPrimaryKey(v *MultiRegionKey) *MultiRegionConfiguration {
s.PrimaryKey = v
return s
}
// SetReplicaKeys sets the ReplicaKeys field's value.
func (s *MultiRegionConfiguration) SetReplicaKeys(v []*MultiRegionKey) *MultiRegionConfiguration {
s.ReplicaKeys = v
return s
}
// Describes the primary or replica key in a multi-Region key.
type MultiRegionKey struct {
_ struct{} `type:"structure"`
// Displays the key ARN of a primary or replica key of a multi-Region key.
Arn *string `min:"20" type:"string"`
// Displays the Amazon Web Services Region of a primary or replica key in a
// multi-Region key.
Region *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MultiRegionKey) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s MultiRegionKey) GoString() string {
return s.String()
}
// SetArn sets the Arn field's value.
func (s *MultiRegionKey) SetArn(v string) *MultiRegionKey {
s.Arn = &v
return s
}
// SetRegion sets the Region field's value.
func (s *MultiRegionKey) SetRegion(v string) *MultiRegionKey {
s.Region = &v
return s
}
// The request was rejected because the specified entity or resource could not
// be found.
type NotFoundException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s NotFoundException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s NotFoundException) GoString() string {
return s.String()
}
func newErrorNotFoundException(v protocol.ResponseMetadata) error {
return &NotFoundException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *NotFoundException) Code() string {
return "NotFoundException"
}
// Message returns the exception's message.
func (s *NotFoundException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *NotFoundException) OrigErr() error {
return nil
}
func (s *NotFoundException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *NotFoundException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *NotFoundException) RequestID() string {
return s.RespMetadata.RequestID
}
type PutKeyPolicyInput struct {
_ struct{} `type:"structure"`
// A flag to indicate whether to bypass the key policy lockout safety check.
//
// Setting this value to true increases the risk that the KMS key becomes unmanageable.
// Do not set this value to true indiscriminately.
//
// For more information, refer to the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section in the Key Management Service Developer Guide.
//
// Use this parameter only when you intend to prevent the principal that is
// making the request from making a subsequent PutKeyPolicy request on the KMS
// key.
//
// The default value is false.
BypassPolicyLockoutSafetyCheck *bool `type:"boolean"`
// Sets the key policy on the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The key policy to attach to the KMS key.
//
// The key policy must meet the following criteria:
//
// * If you don't set BypassPolicyLockoutSafetyCheck to true, the key policy
// must allow the principal that is making the PutKeyPolicy request to make
// a subsequent PutKeyPolicy request on the KMS key. This reduces the risk
// that the KMS key becomes unmanageable. For more information, refer to
// the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section of the Key Management Service Developer Guide.
//
// * Each statement in the key policy must contain one or more principals.
// The principals in the key policy must exist and be visible to KMS. When
// you create a new Amazon Web Services principal (for example, an IAM user
// or role), you might need to enforce a delay before including the new principal
// in a key policy because the new principal might not be immediately visible
// to KMS. For more information, see Changes that I make are not always immediately
// visible (https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency)
// in the Amazon Web Services Identity and Access Management User Guide.
//
// The key policy cannot exceed 32 kilobytes (32768 bytes). For more information,
// see Resource Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/resource-limits.html)
// in the Key Management Service Developer Guide.
//
// Policy is a required field
Policy *string `min:"1" type:"string" required:"true"`
// The name of the key policy. The only valid value is default.
//
// PolicyName is a required field
PolicyName *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PutKeyPolicyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PutKeyPolicyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *PutKeyPolicyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "PutKeyPolicyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Policy == nil {
invalidParams.Add(request.NewErrParamRequired("Policy"))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.PolicyName == nil {
invalidParams.Add(request.NewErrParamRequired("PolicyName"))
}
if s.PolicyName != nil && len(*s.PolicyName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("PolicyName", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetBypassPolicyLockoutSafetyCheck sets the BypassPolicyLockoutSafetyCheck field's value.
func (s *PutKeyPolicyInput) SetBypassPolicyLockoutSafetyCheck(v bool) *PutKeyPolicyInput {
s.BypassPolicyLockoutSafetyCheck = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *PutKeyPolicyInput) SetKeyId(v string) *PutKeyPolicyInput {
s.KeyId = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *PutKeyPolicyInput) SetPolicy(v string) *PutKeyPolicyInput {
s.Policy = &v
return s
}
// SetPolicyName sets the PolicyName field's value.
func (s *PutKeyPolicyInput) SetPolicyName(v string) *PutKeyPolicyInput {
s.PolicyName = &v
return s
}
type PutKeyPolicyOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PutKeyPolicyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PutKeyPolicyOutput) GoString() string {
return s.String()
}
type ReEncryptInput struct {
_ struct{} `type:"structure"`
// Ciphertext of the data to reencrypt.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
//
// CiphertextBlob is a required field
CiphertextBlob []byte `min:"1" type:"blob" required:"true"`
// Specifies the encryption algorithm that KMS will use to reecrypt the data
// after it has decrypted it. The default value, SYMMETRIC_DEFAULT, represents
// the encryption algorithm used for symmetric encryption KMS keys.
//
// This parameter is required only when the destination KMS key is an asymmetric
// KMS key.
DestinationEncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// Specifies that encryption context to use when the reencrypting the data.
//
// A destination encryption context is valid only when the destination KMS key
// is a symmetric encryption KMS key. The standard ciphertext format for asymmetric
// KMS keys does not include fields for metadata.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
DestinationEncryptionContext map[string]*string `type:"map"`
// A unique identifier for the KMS key that is used to reencrypt the data. Specify
// a symmetric encryption KMS key or an asymmetric KMS key with a KeyUsage value
// of ENCRYPT_DECRYPT. To find the KeyUsage value of a KMS key, use the DescribeKey
// operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// DestinationKeyId is a required field
DestinationKeyId *string `min:"1" type:"string" required:"true"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Specifies the encryption algorithm that KMS will use to decrypt the ciphertext
// before it is reencrypted. The default value, SYMMETRIC_DEFAULT, represents
// the algorithm used for symmetric encryption KMS keys.
//
// Specify the same algorithm that was used to encrypt the ciphertext. If you
// specify a different algorithm, the decrypt attempt fails.
//
// This parameter is required only when the ciphertext was encrypted under an
// asymmetric KMS key.
SourceEncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// Specifies the encryption context to use to decrypt the ciphertext. Enter
// the same encryption context that was used to encrypt the ciphertext.
//
// An encryption context is a collection of non-secret key-value pairs that
// represent additional authenticated data. When you use an encryption context
// to encrypt data, you must specify the same (an exact case-sensitive match)
// encryption context to decrypt the data. An encryption context is supported
// only on operations with symmetric encryption KMS keys. On operations with
// symmetric encryption KMS keys, an encryption context is optional, but it
// is strongly recommended.
//
// For more information, see Encryption context (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)
// in the Key Management Service Developer Guide.
SourceEncryptionContext map[string]*string `type:"map"`
// Specifies the KMS key that KMS will use to decrypt the ciphertext before
// it is re-encrypted.
//
// Enter a key ID of the KMS key that was used to encrypt the ciphertext. If
// you identify a different KMS key, the ReEncrypt operation throws an IncorrectKeyException.
//
// This parameter is required only when the ciphertext was encrypted under an
// asymmetric KMS key. If you used a symmetric encryption KMS key, KMS can get
// the KMS key from metadata that it adds to the symmetric ciphertext blob.
// However, it is always recommended as a best practice. This practice ensures
// that you use the KMS key that you intend.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
SourceKeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReEncryptInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReEncryptInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ReEncryptInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ReEncryptInput"}
if s.CiphertextBlob == nil {
invalidParams.Add(request.NewErrParamRequired("CiphertextBlob"))
}
if s.CiphertextBlob != nil && len(s.CiphertextBlob) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CiphertextBlob", 1))
}
if s.DestinationKeyId == nil {
invalidParams.Add(request.NewErrParamRequired("DestinationKeyId"))
}
if s.DestinationKeyId != nil && len(*s.DestinationKeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("DestinationKeyId", 1))
}
if s.SourceKeyId != nil && len(*s.SourceKeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("SourceKeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *ReEncryptInput) SetCiphertextBlob(v []byte) *ReEncryptInput {
s.CiphertextBlob = v
return s
}
// SetDestinationEncryptionAlgorithm sets the DestinationEncryptionAlgorithm field's value.
func (s *ReEncryptInput) SetDestinationEncryptionAlgorithm(v string) *ReEncryptInput {
s.DestinationEncryptionAlgorithm = &v
return s
}
// SetDestinationEncryptionContext sets the DestinationEncryptionContext field's value.
func (s *ReEncryptInput) SetDestinationEncryptionContext(v map[string]*string) *ReEncryptInput {
s.DestinationEncryptionContext = v
return s
}
// SetDestinationKeyId sets the DestinationKeyId field's value.
func (s *ReEncryptInput) SetDestinationKeyId(v string) *ReEncryptInput {
s.DestinationKeyId = &v
return s
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *ReEncryptInput) SetGrantTokens(v []*string) *ReEncryptInput {
s.GrantTokens = v
return s
}
// SetSourceEncryptionAlgorithm sets the SourceEncryptionAlgorithm field's value.
func (s *ReEncryptInput) SetSourceEncryptionAlgorithm(v string) *ReEncryptInput {
s.SourceEncryptionAlgorithm = &v
return s
}
// SetSourceEncryptionContext sets the SourceEncryptionContext field's value.
func (s *ReEncryptInput) SetSourceEncryptionContext(v map[string]*string) *ReEncryptInput {
s.SourceEncryptionContext = v
return s
}
// SetSourceKeyId sets the SourceKeyId field's value.
func (s *ReEncryptInput) SetSourceKeyId(v string) *ReEncryptInput {
s.SourceKeyId = &v
return s
}
type ReEncryptOutput struct {
_ struct{} `type:"structure"`
// The reencrypted data. When you use the HTTP API or the Amazon Web Services
// CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded.
// CiphertextBlob is automatically base64 encoded/decoded by the SDK.
CiphertextBlob []byte `min:"1" type:"blob"`
// The encryption algorithm that was used to reencrypt the data.
DestinationEncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key that was used to reencrypt the data.
KeyId *string `min:"1" type:"string"`
// The encryption algorithm that was used to decrypt the ciphertext before it
// was reencrypted.
SourceEncryptionAlgorithm *string `type:"string" enum:"EncryptionAlgorithmSpec"`
// Unique identifier of the KMS key used to originally encrypt the data.
SourceKeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReEncryptOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReEncryptOutput) GoString() string {
return s.String()
}
// SetCiphertextBlob sets the CiphertextBlob field's value.
func (s *ReEncryptOutput) SetCiphertextBlob(v []byte) *ReEncryptOutput {
s.CiphertextBlob = v
return s
}
// SetDestinationEncryptionAlgorithm sets the DestinationEncryptionAlgorithm field's value.
func (s *ReEncryptOutput) SetDestinationEncryptionAlgorithm(v string) *ReEncryptOutput {
s.DestinationEncryptionAlgorithm = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *ReEncryptOutput) SetKeyId(v string) *ReEncryptOutput {
s.KeyId = &v
return s
}
// SetSourceEncryptionAlgorithm sets the SourceEncryptionAlgorithm field's value.
func (s *ReEncryptOutput) SetSourceEncryptionAlgorithm(v string) *ReEncryptOutput {
s.SourceEncryptionAlgorithm = &v
return s
}
// SetSourceKeyId sets the SourceKeyId field's value.
func (s *ReEncryptOutput) SetSourceKeyId(v string) *ReEncryptOutput {
s.SourceKeyId = &v
return s
}
type ReplicateKeyInput struct {
_ struct{} `type:"structure"`
// A flag to indicate whether to bypass the key policy lockout safety check.
//
// Setting this value to true increases the risk that the KMS key becomes unmanageable.
// Do not set this value to true indiscriminately.
//
// For more information, refer to the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section in the Key Management Service Developer Guide.
//
// Use this parameter only when you intend to prevent the principal that is
// making the request from making a subsequent PutKeyPolicy request on the KMS
// key.
//
// The default value is false.
BypassPolicyLockoutSafetyCheck *bool `type:"boolean"`
// A description of the KMS key. The default value is an empty string (no description).
//
// The description is not a shared property of multi-Region keys. You can specify
// the same description or a different description for each key in a set of
// related multi-Region keys. KMS does not synchronize this property.
Description *string `type:"string"`
// Identifies the multi-Region primary key that is being replicated. To determine
// whether a KMS key is a multi-Region primary key, use the DescribeKey operation
// to check the value of the MultiRegionKeyType property.
//
// Specify the key ID or key ARN of a multi-Region primary key.
//
// For example:
//
// * Key ID: mrk-1234abcd12ab34cd56ef1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The key policy to attach to the KMS key. This parameter is optional. If you
// do not provide a key policy, KMS attaches the default key policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default)
// to the KMS key.
//
// The key policy is not a shared property of multi-Region keys. You can specify
// the same key policy or a different key policy for each key in a set of related
// multi-Region keys. KMS does not synchronize this property.
//
// If you provide a key policy, it must meet the following criteria:
//
// * If you don't set BypassPolicyLockoutSafetyCheck to true, the key policy
// must give the caller kms:PutKeyPolicy permission on the replica key. This
// reduces the risk that the KMS key becomes unmanageable. For more information,
// refer to the scenario in the Default Key Policy (https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-default-allow-root-enable-iam)
// section of the Key Management Service Developer Guide .
//
// * Each statement in the key policy must contain one or more principals.
// The principals in the key policy must exist and be visible to KMS. When
// you create a new Amazon Web Services principal (for example, an IAM user
// or role), you might need to enforce a delay before including the new principal
// in a key policy because the new principal might not be immediately visible
// to KMS. For more information, see Changes that I make are not always immediately
// visible (https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency)
// in the Identity and Access Management User Guide .
//
// * The key policy size quota is 32 kilobytes (32768 bytes).
Policy *string `min:"1" type:"string"`
// The Region ID of the Amazon Web Services Region for this replica key.
//
// Enter the Region ID, such as us-east-1 or ap-southeast-2. For a list of Amazon
// Web Services Regions in which KMS is supported, see KMS service endpoints
// (https://docs.aws.amazon.com/general/latest/gr/kms.html#kms_region) in the
// Amazon Web Services General Reference.
//
// HMAC KMS keys are not supported in all Amazon Web Services Regions. If you
// try to replicate an HMAC KMS key in an Amazon Web Services Region in which
// HMAC keys are not supported, the ReplicateKey operation returns an UnsupportedOperationException.
// For a list of Regions in which HMAC KMS keys are supported, see HMAC keys
// in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/hmac.html)
// in the Key Management Service Developer Guide.
//
// The replica must be in a different Amazon Web Services Region than its primary
// key and other replicas of that primary key, but in the same Amazon Web Services
// partition. KMS must be available in the replica Region. If the Region is
// not enabled by default, the Amazon Web Services account must be enabled in
// the Region. For information about Amazon Web Services partitions, see Amazon
// Resource Names (ARNs) (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference. For information about enabling
// and disabling Regions, see Enabling a Region (https://docs.aws.amazon.com/general/latest/gr/rande-manage.html#rande-manage-enable)
// and Disabling a Region (https://docs.aws.amazon.com/general/latest/gr/rande-manage.html#rande-manage-disable)
// in the Amazon Web Services General Reference.
//
// ReplicaRegion is a required field
ReplicaRegion *string `min:"1" type:"string" required:"true"`
// Assigns one or more tags to the replica key. Use this parameter to tag the
// KMS key when it is created. To tag an existing KMS key, use the TagResource
// operation.
//
// Tagging or untagging a KMS key can allow or deny permission to the KMS key.
// For details, see ABAC in KMS (https://docs.aws.amazon.com/kms/latest/developerguide/abac.html)
// in the Key Management Service Developer Guide.
//
// To use this parameter, you must have kms:TagResource (https://docs.aws.amazon.com/kms/latest/developerguide/kms-api-permissions-reference.html)
// permission in an IAM policy.
//
// Tags are not a shared property of multi-Region keys. You can specify the
// same tags or different tags for each key in a set of related multi-Region
// keys. KMS does not synchronize this property.
//
// Each tag consists of a tag key and a tag value. Both the tag key and the
// tag value are required, but the tag value can be an empty (null) string.
// You cannot have more than one tag on a KMS key with the same tag key. If
// you specify an existing tag key with a different tag value, KMS replaces
// the current tag value with the specified one.
//
// When you add tags to an Amazon Web Services resource, Amazon Web Services
// generates a cost allocation report with usage and costs aggregated by tags.
// Tags can also be used to control access to a KMS key. For details, see Tagging
// Keys (https://docs.aws.amazon.com/kms/latest/developerguide/tagging-keys.html).
Tags []*Tag `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReplicateKeyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReplicateKeyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ReplicateKeyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ReplicateKeyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.ReplicaRegion == nil {
invalidParams.Add(request.NewErrParamRequired("ReplicaRegion"))
}
if s.ReplicaRegion != nil && len(*s.ReplicaRegion) < 1 {
invalidParams.Add(request.NewErrParamMinLen("ReplicaRegion", 1))
}
if s.Tags != nil {
for i, v := range s.Tags {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetBypassPolicyLockoutSafetyCheck sets the BypassPolicyLockoutSafetyCheck field's value.
func (s *ReplicateKeyInput) SetBypassPolicyLockoutSafetyCheck(v bool) *ReplicateKeyInput {
s.BypassPolicyLockoutSafetyCheck = &v
return s
}
// SetDescription sets the Description field's value.
func (s *ReplicateKeyInput) SetDescription(v string) *ReplicateKeyInput {
s.Description = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *ReplicateKeyInput) SetKeyId(v string) *ReplicateKeyInput {
s.KeyId = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *ReplicateKeyInput) SetPolicy(v string) *ReplicateKeyInput {
s.Policy = &v
return s
}
// SetReplicaRegion sets the ReplicaRegion field's value.
func (s *ReplicateKeyInput) SetReplicaRegion(v string) *ReplicateKeyInput {
s.ReplicaRegion = &v
return s
}
// SetTags sets the Tags field's value.
func (s *ReplicateKeyInput) SetTags(v []*Tag) *ReplicateKeyInput {
s.Tags = v
return s
}
type ReplicateKeyOutput struct {
_ struct{} `type:"structure"`
// Displays details about the new replica key, including its Amazon Resource
// Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// and Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html).
// It also includes the ARN and Amazon Web Services Region of its primary key
// and other replica keys.
ReplicaKeyMetadata *KeyMetadata `type:"structure"`
// The key policy of the new replica key. The value is a key policy document
// in JSON format.
ReplicaPolicy *string `min:"1" type:"string"`
// The tags on the new replica key. The value is a list of tag key and tag value
// pairs.
ReplicaTags []*Tag `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReplicateKeyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ReplicateKeyOutput) GoString() string {
return s.String()
}
// SetReplicaKeyMetadata sets the ReplicaKeyMetadata field's value.
func (s *ReplicateKeyOutput) SetReplicaKeyMetadata(v *KeyMetadata) *ReplicateKeyOutput {
s.ReplicaKeyMetadata = v
return s
}
// SetReplicaPolicy sets the ReplicaPolicy field's value.
func (s *ReplicateKeyOutput) SetReplicaPolicy(v string) *ReplicateKeyOutput {
s.ReplicaPolicy = &v
return s
}
// SetReplicaTags sets the ReplicaTags field's value.
func (s *ReplicateKeyOutput) SetReplicaTags(v []*Tag) *ReplicateKeyOutput {
s.ReplicaTags = v
return s
}
type RetireGrantInput struct {
_ struct{} `type:"structure"`
// Identifies the grant to retire. To get the grant ID, use CreateGrant, ListGrants,
// or ListRetirableGrants.
//
// * Grant ID Example - 0123456789012345678901234567890123456789012345678901234567890123
GrantId *string `min:"1" type:"string"`
// Identifies the grant to be retired. You can use a grant token to identify
// a new grant even before it has achieved eventual consistency.
//
// Only the CreateGrant operation returns a grant token. For details, see Grant
// token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Eventual consistency (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#terms-eventual-consistency)
// in the Key Management Service Developer Guide.
GrantToken *string `min:"1" type:"string"`
// The key ARN KMS key associated with the grant. To find the key ARN, use the
// ListKeys operation.
//
// For example: arn:aws:kms:us-east-2:444455556666:key/1234abcd-12ab-34cd-56ef-1234567890ab
KeyId *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RetireGrantInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RetireGrantInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *RetireGrantInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "RetireGrantInput"}
if s.GrantId != nil && len(*s.GrantId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GrantId", 1))
}
if s.GrantToken != nil && len(*s.GrantToken) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GrantToken", 1))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantId sets the GrantId field's value.
func (s *RetireGrantInput) SetGrantId(v string) *RetireGrantInput {
s.GrantId = &v
return s
}
// SetGrantToken sets the GrantToken field's value.
func (s *RetireGrantInput) SetGrantToken(v string) *RetireGrantInput {
s.GrantToken = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *RetireGrantInput) SetKeyId(v string) *RetireGrantInput {
s.KeyId = &v
return s
}
type RetireGrantOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RetireGrantOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RetireGrantOutput) GoString() string {
return s.String()
}
type RevokeGrantInput struct {
_ struct{} `type:"structure"`
// Identifies the grant to revoke. To get the grant ID, use CreateGrant, ListGrants,
// or ListRetirableGrants.
//
// GrantId is a required field
GrantId *string `min:"1" type:"string" required:"true"`
// A unique identifier for the KMS key associated with the grant. To get the
// key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// Specify the key ID or key ARN of the KMS key. To specify a KMS key in a different
// Amazon Web Services account, you must use the key ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RevokeGrantInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RevokeGrantInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *RevokeGrantInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "RevokeGrantInput"}
if s.GrantId == nil {
invalidParams.Add(request.NewErrParamRequired("GrantId"))
}
if s.GrantId != nil && len(*s.GrantId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("GrantId", 1))
}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantId sets the GrantId field's value.
func (s *RevokeGrantInput) SetGrantId(v string) *RevokeGrantInput {
s.GrantId = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *RevokeGrantInput) SetKeyId(v string) *RevokeGrantInput {
s.KeyId = &v
return s
}
type RevokeGrantOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RevokeGrantOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RevokeGrantOutput) GoString() string {
return s.String()
}
type ScheduleKeyDeletionInput struct {
_ struct{} `type:"structure"`
// The unique identifier of the KMS key to delete.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The waiting period, specified in number of days. After the waiting period
// ends, KMS deletes the KMS key.
//
// If the KMS key is a multi-Region primary key with replicas, the waiting period
// begins when the last of its replica keys is deleted. Otherwise, the waiting
// period begins immediately.
//
// This value is optional. If you include a value, it must be between 7 and
// 30, inclusive. If you do not include a value, it defaults to 30.
PendingWindowInDays *int64 `min:"1" type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ScheduleKeyDeletionInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ScheduleKeyDeletionInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ScheduleKeyDeletionInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ScheduleKeyDeletionInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.PendingWindowInDays != nil && *s.PendingWindowInDays < 1 {
invalidParams.Add(request.NewErrParamMinValue("PendingWindowInDays", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *ScheduleKeyDeletionInput) SetKeyId(v string) *ScheduleKeyDeletionInput {
s.KeyId = &v
return s
}
// SetPendingWindowInDays sets the PendingWindowInDays field's value.
func (s *ScheduleKeyDeletionInput) SetPendingWindowInDays(v int64) *ScheduleKeyDeletionInput {
s.PendingWindowInDays = &v
return s
}
type ScheduleKeyDeletionOutput struct {
_ struct{} `type:"structure"`
// The date and time after which KMS deletes the KMS key.
//
// If the KMS key is a multi-Region primary key with replica keys, this field
// does not appear. The deletion date for the primary key isn't known until
// its last replica key is deleted.
DeletionDate *time.Time `type:"timestamp"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the KMS key whose deletion is scheduled.
KeyId *string `min:"1" type:"string"`
// The current status of the KMS key.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide.
KeyState *string `type:"string" enum:"KeyState"`
// The waiting period before the KMS key is deleted.
//
// If the KMS key is a multi-Region primary key with replicas, the waiting period
// begins when the last of its replica keys is deleted. Otherwise, the waiting
// period begins immediately.
PendingWindowInDays *int64 `min:"1" type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ScheduleKeyDeletionOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ScheduleKeyDeletionOutput) GoString() string {
return s.String()
}
// SetDeletionDate sets the DeletionDate field's value.
func (s *ScheduleKeyDeletionOutput) SetDeletionDate(v time.Time) *ScheduleKeyDeletionOutput {
s.DeletionDate = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *ScheduleKeyDeletionOutput) SetKeyId(v string) *ScheduleKeyDeletionOutput {
s.KeyId = &v
return s
}
// SetKeyState sets the KeyState field's value.
func (s *ScheduleKeyDeletionOutput) SetKeyState(v string) *ScheduleKeyDeletionOutput {
s.KeyState = &v
return s
}
// SetPendingWindowInDays sets the PendingWindowInDays field's value.
func (s *ScheduleKeyDeletionOutput) SetPendingWindowInDays(v int64) *ScheduleKeyDeletionOutput {
s.PendingWindowInDays = &v
return s
}
type SignInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Identifies an asymmetric KMS key. KMS uses the private key in the asymmetric
// KMS key to sign the message. The KeyUsage type of the KMS key must be SIGN_VERIFY.
// To find the KeyUsage of a KMS key, use the DescribeKey operation.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Specifies the message or message digest to sign. Messages can be 0-4096 bytes.
// To sign a larger message, provide the message digest.
//
// If you provide a message, KMS generates a hash digest of the message and
// then signs it.
//
// Message is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by SignInput's
// String and GoString methods.
//
// Message is automatically base64 encoded/decoded by the SDK.
//
// Message is a required field
Message []byte `min:"1" type:"blob" required:"true" sensitive:"true"`
// Tells KMS whether the value of the Message parameter is a message or message
// digest. The default value, RAW, indicates a message. To indicate a message
// digest, enter DIGEST.
MessageType *string `type:"string" enum:"MessageType"`
// Specifies the signing algorithm to use when signing the message.
//
// Choose an algorithm that is compatible with the type and size of the specified
// asymmetric KMS key.
//
// SigningAlgorithm is a required field
SigningAlgorithm *string `type:"string" required:"true" enum:"SigningAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s SignInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s SignInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *SignInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "SignInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Message == nil {
invalidParams.Add(request.NewErrParamRequired("Message"))
}
if s.Message != nil && len(s.Message) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Message", 1))
}
if s.SigningAlgorithm == nil {
invalidParams.Add(request.NewErrParamRequired("SigningAlgorithm"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *SignInput) SetGrantTokens(v []*string) *SignInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *SignInput) SetKeyId(v string) *SignInput {
s.KeyId = &v
return s
}
// SetMessage sets the Message field's value.
func (s *SignInput) SetMessage(v []byte) *SignInput {
s.Message = v
return s
}
// SetMessageType sets the MessageType field's value.
func (s *SignInput) SetMessageType(v string) *SignInput {
s.MessageType = &v
return s
}
// SetSigningAlgorithm sets the SigningAlgorithm field's value.
func (s *SignInput) SetSigningAlgorithm(v string) *SignInput {
s.SigningAlgorithm = &v
return s
}
type SignOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the asymmetric KMS key that was used to sign the message.
KeyId *string `min:"1" type:"string"`
// The cryptographic signature that was generated for the message.
//
// * When used with the supported RSA signing algorithms, the encoding of
// this value is defined by PKCS #1 in RFC 8017 (https://tools.ietf.org/html/rfc8017).
//
// * When used with the ECDSA_SHA_256, ECDSA_SHA_384, or ECDSA_SHA_512 signing
// algorithms, this value is a DER-encoded object as defined by ANS X9.62–2005
// and RFC 3279 Section 2.2.3 (https://tools.ietf.org/html/rfc3279#section-2.2.3).
// This is the most commonly used signature format and is appropriate for
// most uses.
//
// When you use the HTTP API or the Amazon Web Services CLI, the value is Base64-encoded.
// Otherwise, it is not Base64-encoded.
// Signature is automatically base64 encoded/decoded by the SDK.
Signature []byte `min:"1" type:"blob"`
// The signing algorithm that was used to sign the message.
SigningAlgorithm *string `type:"string" enum:"SigningAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s SignOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s SignOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *SignOutput) SetKeyId(v string) *SignOutput {
s.KeyId = &v
return s
}
// SetSignature sets the Signature field's value.
func (s *SignOutput) SetSignature(v []byte) *SignOutput {
s.Signature = v
return s
}
// SetSigningAlgorithm sets the SigningAlgorithm field's value.
func (s *SignOutput) SetSigningAlgorithm(v string) *SignOutput {
s.SigningAlgorithm = &v
return s
}
// A key-value pair. A tag consists of a tag key and a tag value. Tag keys and
// tag values are both required, but tag values can be empty (null) strings.
//
// For information about the rules that apply to tag keys and tag values, see
// User-Defined Tag Restrictions (https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/allocation-tag-restrictions.html)
// in the Amazon Web Services Billing and Cost Management User Guide.
type Tag struct {
_ struct{} `type:"structure"`
// The key of the tag.
//
// TagKey is a required field
TagKey *string `min:"1" type:"string" required:"true"`
// The value of the tag.
//
// TagValue is a required field
TagValue *string `type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *Tag) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "Tag"}
if s.TagKey == nil {
invalidParams.Add(request.NewErrParamRequired("TagKey"))
}
if s.TagKey != nil && len(*s.TagKey) < 1 {
invalidParams.Add(request.NewErrParamMinLen("TagKey", 1))
}
if s.TagValue == nil {
invalidParams.Add(request.NewErrParamRequired("TagValue"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetTagKey sets the TagKey field's value.
func (s *Tag) SetTagKey(v string) *Tag {
s.TagKey = &v
return s
}
// SetTagValue sets the TagValue field's value.
func (s *Tag) SetTagValue(v string) *Tag {
s.TagValue = &v
return s
}
// The request was rejected because one or more tags are not valid.
type TagException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagException) GoString() string {
return s.String()
}
func newErrorTagException(v protocol.ResponseMetadata) error {
return &TagException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *TagException) Code() string {
return "TagException"
}
// Message returns the exception's message.
func (s *TagException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *TagException) OrigErr() error {
return nil
}
func (s *TagException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *TagException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *TagException) RequestID() string {
return s.RespMetadata.RequestID
}
type TagResourceInput struct {
_ struct{} `type:"structure"`
// Identifies a customer managed key in the account and Region.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// One or more tags.
//
// Each tag consists of a tag key and a tag value. The tag value can be an empty
// (null) string.
//
// You cannot have more than one tag on a KMS key with the same tag key. If
// you specify an existing tag key with a different tag value, KMS replaces
// the current tag value with the specified one.
//
// Tags is a required field
Tags []*Tag `type:"list" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagResourceInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagResourceInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *TagResourceInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "TagResourceInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Tags == nil {
invalidParams.Add(request.NewErrParamRequired("Tags"))
}
if s.Tags != nil {
for i, v := range s.Tags {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *TagResourceInput) SetKeyId(v string) *TagResourceInput {
s.KeyId = &v
return s
}
// SetTags sets the Tags field's value.
func (s *TagResourceInput) SetTags(v []*Tag) *TagResourceInput {
s.Tags = v
return s
}
type TagResourceOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagResourceOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TagResourceOutput) GoString() string {
return s.String()
}
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
type UnsupportedOperationException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnsupportedOperationException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnsupportedOperationException) GoString() string {
return s.String()
}
func newErrorUnsupportedOperationException(v protocol.ResponseMetadata) error {
return &UnsupportedOperationException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *UnsupportedOperationException) Code() string {
return "UnsupportedOperationException"
}
// Message returns the exception's message.
func (s *UnsupportedOperationException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *UnsupportedOperationException) OrigErr() error {
return nil
}
func (s *UnsupportedOperationException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *UnsupportedOperationException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *UnsupportedOperationException) RequestID() string {
return s.RespMetadata.RequestID
}
type UntagResourceInput struct {
_ struct{} `type:"structure"`
// Identifies the KMS key from which you are removing tags.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// One or more tag keys. Specify only the tag keys, not the tag values.
//
// TagKeys is a required field
TagKeys []*string `type:"list" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UntagResourceInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UntagResourceInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *UntagResourceInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "UntagResourceInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.TagKeys == nil {
invalidParams.Add(request.NewErrParamRequired("TagKeys"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *UntagResourceInput) SetKeyId(v string) *UntagResourceInput {
s.KeyId = &v
return s
}
// SetTagKeys sets the TagKeys field's value.
func (s *UntagResourceInput) SetTagKeys(v []*string) *UntagResourceInput {
s.TagKeys = v
return s
}
type UntagResourceOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UntagResourceOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UntagResourceOutput) GoString() string {
return s.String()
}
type UpdateAliasInput struct {
_ struct{} `type:"structure"`
// Identifies the alias that is changing its KMS key. This value must begin
// with alias/ followed by the alias name, such as alias/ExampleAlias. You cannot
// use UpdateAlias to change the alias name.
//
// AliasName is a required field
AliasName *string `min:"1" type:"string" required:"true"`
// Identifies the customer managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)
// to associate with the alias. You don't have permission to associate an alias
// with an Amazon Web Services managed key (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk).
//
// The KMS key must be in the same Amazon Web Services account and Region as
// the alias. Also, the new target KMS key must be the same type as the current
// target KMS key (both symmetric or both asymmetric) and they must have the
// same key usage.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// To verify that the alias is mapped to the correct KMS key, use ListAliases.
//
// TargetKeyId is a required field
TargetKeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateAliasInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateAliasInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *UpdateAliasInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "UpdateAliasInput"}
if s.AliasName == nil {
invalidParams.Add(request.NewErrParamRequired("AliasName"))
}
if s.AliasName != nil && len(*s.AliasName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("AliasName", 1))
}
if s.TargetKeyId == nil {
invalidParams.Add(request.NewErrParamRequired("TargetKeyId"))
}
if s.TargetKeyId != nil && len(*s.TargetKeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("TargetKeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAliasName sets the AliasName field's value.
func (s *UpdateAliasInput) SetAliasName(v string) *UpdateAliasInput {
s.AliasName = &v
return s
}
// SetTargetKeyId sets the TargetKeyId field's value.
func (s *UpdateAliasInput) SetTargetKeyId(v string) *UpdateAliasInput {
s.TargetKeyId = &v
return s
}
type UpdateAliasOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateAliasOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateAliasOutput) GoString() string {
return s.String()
}
type UpdateCustomKeyStoreInput struct {
_ struct{} `type:"structure"`
// Associates the custom key store with a related CloudHSM cluster.
//
// Enter the cluster ID of the cluster that you used to create the custom key
// store or a cluster that shares a backup history and has the same cluster
// certificate as the original cluster. You cannot use this parameter to associate
// a custom key store with an unrelated cluster. In addition, the replacement
// cluster must fulfill the requirements (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// for a cluster associated with a custom key store. To view the cluster certificate
// of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
CloudHsmClusterId *string `min:"19" type:"string"`
// Identifies the custom key store that you want to update. Enter the ID of
// the custom key store. To find the ID of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// CustomKeyStoreId is a required field
CustomKeyStoreId *string `min:"1" type:"string" required:"true"`
// Enter the current password of the kmsuser crypto user (CU) in the CloudHSM
// cluster that is associated with the custom key store.
//
// This parameter tells KMS the current password of the kmsuser crypto user
// (CU). It does not set or change the password of any users in the CloudHSM
// cluster.
//
// KeyStorePassword is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by UpdateCustomKeyStoreInput's
// String and GoString methods.
KeyStorePassword *string `min:"7" type:"string" sensitive:"true"`
// Changes the friendly name of the custom key store to the value that you specify.
// The custom key store name must be unique in the Amazon Web Services account.
NewCustomKeyStoreName *string `min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateCustomKeyStoreInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateCustomKeyStoreInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *UpdateCustomKeyStoreInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "UpdateCustomKeyStoreInput"}
if s.CloudHsmClusterId != nil && len(*s.CloudHsmClusterId) < 19 {
invalidParams.Add(request.NewErrParamMinLen("CloudHsmClusterId", 19))
}
if s.CustomKeyStoreId == nil {
invalidParams.Add(request.NewErrParamRequired("CustomKeyStoreId"))
}
if s.CustomKeyStoreId != nil && len(*s.CustomKeyStoreId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("CustomKeyStoreId", 1))
}
if s.KeyStorePassword != nil && len(*s.KeyStorePassword) < 7 {
invalidParams.Add(request.NewErrParamMinLen("KeyStorePassword", 7))
}
if s.NewCustomKeyStoreName != nil && len(*s.NewCustomKeyStoreName) < 1 {
invalidParams.Add(request.NewErrParamMinLen("NewCustomKeyStoreName", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetCloudHsmClusterId sets the CloudHsmClusterId field's value.
func (s *UpdateCustomKeyStoreInput) SetCloudHsmClusterId(v string) *UpdateCustomKeyStoreInput {
s.CloudHsmClusterId = &v
return s
}
// SetCustomKeyStoreId sets the CustomKeyStoreId field's value.
func (s *UpdateCustomKeyStoreInput) SetCustomKeyStoreId(v string) *UpdateCustomKeyStoreInput {
s.CustomKeyStoreId = &v
return s
}
// SetKeyStorePassword sets the KeyStorePassword field's value.
func (s *UpdateCustomKeyStoreInput) SetKeyStorePassword(v string) *UpdateCustomKeyStoreInput {
s.KeyStorePassword = &v
return s
}
// SetNewCustomKeyStoreName sets the NewCustomKeyStoreName field's value.
func (s *UpdateCustomKeyStoreInput) SetNewCustomKeyStoreName(v string) *UpdateCustomKeyStoreInput {
s.NewCustomKeyStoreName = &v
return s
}
type UpdateCustomKeyStoreOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateCustomKeyStoreOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateCustomKeyStoreOutput) GoString() string {
return s.String()
}
type UpdateKeyDescriptionInput struct {
_ struct{} `type:"structure"`
// New description for the KMS key.
//
// Description is a required field
Description *string `type:"string" required:"true"`
// Updates the description of the specified KMS key.
//
// Specify the key ID or key ARN of the KMS key.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateKeyDescriptionInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateKeyDescriptionInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *UpdateKeyDescriptionInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "UpdateKeyDescriptionInput"}
if s.Description == nil {
invalidParams.Add(request.NewErrParamRequired("Description"))
}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDescription sets the Description field's value.
func (s *UpdateKeyDescriptionInput) SetDescription(v string) *UpdateKeyDescriptionInput {
s.Description = &v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *UpdateKeyDescriptionInput) SetKeyId(v string) *UpdateKeyDescriptionInput {
s.KeyId = &v
return s
}
type UpdateKeyDescriptionOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateKeyDescriptionOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdateKeyDescriptionOutput) GoString() string {
return s.String()
}
type UpdatePrimaryRegionInput struct {
_ struct{} `type:"structure"`
// Identifies the current primary key. When the operation completes, this KMS
// key will be a replica key.
//
// Specify the key ID or key ARN of a multi-Region primary key.
//
// For example:
//
// * Key ID: mrk-1234abcd12ab34cd56ef1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The Amazon Web Services Region of the new primary key. Enter the Region ID,
// such as us-east-1 or ap-southeast-2. There must be an existing replica key
// in this Region.
//
// When the operation completes, the multi-Region key in this Region will be
// the primary key.
//
// PrimaryRegion is a required field
PrimaryRegion *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdatePrimaryRegionInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdatePrimaryRegionInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *UpdatePrimaryRegionInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "UpdatePrimaryRegionInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.PrimaryRegion == nil {
invalidParams.Add(request.NewErrParamRequired("PrimaryRegion"))
}
if s.PrimaryRegion != nil && len(*s.PrimaryRegion) < 1 {
invalidParams.Add(request.NewErrParamMinLen("PrimaryRegion", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKeyId sets the KeyId field's value.
func (s *UpdatePrimaryRegionInput) SetKeyId(v string) *UpdatePrimaryRegionInput {
s.KeyId = &v
return s
}
// SetPrimaryRegion sets the PrimaryRegion field's value.
func (s *UpdatePrimaryRegionInput) SetPrimaryRegion(v string) *UpdatePrimaryRegionInput {
s.PrimaryRegion = &v
return s
}
type UpdatePrimaryRegionOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdatePrimaryRegionOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UpdatePrimaryRegionOutput) GoString() string {
return s.String()
}
type VerifyInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// Identifies the asymmetric KMS key that will be used to verify the signature.
// This must be the same KMS key that was used to generate the signature. If
// you specify a different KMS key, the signature verification fails.
//
// To specify a KMS key, use its key ID, key ARN, alias name, or alias ARN.
// When using an alias name, prefix it with "alias/". To specify a KMS key in
// a different Amazon Web Services account, you must use the key ARN or alias
// ARN.
//
// For example:
//
// * Key ID: 1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Key ARN: arn:aws:kms:us-east-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab
//
// * Alias name: alias/ExampleAlias
//
// * Alias ARN: arn:aws:kms:us-east-2:111122223333:alias/ExampleAlias
//
// To get the key ID and key ARN for a KMS key, use ListKeys or DescribeKey.
// To get the alias name and alias ARN, use ListAliases.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// Specifies the message that was signed. You can submit a raw message of up
// to 4096 bytes, or a hash digest of the message. If you submit a digest, use
// the MessageType parameter with a value of DIGEST.
//
// If the message specified here is different from the message that was signed,
// the signature verification fails. A message and its hash digest are considered
// to be the same message.
//
// Message is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by VerifyInput's
// String and GoString methods.
//
// Message is automatically base64 encoded/decoded by the SDK.
//
// Message is a required field
Message []byte `min:"1" type:"blob" required:"true" sensitive:"true"`
// Tells KMS whether the value of the Message parameter is a message or message
// digest. The default value, RAW, indicates a message. To indicate a message
// digest, enter DIGEST.
//
// Use the DIGEST value only when the value of the Message parameter is a message
// digest. If you use the DIGEST value with a raw message, the security of the
// verification operation can be compromised.
MessageType *string `type:"string" enum:"MessageType"`
// The signature that the Sign operation generated.
// Signature is automatically base64 encoded/decoded by the SDK.
//
// Signature is a required field
Signature []byte `min:"1" type:"blob" required:"true"`
// The signing algorithm that was used to sign the message. If you submit a
// different algorithm, the signature verification fails.
//
// SigningAlgorithm is a required field
SigningAlgorithm *string `type:"string" required:"true" enum:"SigningAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *VerifyInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "VerifyInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Message == nil {
invalidParams.Add(request.NewErrParamRequired("Message"))
}
if s.Message != nil && len(s.Message) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Message", 1))
}
if s.Signature == nil {
invalidParams.Add(request.NewErrParamRequired("Signature"))
}
if s.Signature != nil && len(s.Signature) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Signature", 1))
}
if s.SigningAlgorithm == nil {
invalidParams.Add(request.NewErrParamRequired("SigningAlgorithm"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *VerifyInput) SetGrantTokens(v []*string) *VerifyInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *VerifyInput) SetKeyId(v string) *VerifyInput {
s.KeyId = &v
return s
}
// SetMessage sets the Message field's value.
func (s *VerifyInput) SetMessage(v []byte) *VerifyInput {
s.Message = v
return s
}
// SetMessageType sets the MessageType field's value.
func (s *VerifyInput) SetMessageType(v string) *VerifyInput {
s.MessageType = &v
return s
}
// SetSignature sets the Signature field's value.
func (s *VerifyInput) SetSignature(v []byte) *VerifyInput {
s.Signature = v
return s
}
// SetSigningAlgorithm sets the SigningAlgorithm field's value.
func (s *VerifyInput) SetSigningAlgorithm(v string) *VerifyInput {
s.SigningAlgorithm = &v
return s
}
type VerifyMacInput struct {
_ struct{} `type:"structure"`
// A list of grant tokens.
//
// Use a grant token when your permission to call this operation comes from
// a new grant that has not yet achieved eventual consistency. For more information,
// see Grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grants.html#grant_token)
// and Using a grant token (https://docs.aws.amazon.com/kms/latest/developerguide/grant-manage.html#using-grant-token)
// in the Key Management Service Developer Guide.
GrantTokens []*string `type:"list"`
// The KMS key that will be used in the verification.
//
// Enter a key ID of the KMS key that was used to generate the HMAC. If you
// identify a different KMS key, the VerifyMac operation fails.
//
// KeyId is a required field
KeyId *string `min:"1" type:"string" required:"true"`
// The HMAC to verify. Enter the HMAC that was generated by the GenerateMac
// operation when you specified the same message, HMAC KMS key, and MAC algorithm
// as the values specified in this request.
// Mac is automatically base64 encoded/decoded by the SDK.
//
// Mac is a required field
Mac []byte `min:"1" type:"blob" required:"true"`
// The MAC algorithm that will be used in the verification. Enter the same MAC
// algorithm that was used to compute the HMAC. This algorithm must be supported
// by the HMAC KMS key identified by the KeyId parameter.
//
// MacAlgorithm is a required field
MacAlgorithm *string `type:"string" required:"true" enum:"MacAlgorithmSpec"`
// The message that will be used in the verification. Enter the same message
// that was used to generate the HMAC.
//
// GenerateMac and VerifyMac do not provide special handling for message digests.
// If you generated an HMAC for a hash digest of a message, you must verify
// the HMAC for the same hash digest.
//
// Message is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by VerifyMacInput's
// String and GoString methods.
//
// Message is automatically base64 encoded/decoded by the SDK.
//
// Message is a required field
Message []byte `min:"1" type:"blob" required:"true" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyMacInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyMacInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *VerifyMacInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "VerifyMacInput"}
if s.KeyId == nil {
invalidParams.Add(request.NewErrParamRequired("KeyId"))
}
if s.KeyId != nil && len(*s.KeyId) < 1 {
invalidParams.Add(request.NewErrParamMinLen("KeyId", 1))
}
if s.Mac == nil {
invalidParams.Add(request.NewErrParamRequired("Mac"))
}
if s.Mac != nil && len(s.Mac) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Mac", 1))
}
if s.MacAlgorithm == nil {
invalidParams.Add(request.NewErrParamRequired("MacAlgorithm"))
}
if s.Message == nil {
invalidParams.Add(request.NewErrParamRequired("Message"))
}
if s.Message != nil && len(s.Message) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Message", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetGrantTokens sets the GrantTokens field's value.
func (s *VerifyMacInput) SetGrantTokens(v []*string) *VerifyMacInput {
s.GrantTokens = v
return s
}
// SetKeyId sets the KeyId field's value.
func (s *VerifyMacInput) SetKeyId(v string) *VerifyMacInput {
s.KeyId = &v
return s
}
// SetMac sets the Mac field's value.
func (s *VerifyMacInput) SetMac(v []byte) *VerifyMacInput {
s.Mac = v
return s
}
// SetMacAlgorithm sets the MacAlgorithm field's value.
func (s *VerifyMacInput) SetMacAlgorithm(v string) *VerifyMacInput {
s.MacAlgorithm = &v
return s
}
// SetMessage sets the Message field's value.
func (s *VerifyMacInput) SetMessage(v []byte) *VerifyMacInput {
s.Message = v
return s
}
type VerifyMacOutput struct {
_ struct{} `type:"structure"`
// The HMAC KMS key used in the verification.
KeyId *string `min:"1" type:"string"`
// The MAC algorithm used in the verification.
MacAlgorithm *string `type:"string" enum:"MacAlgorithmSpec"`
// A Boolean value that indicates whether the HMAC was verified. A value of
// True indicates that the HMAC (Mac) was generated with the specified Message,
// HMAC KMS key (KeyID) and MacAlgorithm..
//
// If the HMAC is not verified, the VerifyMac operation fails with a KMSInvalidMacException
// exception. This exception indicates that one or more of the inputs changed
// since the HMAC was computed.
MacValid *bool `type:"boolean"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyMacOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyMacOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *VerifyMacOutput) SetKeyId(v string) *VerifyMacOutput {
s.KeyId = &v
return s
}
// SetMacAlgorithm sets the MacAlgorithm field's value.
func (s *VerifyMacOutput) SetMacAlgorithm(v string) *VerifyMacOutput {
s.MacAlgorithm = &v
return s
}
// SetMacValid sets the MacValid field's value.
func (s *VerifyMacOutput) SetMacValid(v bool) *VerifyMacOutput {
s.MacValid = &v
return s
}
type VerifyOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (key ARN (https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN))
// of the asymmetric KMS key that was used to verify the signature.
KeyId *string `min:"1" type:"string"`
// A Boolean value that indicates whether the signature was verified. A value
// of True indicates that the Signature was produced by signing the Message
// with the specified KeyID and SigningAlgorithm. If the signature is not verified,
// the Verify operation fails with a KMSInvalidSignatureException exception.
SignatureValid *bool `type:"boolean"`
// The signing algorithm that was used to verify the signature.
SigningAlgorithm *string `type:"string" enum:"SigningAlgorithmSpec"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s VerifyOutput) GoString() string {
return s.String()
}
// SetKeyId sets the KeyId field's value.
func (s *VerifyOutput) SetKeyId(v string) *VerifyOutput {
s.KeyId = &v
return s
}
// SetSignatureValid sets the SignatureValid field's value.
func (s *VerifyOutput) SetSignatureValid(v bool) *VerifyOutput {
s.SignatureValid = &v
return s
}
// SetSigningAlgorithm sets the SigningAlgorithm field's value.
func (s *VerifyOutput) SetSigningAlgorithm(v string) *VerifyOutput {
s.SigningAlgorithm = &v
return s
}
const (
// AlgorithmSpecRsaesPkcs1V15 is a AlgorithmSpec enum value
AlgorithmSpecRsaesPkcs1V15 = "RSAES_PKCS1_V1_5"
// AlgorithmSpecRsaesOaepSha1 is a AlgorithmSpec enum value
AlgorithmSpecRsaesOaepSha1 = "RSAES_OAEP_SHA_1"
// AlgorithmSpecRsaesOaepSha256 is a AlgorithmSpec enum value
AlgorithmSpecRsaesOaepSha256 = "RSAES_OAEP_SHA_256"
)
// AlgorithmSpec_Values returns all elements of the AlgorithmSpec enum
func AlgorithmSpec_Values() []string {
return []string{
AlgorithmSpecRsaesPkcs1V15,
AlgorithmSpecRsaesOaepSha1,
AlgorithmSpecRsaesOaepSha256,
}
}
const (
// ConnectionErrorCodeTypeInvalidCredentials is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeInvalidCredentials = "INVALID_CREDENTIALS"
// ConnectionErrorCodeTypeClusterNotFound is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeClusterNotFound = "CLUSTER_NOT_FOUND"
// ConnectionErrorCodeTypeNetworkErrors is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeNetworkErrors = "NETWORK_ERRORS"
// ConnectionErrorCodeTypeInternalError is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeInternalError = "INTERNAL_ERROR"
// ConnectionErrorCodeTypeInsufficientCloudhsmHsms is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeInsufficientCloudhsmHsms = "INSUFFICIENT_CLOUDHSM_HSMS"
// ConnectionErrorCodeTypeUserLockedOut is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeUserLockedOut = "USER_LOCKED_OUT"
// ConnectionErrorCodeTypeUserNotFound is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeUserNotFound = "USER_NOT_FOUND"
// ConnectionErrorCodeTypeUserLoggedIn is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeUserLoggedIn = "USER_LOGGED_IN"
// ConnectionErrorCodeTypeSubnetNotFound is a ConnectionErrorCodeType enum value
ConnectionErrorCodeTypeSubnetNotFound = "SUBNET_NOT_FOUND"
)
// ConnectionErrorCodeType_Values returns all elements of the ConnectionErrorCodeType enum
func ConnectionErrorCodeType_Values() []string {
return []string{
ConnectionErrorCodeTypeInvalidCredentials,
ConnectionErrorCodeTypeClusterNotFound,
ConnectionErrorCodeTypeNetworkErrors,
ConnectionErrorCodeTypeInternalError,
ConnectionErrorCodeTypeInsufficientCloudhsmHsms,
ConnectionErrorCodeTypeUserLockedOut,
ConnectionErrorCodeTypeUserNotFound,
ConnectionErrorCodeTypeUserLoggedIn,
ConnectionErrorCodeTypeSubnetNotFound,
}
}
const (
// ConnectionStateTypeConnected is a ConnectionStateType enum value
ConnectionStateTypeConnected = "CONNECTED"
// ConnectionStateTypeConnecting is a ConnectionStateType enum value
ConnectionStateTypeConnecting = "CONNECTING"
// ConnectionStateTypeFailed is a ConnectionStateType enum value
ConnectionStateTypeFailed = "FAILED"
// ConnectionStateTypeDisconnected is a ConnectionStateType enum value
ConnectionStateTypeDisconnected = "DISCONNECTED"
// ConnectionStateTypeDisconnecting is a ConnectionStateType enum value
ConnectionStateTypeDisconnecting = "DISCONNECTING"
)
// ConnectionStateType_Values returns all elements of the ConnectionStateType enum
func ConnectionStateType_Values() []string {
return []string{
ConnectionStateTypeConnected,
ConnectionStateTypeConnecting,
ConnectionStateTypeFailed,
ConnectionStateTypeDisconnected,
ConnectionStateTypeDisconnecting,
}
}
const (
// CustomerMasterKeySpecRsa2048 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecRsa2048 = "RSA_2048"
// CustomerMasterKeySpecRsa3072 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecRsa3072 = "RSA_3072"
// CustomerMasterKeySpecRsa4096 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecRsa4096 = "RSA_4096"
// CustomerMasterKeySpecEccNistP256 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecEccNistP256 = "ECC_NIST_P256"
// CustomerMasterKeySpecEccNistP384 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecEccNistP384 = "ECC_NIST_P384"
// CustomerMasterKeySpecEccNistP521 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecEccNistP521 = "ECC_NIST_P521"
// CustomerMasterKeySpecEccSecgP256k1 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecEccSecgP256k1 = "ECC_SECG_P256K1"
// CustomerMasterKeySpecSymmetricDefault is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecSymmetricDefault = "SYMMETRIC_DEFAULT"
// CustomerMasterKeySpecHmac224 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecHmac224 = "HMAC_224"
// CustomerMasterKeySpecHmac256 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecHmac256 = "HMAC_256"
// CustomerMasterKeySpecHmac384 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecHmac384 = "HMAC_384"
// CustomerMasterKeySpecHmac512 is a CustomerMasterKeySpec enum value
CustomerMasterKeySpecHmac512 = "HMAC_512"
)
// CustomerMasterKeySpec_Values returns all elements of the CustomerMasterKeySpec enum
func CustomerMasterKeySpec_Values() []string {
return []string{
CustomerMasterKeySpecRsa2048,
CustomerMasterKeySpecRsa3072,
CustomerMasterKeySpecRsa4096,
CustomerMasterKeySpecEccNistP256,
CustomerMasterKeySpecEccNistP384,
CustomerMasterKeySpecEccNistP521,
CustomerMasterKeySpecEccSecgP256k1,
CustomerMasterKeySpecSymmetricDefault,
CustomerMasterKeySpecHmac224,
CustomerMasterKeySpecHmac256,
CustomerMasterKeySpecHmac384,
CustomerMasterKeySpecHmac512,
}
}
const (
// DataKeyPairSpecRsa2048 is a DataKeyPairSpec enum value
DataKeyPairSpecRsa2048 = "RSA_2048"
// DataKeyPairSpecRsa3072 is a DataKeyPairSpec enum value
DataKeyPairSpecRsa3072 = "RSA_3072"
// DataKeyPairSpecRsa4096 is a DataKeyPairSpec enum value
DataKeyPairSpecRsa4096 = "RSA_4096"
// DataKeyPairSpecEccNistP256 is a DataKeyPairSpec enum value
DataKeyPairSpecEccNistP256 = "ECC_NIST_P256"
// DataKeyPairSpecEccNistP384 is a DataKeyPairSpec enum value
DataKeyPairSpecEccNistP384 = "ECC_NIST_P384"
// DataKeyPairSpecEccNistP521 is a DataKeyPairSpec enum value
DataKeyPairSpecEccNistP521 = "ECC_NIST_P521"
// DataKeyPairSpecEccSecgP256k1 is a DataKeyPairSpec enum value
DataKeyPairSpecEccSecgP256k1 = "ECC_SECG_P256K1"
)
// DataKeyPairSpec_Values returns all elements of the DataKeyPairSpec enum
func DataKeyPairSpec_Values() []string {
return []string{
DataKeyPairSpecRsa2048,
DataKeyPairSpecRsa3072,
DataKeyPairSpecRsa4096,
DataKeyPairSpecEccNistP256,
DataKeyPairSpecEccNistP384,
DataKeyPairSpecEccNistP521,
DataKeyPairSpecEccSecgP256k1,
}
}
const (
// DataKeySpecAes256 is a DataKeySpec enum value
DataKeySpecAes256 = "AES_256"
// DataKeySpecAes128 is a DataKeySpec enum value
DataKeySpecAes128 = "AES_128"
)
// DataKeySpec_Values returns all elements of the DataKeySpec enum
func DataKeySpec_Values() []string {
return []string{
DataKeySpecAes256,
DataKeySpecAes128,
}
}
const (
// EncryptionAlgorithmSpecSymmetricDefault is a EncryptionAlgorithmSpec enum value
EncryptionAlgorithmSpecSymmetricDefault = "SYMMETRIC_DEFAULT"
// EncryptionAlgorithmSpecRsaesOaepSha1 is a EncryptionAlgorithmSpec enum value
EncryptionAlgorithmSpecRsaesOaepSha1 = "RSAES_OAEP_SHA_1"
// EncryptionAlgorithmSpecRsaesOaepSha256 is a EncryptionAlgorithmSpec enum value
EncryptionAlgorithmSpecRsaesOaepSha256 = "RSAES_OAEP_SHA_256"
)
// EncryptionAlgorithmSpec_Values returns all elements of the EncryptionAlgorithmSpec enum
func EncryptionAlgorithmSpec_Values() []string {
return []string{
EncryptionAlgorithmSpecSymmetricDefault,
EncryptionAlgorithmSpecRsaesOaepSha1,
EncryptionAlgorithmSpecRsaesOaepSha256,
}
}
const (
// ExpirationModelTypeKeyMaterialExpires is a ExpirationModelType enum value
ExpirationModelTypeKeyMaterialExpires = "KEY_MATERIAL_EXPIRES"
// ExpirationModelTypeKeyMaterialDoesNotExpire is a ExpirationModelType enum value
ExpirationModelTypeKeyMaterialDoesNotExpire = "KEY_MATERIAL_DOES_NOT_EXPIRE"
)
// ExpirationModelType_Values returns all elements of the ExpirationModelType enum
func ExpirationModelType_Values() []string {
return []string{
ExpirationModelTypeKeyMaterialExpires,
ExpirationModelTypeKeyMaterialDoesNotExpire,
}
}
const (
// GrantOperationDecrypt is a GrantOperation enum value
GrantOperationDecrypt = "Decrypt"
// GrantOperationEncrypt is a GrantOperation enum value
GrantOperationEncrypt = "Encrypt"
// GrantOperationGenerateDataKey is a GrantOperation enum value
GrantOperationGenerateDataKey = "GenerateDataKey"
// GrantOperationGenerateDataKeyWithoutPlaintext is a GrantOperation enum value
GrantOperationGenerateDataKeyWithoutPlaintext = "GenerateDataKeyWithoutPlaintext"
// GrantOperationReEncryptFrom is a GrantOperation enum value
GrantOperationReEncryptFrom = "ReEncryptFrom"
// GrantOperationReEncryptTo is a GrantOperation enum value
GrantOperationReEncryptTo = "ReEncryptTo"
// GrantOperationSign is a GrantOperation enum value
GrantOperationSign = "Sign"
// GrantOperationVerify is a GrantOperation enum value
GrantOperationVerify = "Verify"
// GrantOperationGetPublicKey is a GrantOperation enum value
GrantOperationGetPublicKey = "GetPublicKey"
// GrantOperationCreateGrant is a GrantOperation enum value
GrantOperationCreateGrant = "CreateGrant"
// GrantOperationRetireGrant is a GrantOperation enum value
GrantOperationRetireGrant = "RetireGrant"
// GrantOperationDescribeKey is a GrantOperation enum value
GrantOperationDescribeKey = "DescribeKey"
// GrantOperationGenerateDataKeyPair is a GrantOperation enum value
GrantOperationGenerateDataKeyPair = "GenerateDataKeyPair"
// GrantOperationGenerateDataKeyPairWithoutPlaintext is a GrantOperation enum value
GrantOperationGenerateDataKeyPairWithoutPlaintext = "GenerateDataKeyPairWithoutPlaintext"
// GrantOperationGenerateMac is a GrantOperation enum value
GrantOperationGenerateMac = "GenerateMac"
// GrantOperationVerifyMac is a GrantOperation enum value
GrantOperationVerifyMac = "VerifyMac"
)
// GrantOperation_Values returns all elements of the GrantOperation enum
func GrantOperation_Values() []string {
return []string{
GrantOperationDecrypt,
GrantOperationEncrypt,
GrantOperationGenerateDataKey,
GrantOperationGenerateDataKeyWithoutPlaintext,
GrantOperationReEncryptFrom,
GrantOperationReEncryptTo,
GrantOperationSign,
GrantOperationVerify,
GrantOperationGetPublicKey,
GrantOperationCreateGrant,
GrantOperationRetireGrant,
GrantOperationDescribeKey,
GrantOperationGenerateDataKeyPair,
GrantOperationGenerateDataKeyPairWithoutPlaintext,
GrantOperationGenerateMac,
GrantOperationVerifyMac,
}
}
const (
// KeyManagerTypeAws is a KeyManagerType enum value
KeyManagerTypeAws = "AWS"
// KeyManagerTypeCustomer is a KeyManagerType enum value
KeyManagerTypeCustomer = "CUSTOMER"
)
// KeyManagerType_Values returns all elements of the KeyManagerType enum
func KeyManagerType_Values() []string {
return []string{
KeyManagerTypeAws,
KeyManagerTypeCustomer,
}
}
const (
// KeySpecRsa2048 is a KeySpec enum value
KeySpecRsa2048 = "RSA_2048"
// KeySpecRsa3072 is a KeySpec enum value
KeySpecRsa3072 = "RSA_3072"
// KeySpecRsa4096 is a KeySpec enum value
KeySpecRsa4096 = "RSA_4096"
// KeySpecEccNistP256 is a KeySpec enum value
KeySpecEccNistP256 = "ECC_NIST_P256"
// KeySpecEccNistP384 is a KeySpec enum value
KeySpecEccNistP384 = "ECC_NIST_P384"
// KeySpecEccNistP521 is a KeySpec enum value
KeySpecEccNistP521 = "ECC_NIST_P521"
// KeySpecEccSecgP256k1 is a KeySpec enum value
KeySpecEccSecgP256k1 = "ECC_SECG_P256K1"
// KeySpecSymmetricDefault is a KeySpec enum value
KeySpecSymmetricDefault = "SYMMETRIC_DEFAULT"
// KeySpecHmac224 is a KeySpec enum value
KeySpecHmac224 = "HMAC_224"
// KeySpecHmac256 is a KeySpec enum value
KeySpecHmac256 = "HMAC_256"
// KeySpecHmac384 is a KeySpec enum value
KeySpecHmac384 = "HMAC_384"
// KeySpecHmac512 is a KeySpec enum value
KeySpecHmac512 = "HMAC_512"
)
// KeySpec_Values returns all elements of the KeySpec enum
func KeySpec_Values() []string {
return []string{
KeySpecRsa2048,
KeySpecRsa3072,
KeySpecRsa4096,
KeySpecEccNistP256,
KeySpecEccNistP384,
KeySpecEccNistP521,
KeySpecEccSecgP256k1,
KeySpecSymmetricDefault,
KeySpecHmac224,
KeySpecHmac256,
KeySpecHmac384,
KeySpecHmac512,
}
}
const (
// KeyStateCreating is a KeyState enum value
KeyStateCreating = "Creating"
// KeyStateEnabled is a KeyState enum value
KeyStateEnabled = "Enabled"
// KeyStateDisabled is a KeyState enum value
KeyStateDisabled = "Disabled"
// KeyStatePendingDeletion is a KeyState enum value
KeyStatePendingDeletion = "PendingDeletion"
// KeyStatePendingImport is a KeyState enum value
KeyStatePendingImport = "PendingImport"
// KeyStatePendingReplicaDeletion is a KeyState enum value
KeyStatePendingReplicaDeletion = "PendingReplicaDeletion"
// KeyStateUnavailable is a KeyState enum value
KeyStateUnavailable = "Unavailable"
// KeyStateUpdating is a KeyState enum value
KeyStateUpdating = "Updating"
)
// KeyState_Values returns all elements of the KeyState enum
func KeyState_Values() []string {
return []string{
KeyStateCreating,
KeyStateEnabled,
KeyStateDisabled,
KeyStatePendingDeletion,
KeyStatePendingImport,
KeyStatePendingReplicaDeletion,
KeyStateUnavailable,
KeyStateUpdating,
}
}
const (
// KeyUsageTypeSignVerify is a KeyUsageType enum value
KeyUsageTypeSignVerify = "SIGN_VERIFY"
// KeyUsageTypeEncryptDecrypt is a KeyUsageType enum value
KeyUsageTypeEncryptDecrypt = "ENCRYPT_DECRYPT"
// KeyUsageTypeGenerateVerifyMac is a KeyUsageType enum value
KeyUsageTypeGenerateVerifyMac = "GENERATE_VERIFY_MAC"
)
// KeyUsageType_Values returns all elements of the KeyUsageType enum
func KeyUsageType_Values() []string {
return []string{
KeyUsageTypeSignVerify,
KeyUsageTypeEncryptDecrypt,
KeyUsageTypeGenerateVerifyMac,
}
}
const (
// MacAlgorithmSpecHmacSha224 is a MacAlgorithmSpec enum value
MacAlgorithmSpecHmacSha224 = "HMAC_SHA_224"
// MacAlgorithmSpecHmacSha256 is a MacAlgorithmSpec enum value
MacAlgorithmSpecHmacSha256 = "HMAC_SHA_256"
// MacAlgorithmSpecHmacSha384 is a MacAlgorithmSpec enum value
MacAlgorithmSpecHmacSha384 = "HMAC_SHA_384"
// MacAlgorithmSpecHmacSha512 is a MacAlgorithmSpec enum value
MacAlgorithmSpecHmacSha512 = "HMAC_SHA_512"
)
// MacAlgorithmSpec_Values returns all elements of the MacAlgorithmSpec enum
func MacAlgorithmSpec_Values() []string {
return []string{
MacAlgorithmSpecHmacSha224,
MacAlgorithmSpecHmacSha256,
MacAlgorithmSpecHmacSha384,
MacAlgorithmSpecHmacSha512,
}
}
const (
// MessageTypeRaw is a MessageType enum value
MessageTypeRaw = "RAW"
// MessageTypeDigest is a MessageType enum value
MessageTypeDigest = "DIGEST"
)
// MessageType_Values returns all elements of the MessageType enum
func MessageType_Values() []string {
return []string{
MessageTypeRaw,
MessageTypeDigest,
}
}
const (
// MultiRegionKeyTypePrimary is a MultiRegionKeyType enum value
MultiRegionKeyTypePrimary = "PRIMARY"
// MultiRegionKeyTypeReplica is a MultiRegionKeyType enum value
MultiRegionKeyTypeReplica = "REPLICA"
)
// MultiRegionKeyType_Values returns all elements of the MultiRegionKeyType enum
func MultiRegionKeyType_Values() []string {
return []string{
MultiRegionKeyTypePrimary,
MultiRegionKeyTypeReplica,
}
}
const (
// OriginTypeAwsKms is a OriginType enum value
OriginTypeAwsKms = "AWS_KMS"
// OriginTypeExternal is a OriginType enum value
OriginTypeExternal = "EXTERNAL"
// OriginTypeAwsCloudhsm is a OriginType enum value
OriginTypeAwsCloudhsm = "AWS_CLOUDHSM"
)
// OriginType_Values returns all elements of the OriginType enum
func OriginType_Values() []string {
return []string{
OriginTypeAwsKms,
OriginTypeExternal,
OriginTypeAwsCloudhsm,
}
}
const (
// SigningAlgorithmSpecRsassaPssSha256 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPssSha256 = "RSASSA_PSS_SHA_256"
// SigningAlgorithmSpecRsassaPssSha384 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPssSha384 = "RSASSA_PSS_SHA_384"
// SigningAlgorithmSpecRsassaPssSha512 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPssSha512 = "RSASSA_PSS_SHA_512"
// SigningAlgorithmSpecRsassaPkcs1V15Sha256 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPkcs1V15Sha256 = "RSASSA_PKCS1_V1_5_SHA_256"
// SigningAlgorithmSpecRsassaPkcs1V15Sha384 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPkcs1V15Sha384 = "RSASSA_PKCS1_V1_5_SHA_384"
// SigningAlgorithmSpecRsassaPkcs1V15Sha512 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecRsassaPkcs1V15Sha512 = "RSASSA_PKCS1_V1_5_SHA_512"
// SigningAlgorithmSpecEcdsaSha256 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecEcdsaSha256 = "ECDSA_SHA_256"
// SigningAlgorithmSpecEcdsaSha384 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecEcdsaSha384 = "ECDSA_SHA_384"
// SigningAlgorithmSpecEcdsaSha512 is a SigningAlgorithmSpec enum value
SigningAlgorithmSpecEcdsaSha512 = "ECDSA_SHA_512"
)
// SigningAlgorithmSpec_Values returns all elements of the SigningAlgorithmSpec enum
func SigningAlgorithmSpec_Values() []string {
return []string{
SigningAlgorithmSpecRsassaPssSha256,
SigningAlgorithmSpecRsassaPssSha384,
SigningAlgorithmSpecRsassaPssSha512,
SigningAlgorithmSpecRsassaPkcs1V15Sha256,
SigningAlgorithmSpecRsassaPkcs1V15Sha384,
SigningAlgorithmSpecRsassaPkcs1V15Sha512,
SigningAlgorithmSpecEcdsaSha256,
SigningAlgorithmSpecEcdsaSha384,
SigningAlgorithmSpecEcdsaSha512,
}
}
const (
// WrappingKeySpecRsa2048 is a WrappingKeySpec enum value
WrappingKeySpecRsa2048 = "RSA_2048"
)
// WrappingKeySpec_Values returns all elements of the WrappingKeySpec enum
func WrappingKeySpec_Values() []string {
return []string{
WrappingKeySpecRsa2048,
}
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/kms/doc.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package kms provides the client and types for making API
// requests to AWS Key Management Service.
//
// Key Management Service (KMS) is an encryption and key management web service.
// This guide describes the KMS operations that you can call programmatically.
// For general information about KMS, see the Key Management Service Developer
// Guide (https://docs.aws.amazon.com/kms/latest/developerguide/).
//
// KMS is replacing the term customer master key (CMK) with KMS key and KMS
// key. The concept has not changed. To prevent breaking changes, KMS is keeping
// some variations of this term.
//
// Amazon Web Services provides SDKs that consist of libraries and sample code
// for various programming languages and platforms (Java, Ruby, .Net, macOS,
// Android, etc.). The SDKs provide a convenient way to create programmatic
// access to KMS and other Amazon Web Services services. For example, the SDKs
// take care of tasks such as signing requests (see below), managing errors,
// and retrying requests automatically. For more information about the Amazon
// Web Services SDKs, including how to download and install them, see Tools
// for Amazon Web Services (http://aws.amazon.com/tools/).
//
// We recommend that you use the Amazon Web Services SDKs to make programmatic
// API calls to KMS.
//
// If you need to use FIPS 140-2 validated cryptographic modules when communicating
// with Amazon Web Services, use the FIPS endpoint in your preferred Amazon
// Web Services Region. For more information about the available FIPS endpoints,
// see Service endpoints (https://docs.aws.amazon.com/general/latest/gr/kms.html#kms_region)
// in the Key Management Service topic of the Amazon Web Services General Reference.
//
// Clients must support TLS (Transport Layer Security) 1.0. We recommend TLS
// 1.2. Clients must also support cipher suites with Perfect Forward Secrecy
// (PFS) such as Ephemeral Diffie-Hellman (DHE) or Elliptic Curve Ephemeral
// Diffie-Hellman (ECDHE). Most modern systems such as Java 7 and later support
// these modes.
//
// Signing Requests
//
// Requests must be signed by using an access key ID and a secret access key.
// We strongly recommend that you do not use your Amazon Web Services account
// (root) access key ID and secret key for everyday work with KMS. Instead,
// use the access key ID and secret access key for an IAM user. You can also
// use the Amazon Web Services Security Token Service to generate temporary
// security credentials that you can use to sign requests.
//
// All KMS operations require Signature Version 4 (https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).
//
// Logging API Requests
//
// KMS supports CloudTrail, a service that logs Amazon Web Services API calls
// and related events for your Amazon Web Services account and delivers them
// to an Amazon S3 bucket that you specify. By using the information collected
// by CloudTrail, you can determine what requests were made to KMS, who made
// the request, when it was made, and so on. To learn more about CloudTrail,
// including how to turn it on and find your log files, see the CloudTrail User
// Guide (https://docs.aws.amazon.com/awscloudtrail/latest/userguide/).
//
// Additional Resources
//
// For more information about credentials and request signing, see the following:
//
// * Amazon Web Services Security Credentials (https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html)
// - This topic provides general information about the types of credentials
// used to access Amazon Web Services.
//
// * Temporary Security Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html)
// - This section of the IAM User Guide describes how to create and use temporary
// security credentials.
//
// * Signature Version 4 Signing Process (https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)
// - This set of topics walks you through the process of signing a request
// using an access key ID and a secret access key.
//
// Commonly Used API Operations
//
// Of the API operations discussed in this guide, the following will prove the
// most useful for most applications. You will likely perform operations other
// than these, such as creating keys and assigning policies, by using the console.
//
// * Encrypt
//
// * Decrypt
//
// * GenerateDataKey
//
// * GenerateDataKeyWithoutPlaintext
//
// See https://docs.aws.amazon.com/goto/WebAPI/kms-2014-11-01 for more information on this service.
//
// See kms package documentation for more information.
// https://docs.aws.amazon.com/sdk-for-go/api/service/kms/
//
// Using the Client
//
// To contact AWS Key Management Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
// See the SDK's documentation for more information on how to use the SDK.
// https://docs.aws.amazon.com/sdk-for-go/api/
//
// See aws.Config documentation for more information on configuring SDK clients.
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
//
// See the AWS Key Management Service client KMS for more
// information on creating client for this service.
// https://docs.aws.amazon.com/sdk-for-go/api/service/kms/#New
package kms
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/kms/errors.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package kms
import (
"github.com/aws/aws-sdk-go/private/protocol"
)
const (
// ErrCodeAlreadyExistsException for service response error code
// "AlreadyExistsException".
//
// The request was rejected because it attempted to create a resource that already
// exists.
ErrCodeAlreadyExistsException = "AlreadyExistsException"
// ErrCodeCloudHsmClusterInUseException for service response error code
// "CloudHsmClusterInUseException".
//
// The request was rejected because the specified CloudHSM cluster is already
// associated with a custom key store or it shares a backup history with a cluster
// that is associated with a custom key store. Each custom key store must be
// associated with a different CloudHSM cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
ErrCodeCloudHsmClusterInUseException = "CloudHsmClusterInUseException"
// ErrCodeCloudHsmClusterInvalidConfigurationException for service response error code
// "CloudHsmClusterInvalidConfigurationException".
//
// The request was rejected because the associated CloudHSM cluster did not
// meet the configuration requirements for a custom key store.
//
// * The cluster must be configured with private subnets in at least two
// different Availability Zones in the Region.
//
// * The security group for the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// (cloudhsm-cluster--sg) must include inbound rules and outbound
// rules that allow TCP traffic on ports 2223-2225. The Source in the inbound
// rules and the Destination in the outbound rules must match the security
// group ID. These rules are set by default when you create the cluster.
// Do not delete or change them. To get information about a particular security
// group, use the DescribeSecurityGroups (https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
// operation.
//
// * The cluster must contain at least as many HSMs as the operation requires.
// To add HSMs, use the CloudHSM CreateHsm (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_CreateHsm.html)
// operation. For the CreateCustomKeyStore, UpdateCustomKeyStore, and CreateKey
// operations, the CloudHSM cluster must have at least two active HSMs, each
// in a different Availability Zone. For the ConnectCustomKeyStore operation,
// the CloudHSM must contain at least one active HSM.
//
// For information about the requirements for an CloudHSM cluster that is associated
// with a custom key store, see Assemble the Prerequisites (https://docs.aws.amazon.com/kms/latest/developerguide/create-keystore.html#before-keystore)
// in the Key Management Service Developer Guide. For information about creating
// a private subnet for an CloudHSM cluster, see Create a Private Subnet (https://docs.aws.amazon.com/cloudhsm/latest/userguide/create-subnets.html)
// in the CloudHSM User Guide. For information about cluster security groups,
// see Configure a Default Security Group (https://docs.aws.amazon.com/cloudhsm/latest/userguide/configure-sg.html)
// in the CloudHSM User Guide .
ErrCodeCloudHsmClusterInvalidConfigurationException = "CloudHsmClusterInvalidConfigurationException"
// ErrCodeCloudHsmClusterNotActiveException for service response error code
// "CloudHsmClusterNotActiveException".
//
// The request was rejected because the CloudHSM cluster that is associated
// with the custom key store is not active. Initialize and activate the cluster
// and try the command again. For detailed instructions, see Getting Started
// (https://docs.aws.amazon.com/cloudhsm/latest/userguide/getting-started.html)
// in the CloudHSM User Guide.
ErrCodeCloudHsmClusterNotActiveException = "CloudHsmClusterNotActiveException"
// ErrCodeCloudHsmClusterNotFoundException for service response error code
// "CloudHsmClusterNotFoundException".
//
// The request was rejected because KMS cannot find the CloudHSM cluster with
// the specified cluster ID. Retry the request with a different cluster ID.
ErrCodeCloudHsmClusterNotFoundException = "CloudHsmClusterNotFoundException"
// ErrCodeCloudHsmClusterNotRelatedException for service response error code
// "CloudHsmClusterNotRelatedException".
//
// The request was rejected because the specified CloudHSM cluster has a different
// cluster certificate than the original cluster. You cannot use the operation
// to specify an unrelated cluster.
//
// Specify a cluster that shares a backup history with the original cluster.
// This includes clusters that were created from a backup of the current cluster,
// and clusters that were created from the same backup that produced the current
// cluster.
//
// Clusters that share a backup history have the same cluster certificate. To
// view the cluster certificate of a cluster, use the DescribeClusters (https://docs.aws.amazon.com/cloudhsm/latest/APIReference/API_DescribeClusters.html)
// operation.
ErrCodeCloudHsmClusterNotRelatedException = "CloudHsmClusterNotRelatedException"
// ErrCodeCustomKeyStoreHasCMKsException for service response error code
// "CustomKeyStoreHasCMKsException".
//
// The request was rejected because the custom key store contains KMS keys.
// After verifying that you do not need to use the KMS keys, use the ScheduleKeyDeletion
// operation to delete the KMS keys. After they are deleted, you can delete
// the custom key store.
ErrCodeCustomKeyStoreHasCMKsException = "CustomKeyStoreHasCMKsException"
// ErrCodeCustomKeyStoreInvalidStateException for service response error code
// "CustomKeyStoreInvalidStateException".
//
// The request was rejected because of the ConnectionState of the custom key
// store. To get the ConnectionState of a custom key store, use the DescribeCustomKeyStores
// operation.
//
// This exception is thrown under the following conditions:
//
// * You requested the CreateKey or GenerateRandom operation in a custom
// key store that is not connected. These operations are valid only when
// the custom key store ConnectionState is CONNECTED.
//
// * You requested the UpdateCustomKeyStore or DeleteCustomKeyStore operation
// on a custom key store that is not disconnected. This operation is valid
// only when the custom key store ConnectionState is DISCONNECTED.
//
// * You requested the ConnectCustomKeyStore operation on a custom key store
// with a ConnectionState of DISCONNECTING or FAILED. This operation is valid
// for all other ConnectionState values.
ErrCodeCustomKeyStoreInvalidStateException = "CustomKeyStoreInvalidStateException"
// ErrCodeCustomKeyStoreNameInUseException for service response error code
// "CustomKeyStoreNameInUseException".
//
// The request was rejected because the specified custom key store name is already
// assigned to another custom key store in the account. Try again with a custom
// key store name that is unique in the account.
ErrCodeCustomKeyStoreNameInUseException = "CustomKeyStoreNameInUseException"
// ErrCodeCustomKeyStoreNotFoundException for service response error code
// "CustomKeyStoreNotFoundException".
//
// The request was rejected because KMS cannot find a custom key store with
// the specified key store name or ID.
ErrCodeCustomKeyStoreNotFoundException = "CustomKeyStoreNotFoundException"
// ErrCodeDependencyTimeoutException for service response error code
// "DependencyTimeoutException".
//
// The system timed out while trying to fulfill the request. The request can
// be retried.
ErrCodeDependencyTimeoutException = "DependencyTimeoutException"
// ErrCodeDisabledException for service response error code
// "DisabledException".
//
// The request was rejected because the specified KMS key is not enabled.
ErrCodeDisabledException = "DisabledException"
// ErrCodeExpiredImportTokenException for service response error code
// "ExpiredImportTokenException".
//
// The request was rejected because the specified import token is expired. Use
// GetParametersForImport to get a new import token and public key, use the
// new public key to encrypt the key material, and then try the request again.
ErrCodeExpiredImportTokenException = "ExpiredImportTokenException"
// ErrCodeIncorrectKeyException for service response error code
// "IncorrectKeyException".
//
// The request was rejected because the specified KMS key cannot decrypt the
// data. The KeyId in a Decrypt request and the SourceKeyId in a ReEncrypt request
// must identify the same KMS key that was used to encrypt the ciphertext.
ErrCodeIncorrectKeyException = "IncorrectKeyException"
// ErrCodeIncorrectKeyMaterialException for service response error code
// "IncorrectKeyMaterialException".
//
// The request was rejected because the key material in the request is, expired,
// invalid, or is not the same key material that was previously imported into
// this KMS key.
ErrCodeIncorrectKeyMaterialException = "IncorrectKeyMaterialException"
// ErrCodeIncorrectTrustAnchorException for service response error code
// "IncorrectTrustAnchorException".
//
// The request was rejected because the trust anchor certificate in the request
// is not the trust anchor certificate for the specified CloudHSM cluster.
//
// When you initialize the cluster (https://docs.aws.amazon.com/cloudhsm/latest/userguide/initialize-cluster.html#sign-csr),
// you create the trust anchor certificate and save it in the customerCA.crt
// file.
ErrCodeIncorrectTrustAnchorException = "IncorrectTrustAnchorException"
// ErrCodeInternalException for service response error code
// "KMSInternalException".
//
// The request was rejected because an internal exception occurred. The request
// can be retried.
ErrCodeInternalException = "KMSInternalException"
// ErrCodeInvalidAliasNameException for service response error code
// "InvalidAliasNameException".
//
// The request was rejected because the specified alias name is not valid.
ErrCodeInvalidAliasNameException = "InvalidAliasNameException"
// ErrCodeInvalidArnException for service response error code
// "InvalidArnException".
//
// The request was rejected because a specified ARN, or an ARN in a key policy,
// is not valid.
ErrCodeInvalidArnException = "InvalidArnException"
// ErrCodeInvalidCiphertextException for service response error code
// "InvalidCiphertextException".
//
// From the Decrypt or ReEncrypt operation, the request was rejected because
// the specified ciphertext, or additional authenticated data incorporated into
// the ciphertext, such as the encryption context, is corrupted, missing, or
// otherwise invalid.
//
// From the ImportKeyMaterial operation, the request was rejected because KMS
// could not decrypt the encrypted (wrapped) key material.
ErrCodeInvalidCiphertextException = "InvalidCiphertextException"
// ErrCodeInvalidGrantIdException for service response error code
// "InvalidGrantIdException".
//
// The request was rejected because the specified GrantId is not valid.
ErrCodeInvalidGrantIdException = "InvalidGrantIdException"
// ErrCodeInvalidGrantTokenException for service response error code
// "InvalidGrantTokenException".
//
// The request was rejected because the specified grant token is not valid.
ErrCodeInvalidGrantTokenException = "InvalidGrantTokenException"
// ErrCodeInvalidImportTokenException for service response error code
// "InvalidImportTokenException".
//
// The request was rejected because the provided import token is invalid or
// is associated with a different KMS key.
ErrCodeInvalidImportTokenException = "InvalidImportTokenException"
// ErrCodeInvalidKeyUsageException for service response error code
// "InvalidKeyUsageException".
//
// The request was rejected for one of the following reasons:
//
// * The KeyUsage value of the KMS key is incompatible with the API operation.
//
// * The encryption algorithm or signing algorithm specified for the operation
// is incompatible with the type of key material in the KMS key (KeySpec).
//
// For encrypting, decrypting, re-encrypting, and generating data keys, the
// KeyUsage must be ENCRYPT_DECRYPT. For signing and verifying messages, the
// KeyUsage must be SIGN_VERIFY. For generating and verifying message authentication
// codes (MACs), the KeyUsage must be GENERATE_VERIFY_MAC. To find the KeyUsage
// of a KMS key, use the DescribeKey operation.
//
// To find the encryption or signing algorithms supported for a particular KMS
// key, use the DescribeKey operation.
ErrCodeInvalidKeyUsageException = "InvalidKeyUsageException"
// ErrCodeInvalidMarkerException for service response error code
// "InvalidMarkerException".
//
// The request was rejected because the marker that specifies where pagination
// should next begin is not valid.
ErrCodeInvalidMarkerException = "InvalidMarkerException"
// ErrCodeInvalidStateException for service response error code
// "KMSInvalidStateException".
//
// The request was rejected because the state of the specified resource is not
// valid for this request.
//
// For more information about how key state affects the use of a KMS key, see
// Key states of KMS keys (https://docs.aws.amazon.com/kms/latest/developerguide/key-state.html)
// in the Key Management Service Developer Guide .
ErrCodeInvalidStateException = "KMSInvalidStateException"
// ErrCodeKMSInvalidMacException for service response error code
// "KMSInvalidMacException".
//
// The request was rejected because the HMAC verification failed. HMAC verification
// fails when the HMAC computed by using the specified message, HMAC KMS key,
// and MAC algorithm does not match the HMAC specified in the request.
ErrCodeKMSInvalidMacException = "KMSInvalidMacException"
// ErrCodeKMSInvalidSignatureException for service response error code
// "KMSInvalidSignatureException".
//
// The request was rejected because the signature verification failed. Signature
// verification fails when it cannot confirm that signature was produced by
// signing the specified message with the specified KMS key and signing algorithm.
ErrCodeKMSInvalidSignatureException = "KMSInvalidSignatureException"
// ErrCodeKeyUnavailableException for service response error code
// "KeyUnavailableException".
//
// The request was rejected because the specified KMS key was not available.
// You can retry the request.
ErrCodeKeyUnavailableException = "KeyUnavailableException"
// ErrCodeLimitExceededException for service response error code
// "LimitExceededException".
//
// The request was rejected because a quota was exceeded. For more information,
// see Quotas (https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)
// in the Key Management Service Developer Guide.
ErrCodeLimitExceededException = "LimitExceededException"
// ErrCodeMalformedPolicyDocumentException for service response error code
// "MalformedPolicyDocumentException".
//
// The request was rejected because the specified policy is not syntactically
// or semantically correct.
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocumentException"
// ErrCodeNotFoundException for service response error code
// "NotFoundException".
//
// The request was rejected because the specified entity or resource could not
// be found.
ErrCodeNotFoundException = "NotFoundException"
// ErrCodeTagException for service response error code
// "TagException".
//
// The request was rejected because one or more tags are not valid.
ErrCodeTagException = "TagException"
// ErrCodeUnsupportedOperationException for service response error code
// "UnsupportedOperationException".
//
// The request was rejected because a specified parameter is not supported or
// a specified resource is not valid for this operation.
ErrCodeUnsupportedOperationException = "UnsupportedOperationException"
)
var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{
"AlreadyExistsException": newErrorAlreadyExistsException,
"CloudHsmClusterInUseException": newErrorCloudHsmClusterInUseException,
"CloudHsmClusterInvalidConfigurationException": newErrorCloudHsmClusterInvalidConfigurationException,
"CloudHsmClusterNotActiveException": newErrorCloudHsmClusterNotActiveException,
"CloudHsmClusterNotFoundException": newErrorCloudHsmClusterNotFoundException,
"CloudHsmClusterNotRelatedException": newErrorCloudHsmClusterNotRelatedException,
"CustomKeyStoreHasCMKsException": newErrorCustomKeyStoreHasCMKsException,
"CustomKeyStoreInvalidStateException": newErrorCustomKeyStoreInvalidStateException,
"CustomKeyStoreNameInUseException": newErrorCustomKeyStoreNameInUseException,
"CustomKeyStoreNotFoundException": newErrorCustomKeyStoreNotFoundException,
"DependencyTimeoutException": newErrorDependencyTimeoutException,
"DisabledException": newErrorDisabledException,
"ExpiredImportTokenException": newErrorExpiredImportTokenException,
"IncorrectKeyException": newErrorIncorrectKeyException,
"IncorrectKeyMaterialException": newErrorIncorrectKeyMaterialException,
"IncorrectTrustAnchorException": newErrorIncorrectTrustAnchorException,
"KMSInternalException": newErrorInternalException,
"InvalidAliasNameException": newErrorInvalidAliasNameException,
"InvalidArnException": newErrorInvalidArnException,
"InvalidCiphertextException": newErrorInvalidCiphertextException,
"InvalidGrantIdException": newErrorInvalidGrantIdException,
"InvalidGrantTokenException": newErrorInvalidGrantTokenException,
"InvalidImportTokenException": newErrorInvalidImportTokenException,
"InvalidKeyUsageException": newErrorInvalidKeyUsageException,
"InvalidMarkerException": newErrorInvalidMarkerException,
"KMSInvalidStateException": newErrorInvalidStateException,
"KMSInvalidMacException": newErrorKMSInvalidMacException,
"KMSInvalidSignatureException": newErrorKMSInvalidSignatureException,
"KeyUnavailableException": newErrorKeyUnavailableException,
"LimitExceededException": newErrorLimitExceededException,
"MalformedPolicyDocumentException": newErrorMalformedPolicyDocumentException,
"NotFoundException": newErrorNotFoundException,
"TagException": newErrorTagException,
"UnsupportedOperationException": newErrorUnsupportedOperationException,
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/kms/kmsiface/interface.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package kmsiface provides an interface to enable mocking the AWS Key Management Service service client
// for testing your code.
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters.
package kmsiface
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/kms"
)
// KMSAPI provides an interface to enable mocking the
// kms.KMS service client's API operation,
// paginators, and waiters. This make unit testing your code that calls out
// to the SDK's service client's calls easier.
//
// The best way to use this interface is so the SDK's service client's calls
// can be stubbed out for unit testing your code with the SDK without needing
// to inject custom request handlers into the SDK's request pipeline.
//
// // myFunc uses an SDK service client to make a request to
// // AWS Key Management Service.
// func myFunc(svc kmsiface.KMSAPI) bool {
// // Make svc.CancelKeyDeletion request
// }
//
// func main() {
// sess := session.New()
// svc := kms.New(sess)
//
// myFunc(svc)
// }
//
// In your _test.go file:
//
// // Define a mock struct to be used in your unit tests of myFunc.
// type mockKMSClient struct {
// kmsiface.KMSAPI
// }
// func (m *mockKMSClient) CancelKeyDeletion(input *kms.CancelKeyDeletionInput) (*kms.CancelKeyDeletionOutput, error) {
// // mock response/functionality
// }
//
// func TestMyFunc(t *testing.T) {
// // Setup Test
// mockSvc := &mockKMSClient{}
//
// myfunc(mockSvc)
//
// // Verify myFunc's functionality
// }
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters. Its suggested to use the pattern above for testing, or using
// tooling to generate mocks to satisfy the interfaces.
type KMSAPI interface {
CancelKeyDeletion(*kms.CancelKeyDeletionInput) (*kms.CancelKeyDeletionOutput, error)
CancelKeyDeletionWithContext(aws.Context, *kms.CancelKeyDeletionInput, ...request.Option) (*kms.CancelKeyDeletionOutput, error)
CancelKeyDeletionRequest(*kms.CancelKeyDeletionInput) (*request.Request, *kms.CancelKeyDeletionOutput)
ConnectCustomKeyStore(*kms.ConnectCustomKeyStoreInput) (*kms.ConnectCustomKeyStoreOutput, error)
ConnectCustomKeyStoreWithContext(aws.Context, *kms.ConnectCustomKeyStoreInput, ...request.Option) (*kms.ConnectCustomKeyStoreOutput, error)
ConnectCustomKeyStoreRequest(*kms.ConnectCustomKeyStoreInput) (*request.Request, *kms.ConnectCustomKeyStoreOutput)
CreateAlias(*kms.CreateAliasInput) (*kms.CreateAliasOutput, error)
CreateAliasWithContext(aws.Context, *kms.CreateAliasInput, ...request.Option) (*kms.CreateAliasOutput, error)
CreateAliasRequest(*kms.CreateAliasInput) (*request.Request, *kms.CreateAliasOutput)
CreateCustomKeyStore(*kms.CreateCustomKeyStoreInput) (*kms.CreateCustomKeyStoreOutput, error)
CreateCustomKeyStoreWithContext(aws.Context, *kms.CreateCustomKeyStoreInput, ...request.Option) (*kms.CreateCustomKeyStoreOutput, error)
CreateCustomKeyStoreRequest(*kms.CreateCustomKeyStoreInput) (*request.Request, *kms.CreateCustomKeyStoreOutput)
CreateGrant(*kms.CreateGrantInput) (*kms.CreateGrantOutput, error)
CreateGrantWithContext(aws.Context, *kms.CreateGrantInput, ...request.Option) (*kms.CreateGrantOutput, error)
CreateGrantRequest(*kms.CreateGrantInput) (*request.Request, *kms.CreateGrantOutput)
CreateKey(*kms.CreateKeyInput) (*kms.CreateKeyOutput, error)
CreateKeyWithContext(aws.Context, *kms.CreateKeyInput, ...request.Option) (*kms.CreateKeyOutput, error)
CreateKeyRequest(*kms.CreateKeyInput) (*request.Request, *kms.CreateKeyOutput)
Decrypt(*kms.DecryptInput) (*kms.DecryptOutput, error)
DecryptWithContext(aws.Context, *kms.DecryptInput, ...request.Option) (*kms.DecryptOutput, error)
DecryptRequest(*kms.DecryptInput) (*request.Request, *kms.DecryptOutput)
DeleteAlias(*kms.DeleteAliasInput) (*kms.DeleteAliasOutput, error)
DeleteAliasWithContext(aws.Context, *kms.DeleteAliasInput, ...request.Option) (*kms.DeleteAliasOutput, error)
DeleteAliasRequest(*kms.DeleteAliasInput) (*request.Request, *kms.DeleteAliasOutput)
DeleteCustomKeyStore(*kms.DeleteCustomKeyStoreInput) (*kms.DeleteCustomKeyStoreOutput, error)
DeleteCustomKeyStoreWithContext(aws.Context, *kms.DeleteCustomKeyStoreInput, ...request.Option) (*kms.DeleteCustomKeyStoreOutput, error)
DeleteCustomKeyStoreRequest(*kms.DeleteCustomKeyStoreInput) (*request.Request, *kms.DeleteCustomKeyStoreOutput)
DeleteImportedKeyMaterial(*kms.DeleteImportedKeyMaterialInput) (*kms.DeleteImportedKeyMaterialOutput, error)
DeleteImportedKeyMaterialWithContext(aws.Context, *kms.DeleteImportedKeyMaterialInput, ...request.Option) (*kms.DeleteImportedKeyMaterialOutput, error)
DeleteImportedKeyMaterialRequest(*kms.DeleteImportedKeyMaterialInput) (*request.Request, *kms.DeleteImportedKeyMaterialOutput)
DescribeCustomKeyStores(*kms.DescribeCustomKeyStoresInput) (*kms.DescribeCustomKeyStoresOutput, error)
DescribeCustomKeyStoresWithContext(aws.Context, *kms.DescribeCustomKeyStoresInput, ...request.Option) (*kms.DescribeCustomKeyStoresOutput, error)
DescribeCustomKeyStoresRequest(*kms.DescribeCustomKeyStoresInput) (*request.Request, *kms.DescribeCustomKeyStoresOutput)
DescribeKey(*kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error)
DescribeKeyWithContext(aws.Context, *kms.DescribeKeyInput, ...request.Option) (*kms.DescribeKeyOutput, error)
DescribeKeyRequest(*kms.DescribeKeyInput) (*request.Request, *kms.DescribeKeyOutput)
DisableKey(*kms.DisableKeyInput) (*kms.DisableKeyOutput, error)
DisableKeyWithContext(aws.Context, *kms.DisableKeyInput, ...request.Option) (*kms.DisableKeyOutput, error)
DisableKeyRequest(*kms.DisableKeyInput) (*request.Request, *kms.DisableKeyOutput)
DisableKeyRotation(*kms.DisableKeyRotationInput) (*kms.DisableKeyRotationOutput, error)
DisableKeyRotationWithContext(aws.Context, *kms.DisableKeyRotationInput, ...request.Option) (*kms.DisableKeyRotationOutput, error)
DisableKeyRotationRequest(*kms.DisableKeyRotationInput) (*request.Request, *kms.DisableKeyRotationOutput)
DisconnectCustomKeyStore(*kms.DisconnectCustomKeyStoreInput) (*kms.DisconnectCustomKeyStoreOutput, error)
DisconnectCustomKeyStoreWithContext(aws.Context, *kms.DisconnectCustomKeyStoreInput, ...request.Option) (*kms.DisconnectCustomKeyStoreOutput, error)
DisconnectCustomKeyStoreRequest(*kms.DisconnectCustomKeyStoreInput) (*request.Request, *kms.DisconnectCustomKeyStoreOutput)
EnableKey(*kms.EnableKeyInput) (*kms.EnableKeyOutput, error)
EnableKeyWithContext(aws.Context, *kms.EnableKeyInput, ...request.Option) (*kms.EnableKeyOutput, error)
EnableKeyRequest(*kms.EnableKeyInput) (*request.Request, *kms.EnableKeyOutput)
EnableKeyRotation(*kms.EnableKeyRotationInput) (*kms.EnableKeyRotationOutput, error)
EnableKeyRotationWithContext(aws.Context, *kms.EnableKeyRotationInput, ...request.Option) (*kms.EnableKeyRotationOutput, error)
EnableKeyRotationRequest(*kms.EnableKeyRotationInput) (*request.Request, *kms.EnableKeyRotationOutput)
Encrypt(*kms.EncryptInput) (*kms.EncryptOutput, error)
EncryptWithContext(aws.Context, *kms.EncryptInput, ...request.Option) (*kms.EncryptOutput, error)
EncryptRequest(*kms.EncryptInput) (*request.Request, *kms.EncryptOutput)
GenerateDataKey(*kms.GenerateDataKeyInput) (*kms.GenerateDataKeyOutput, error)
GenerateDataKeyWithContext(aws.Context, *kms.GenerateDataKeyInput, ...request.Option) (*kms.GenerateDataKeyOutput, error)
GenerateDataKeyRequest(*kms.GenerateDataKeyInput) (*request.Request, *kms.GenerateDataKeyOutput)
GenerateDataKeyPair(*kms.GenerateDataKeyPairInput) (*kms.GenerateDataKeyPairOutput, error)
GenerateDataKeyPairWithContext(aws.Context, *kms.GenerateDataKeyPairInput, ...request.Option) (*kms.GenerateDataKeyPairOutput, error)
GenerateDataKeyPairRequest(*kms.GenerateDataKeyPairInput) (*request.Request, *kms.GenerateDataKeyPairOutput)
GenerateDataKeyPairWithoutPlaintext(*kms.GenerateDataKeyPairWithoutPlaintextInput) (*kms.GenerateDataKeyPairWithoutPlaintextOutput, error)
GenerateDataKeyPairWithoutPlaintextWithContext(aws.Context, *kms.GenerateDataKeyPairWithoutPlaintextInput, ...request.Option) (*kms.GenerateDataKeyPairWithoutPlaintextOutput, error)
GenerateDataKeyPairWithoutPlaintextRequest(*kms.GenerateDataKeyPairWithoutPlaintextInput) (*request.Request, *kms.GenerateDataKeyPairWithoutPlaintextOutput)
GenerateDataKeyWithoutPlaintext(*kms.GenerateDataKeyWithoutPlaintextInput) (*kms.GenerateDataKeyWithoutPlaintextOutput, error)
GenerateDataKeyWithoutPlaintextWithContext(aws.Context, *kms.GenerateDataKeyWithoutPlaintextInput, ...request.Option) (*kms.GenerateDataKeyWithoutPlaintextOutput, error)
GenerateDataKeyWithoutPlaintextRequest(*kms.GenerateDataKeyWithoutPlaintextInput) (*request.Request, *kms.GenerateDataKeyWithoutPlaintextOutput)
GenerateMac(*kms.GenerateMacInput) (*kms.GenerateMacOutput, error)
GenerateMacWithContext(aws.Context, *kms.GenerateMacInput, ...request.Option) (*kms.GenerateMacOutput, error)
GenerateMacRequest(*kms.GenerateMacInput) (*request.Request, *kms.GenerateMacOutput)
GenerateRandom(*kms.GenerateRandomInput) (*kms.GenerateRandomOutput, error)
GenerateRandomWithContext(aws.Context, *kms.GenerateRandomInput, ...request.Option) (*kms.GenerateRandomOutput, error)
GenerateRandomRequest(*kms.GenerateRandomInput) (*request.Request, *kms.GenerateRandomOutput)
GetKeyPolicy(*kms.GetKeyPolicyInput) (*kms.GetKeyPolicyOutput, error)
GetKeyPolicyWithContext(aws.Context, *kms.GetKeyPolicyInput, ...request.Option) (*kms.GetKeyPolicyOutput, error)
GetKeyPolicyRequest(*kms.GetKeyPolicyInput) (*request.Request, *kms.GetKeyPolicyOutput)
GetKeyRotationStatus(*kms.GetKeyRotationStatusInput) (*kms.GetKeyRotationStatusOutput, error)
GetKeyRotationStatusWithContext(aws.Context, *kms.GetKeyRotationStatusInput, ...request.Option) (*kms.GetKeyRotationStatusOutput, error)
GetKeyRotationStatusRequest(*kms.GetKeyRotationStatusInput) (*request.Request, *kms.GetKeyRotationStatusOutput)
GetParametersForImport(*kms.GetParametersForImportInput) (*kms.GetParametersForImportOutput, error)
GetParametersForImportWithContext(aws.Context, *kms.GetParametersForImportInput, ...request.Option) (*kms.GetParametersForImportOutput, error)
GetParametersForImportRequest(*kms.GetParametersForImportInput) (*request.Request, *kms.GetParametersForImportOutput)
GetPublicKey(*kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error)
GetPublicKeyWithContext(aws.Context, *kms.GetPublicKeyInput, ...request.Option) (*kms.GetPublicKeyOutput, error)
GetPublicKeyRequest(*kms.GetPublicKeyInput) (*request.Request, *kms.GetPublicKeyOutput)
ImportKeyMaterial(*kms.ImportKeyMaterialInput) (*kms.ImportKeyMaterialOutput, error)
ImportKeyMaterialWithContext(aws.Context, *kms.ImportKeyMaterialInput, ...request.Option) (*kms.ImportKeyMaterialOutput, error)
ImportKeyMaterialRequest(*kms.ImportKeyMaterialInput) (*request.Request, *kms.ImportKeyMaterialOutput)
ListAliases(*kms.ListAliasesInput) (*kms.ListAliasesOutput, error)
ListAliasesWithContext(aws.Context, *kms.ListAliasesInput, ...request.Option) (*kms.ListAliasesOutput, error)
ListAliasesRequest(*kms.ListAliasesInput) (*request.Request, *kms.ListAliasesOutput)
ListAliasesPages(*kms.ListAliasesInput, func(*kms.ListAliasesOutput, bool) bool) error
ListAliasesPagesWithContext(aws.Context, *kms.ListAliasesInput, func(*kms.ListAliasesOutput, bool) bool, ...request.Option) error
ListGrants(*kms.ListGrantsInput) (*kms.ListGrantsResponse, error)
ListGrantsWithContext(aws.Context, *kms.ListGrantsInput, ...request.Option) (*kms.ListGrantsResponse, error)
ListGrantsRequest(*kms.ListGrantsInput) (*request.Request, *kms.ListGrantsResponse)
ListGrantsPages(*kms.ListGrantsInput, func(*kms.ListGrantsResponse, bool) bool) error
ListGrantsPagesWithContext(aws.Context, *kms.ListGrantsInput, func(*kms.ListGrantsResponse, bool) bool, ...request.Option) error
ListKeyPolicies(*kms.ListKeyPoliciesInput) (*kms.ListKeyPoliciesOutput, error)
ListKeyPoliciesWithContext(aws.Context, *kms.ListKeyPoliciesInput, ...request.Option) (*kms.ListKeyPoliciesOutput, error)
ListKeyPoliciesRequest(*kms.ListKeyPoliciesInput) (*request.Request, *kms.ListKeyPoliciesOutput)
ListKeyPoliciesPages(*kms.ListKeyPoliciesInput, func(*kms.ListKeyPoliciesOutput, bool) bool) error
ListKeyPoliciesPagesWithContext(aws.Context, *kms.ListKeyPoliciesInput, func(*kms.ListKeyPoliciesOutput, bool) bool, ...request.Option) error
ListKeys(*kms.ListKeysInput) (*kms.ListKeysOutput, error)
ListKeysWithContext(aws.Context, *kms.ListKeysInput, ...request.Option) (*kms.ListKeysOutput, error)
ListKeysRequest(*kms.ListKeysInput) (*request.Request, *kms.ListKeysOutput)
ListKeysPages(*kms.ListKeysInput, func(*kms.ListKeysOutput, bool) bool) error
ListKeysPagesWithContext(aws.Context, *kms.ListKeysInput, func(*kms.ListKeysOutput, bool) bool, ...request.Option) error
ListResourceTags(*kms.ListResourceTagsInput) (*kms.ListResourceTagsOutput, error)
ListResourceTagsWithContext(aws.Context, *kms.ListResourceTagsInput, ...request.Option) (*kms.ListResourceTagsOutput, error)
ListResourceTagsRequest(*kms.ListResourceTagsInput) (*request.Request, *kms.ListResourceTagsOutput)
ListRetirableGrants(*kms.ListRetirableGrantsInput) (*kms.ListGrantsResponse, error)
ListRetirableGrantsWithContext(aws.Context, *kms.ListRetirableGrantsInput, ...request.Option) (*kms.ListGrantsResponse, error)
ListRetirableGrantsRequest(*kms.ListRetirableGrantsInput) (*request.Request, *kms.ListGrantsResponse)
PutKeyPolicy(*kms.PutKeyPolicyInput) (*kms.PutKeyPolicyOutput, error)
PutKeyPolicyWithContext(aws.Context, *kms.PutKeyPolicyInput, ...request.Option) (*kms.PutKeyPolicyOutput, error)
PutKeyPolicyRequest(*kms.PutKeyPolicyInput) (*request.Request, *kms.PutKeyPolicyOutput)
ReEncrypt(*kms.ReEncryptInput) (*kms.ReEncryptOutput, error)
ReEncryptWithContext(aws.Context, *kms.ReEncryptInput, ...request.Option) (*kms.ReEncryptOutput, error)
ReEncryptRequest(*kms.ReEncryptInput) (*request.Request, *kms.ReEncryptOutput)
ReplicateKey(*kms.ReplicateKeyInput) (*kms.ReplicateKeyOutput, error)
ReplicateKeyWithContext(aws.Context, *kms.ReplicateKeyInput, ...request.Option) (*kms.ReplicateKeyOutput, error)
ReplicateKeyRequest(*kms.ReplicateKeyInput) (*request.Request, *kms.ReplicateKeyOutput)
RetireGrant(*kms.RetireGrantInput) (*kms.RetireGrantOutput, error)
RetireGrantWithContext(aws.Context, *kms.RetireGrantInput, ...request.Option) (*kms.RetireGrantOutput, error)
RetireGrantRequest(*kms.RetireGrantInput) (*request.Request, *kms.RetireGrantOutput)
RevokeGrant(*kms.RevokeGrantInput) (*kms.RevokeGrantOutput, error)
RevokeGrantWithContext(aws.Context, *kms.RevokeGrantInput, ...request.Option) (*kms.RevokeGrantOutput, error)
RevokeGrantRequest(*kms.RevokeGrantInput) (*request.Request, *kms.RevokeGrantOutput)
ScheduleKeyDeletion(*kms.ScheduleKeyDeletionInput) (*kms.ScheduleKeyDeletionOutput, error)
ScheduleKeyDeletionWithContext(aws.Context, *kms.ScheduleKeyDeletionInput, ...request.Option) (*kms.ScheduleKeyDeletionOutput, error)
ScheduleKeyDeletionRequest(*kms.ScheduleKeyDeletionInput) (*request.Request, *kms.ScheduleKeyDeletionOutput)
Sign(*kms.SignInput) (*kms.SignOutput, error)
SignWithContext(aws.Context, *kms.SignInput, ...request.Option) (*kms.SignOutput, error)
SignRequest(*kms.SignInput) (*request.Request, *kms.SignOutput)
TagResource(*kms.TagResourceInput) (*kms.TagResourceOutput, error)
TagResourceWithContext(aws.Context, *kms.TagResourceInput, ...request.Option) (*kms.TagResourceOutput, error)
TagResourceRequest(*kms.TagResourceInput) (*request.Request, *kms.TagResourceOutput)
UntagResource(*kms.UntagResourceInput) (*kms.UntagResourceOutput, error)
UntagResourceWithContext(aws.Context, *kms.UntagResourceInput, ...request.Option) (*kms.UntagResourceOutput, error)
UntagResourceRequest(*kms.UntagResourceInput) (*request.Request, *kms.UntagResourceOutput)
UpdateAlias(*kms.UpdateAliasInput) (*kms.UpdateAliasOutput, error)
UpdateAliasWithContext(aws.Context, *kms.UpdateAliasInput, ...request.Option) (*kms.UpdateAliasOutput, error)
UpdateAliasRequest(*kms.UpdateAliasInput) (*request.Request, *kms.UpdateAliasOutput)
UpdateCustomKeyStore(*kms.UpdateCustomKeyStoreInput) (*kms.UpdateCustomKeyStoreOutput, error)
UpdateCustomKeyStoreWithContext(aws.Context, *kms.UpdateCustomKeyStoreInput, ...request.Option) (*kms.UpdateCustomKeyStoreOutput, error)
UpdateCustomKeyStoreRequest(*kms.UpdateCustomKeyStoreInput) (*request.Request, *kms.UpdateCustomKeyStoreOutput)
UpdateKeyDescription(*kms.UpdateKeyDescriptionInput) (*kms.UpdateKeyDescriptionOutput, error)
UpdateKeyDescriptionWithContext(aws.Context, *kms.UpdateKeyDescriptionInput, ...request.Option) (*kms.UpdateKeyDescriptionOutput, error)
UpdateKeyDescriptionRequest(*kms.UpdateKeyDescriptionInput) (*request.Request, *kms.UpdateKeyDescriptionOutput)
UpdatePrimaryRegion(*kms.UpdatePrimaryRegionInput) (*kms.UpdatePrimaryRegionOutput, error)
UpdatePrimaryRegionWithContext(aws.Context, *kms.UpdatePrimaryRegionInput, ...request.Option) (*kms.UpdatePrimaryRegionOutput, error)
UpdatePrimaryRegionRequest(*kms.UpdatePrimaryRegionInput) (*request.Request, *kms.UpdatePrimaryRegionOutput)
Verify(*kms.VerifyInput) (*kms.VerifyOutput, error)
VerifyWithContext(aws.Context, *kms.VerifyInput, ...request.Option) (*kms.VerifyOutput, error)
VerifyRequest(*kms.VerifyInput) (*request.Request, *kms.VerifyOutput)
VerifyMac(*kms.VerifyMacInput) (*kms.VerifyMacOutput, error)
VerifyMacWithContext(aws.Context, *kms.VerifyMacInput, ...request.Option) (*kms.VerifyMacOutput, error)
VerifyMacRequest(*kms.VerifyMacInput) (*request.Request, *kms.VerifyMacOutput)
}
var _ KMSAPI = (*kms.KMS)(nil)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/kms/service.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package kms
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/jsonrpc"
)
// KMS provides the API operation methods for making requests to
// AWS Key Management Service. See this package's package overview docs
// for details on the service.
//
// KMS methods are safe to use concurrently. It is not safe to
// modify mutate any of the struct's properties though.
type KMS struct {
*client.Client
}
// Used for custom client initialization logic
var initClient func(*client.Client)
// Used for custom request initialization logic
var initRequest func(*request.Request)
// Service information constants
const (
ServiceName = "kms" // Name of service.
EndpointsID = ServiceName // ID to lookup a service endpoint with.
ServiceID = "KMS" // ServiceID is a unique identifier of a specific service.
)
// New creates a new instance of the KMS client with a session.
// If additional configuration is needed for the client instance use the optional
// aws.Config parameter to add your extra config.
//
// Example:
// mySession := session.Must(session.NewSession())
//
// // Create a KMS client from just a session.
// svc := kms.New(mySession)
//
// // Create a KMS client with additional configuration
// svc := kms.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *KMS {
c := p.ClientConfig(EndpointsID, cfgs...)
if c.SigningNameDerived || len(c.SigningName) == 0 {
c.SigningName = EndpointsID
// No Fallback
}
return newClient(*c.Config, c.Handlers, c.PartitionID, c.Endpoint, c.SigningRegion, c.SigningName, c.ResolvedRegion)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, partitionID, endpoint, signingRegion, signingName, resolvedRegion string) *KMS {
svc := &KMS{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceID,
SigningName: signingName,
SigningRegion: signingRegion,
PartitionID: partitionID,
Endpoint: endpoint,
APIVersion: "2014-11-01",
ResolvedRegion: resolvedRegion,
JSONVersion: "1.1",
TargetPrefix: "TrentService",
},
handlers,
),
}
// Handlers
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
svc.Handlers.Build.PushBackNamed(jsonrpc.BuildHandler)
svc.Handlers.Unmarshal.PushBackNamed(jsonrpc.UnmarshalHandler)
svc.Handlers.UnmarshalMeta.PushBackNamed(jsonrpc.UnmarshalMetaHandler)
svc.Handlers.UnmarshalError.PushBackNamed(
protocol.NewUnmarshalErrorHandler(jsonrpc.NewUnmarshalTypedError(exceptionFromCode)).NamedHandler(),
)
// Run custom client initialization if present
if initClient != nil {
initClient(svc.Client)
}
return svc
}
// newRequest creates a new request for a KMS operation and runs any
// custom request initialization.
func (c *KMS) newRequest(op *request.Operation, params, data interface{}) *request.Request {
req := c.NewRequest(op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sso/api.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sso
import (
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/restjson"
)
const opGetRoleCredentials = "GetRoleCredentials"
// GetRoleCredentialsRequest generates a "aws/request.Request" representing the
// client's request for the GetRoleCredentials operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetRoleCredentials for more information on using the GetRoleCredentials
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetRoleCredentialsRequest method.
// req, resp := client.GetRoleCredentialsRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/GetRoleCredentials
func (c *SSO) GetRoleCredentialsRequest(input *GetRoleCredentialsInput) (req *request.Request, output *GetRoleCredentialsOutput) {
op := &request.Operation{
Name: opGetRoleCredentials,
HTTPMethod: "GET",
HTTPPath: "/federation/credentials",
}
if input == nil {
input = &GetRoleCredentialsInput{}
}
output = &GetRoleCredentialsOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
return
}
// GetRoleCredentials API operation for AWS Single Sign-On.
//
// Returns the STS short-term credentials for a given role name that is assigned
// to the user.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Single Sign-On's
// API operation GetRoleCredentials for usage and error information.
//
// Returned Error Types:
// * InvalidRequestException
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
//
// * UnauthorizedException
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
//
// * TooManyRequestsException
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
//
// * ResourceNotFoundException
// The specified resource doesn't exist.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/GetRoleCredentials
func (c *SSO) GetRoleCredentials(input *GetRoleCredentialsInput) (*GetRoleCredentialsOutput, error) {
req, out := c.GetRoleCredentialsRequest(input)
return out, req.Send()
}
// GetRoleCredentialsWithContext is the same as GetRoleCredentials with the addition of
// the ability to pass a context and additional request options.
//
// See GetRoleCredentials for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) GetRoleCredentialsWithContext(ctx aws.Context, input *GetRoleCredentialsInput, opts ...request.Option) (*GetRoleCredentialsOutput, error) {
req, out := c.GetRoleCredentialsRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opListAccountRoles = "ListAccountRoles"
// ListAccountRolesRequest generates a "aws/request.Request" representing the
// client's request for the ListAccountRoles operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListAccountRoles for more information on using the ListAccountRoles
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListAccountRolesRequest method.
// req, resp := client.ListAccountRolesRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/ListAccountRoles
func (c *SSO) ListAccountRolesRequest(input *ListAccountRolesInput) (req *request.Request, output *ListAccountRolesOutput) {
op := &request.Operation{
Name: opListAccountRoles,
HTTPMethod: "GET",
HTTPPath: "/assignment/roles",
Paginator: &request.Paginator{
InputTokens: []string{"nextToken"},
OutputTokens: []string{"nextToken"},
LimitToken: "maxResults",
TruncationToken: "",
},
}
if input == nil {
input = &ListAccountRolesInput{}
}
output = &ListAccountRolesOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
return
}
// ListAccountRoles API operation for AWS Single Sign-On.
//
// Lists all roles that are assigned to the user for a given AWS account.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Single Sign-On's
// API operation ListAccountRoles for usage and error information.
//
// Returned Error Types:
// * InvalidRequestException
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
//
// * UnauthorizedException
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
//
// * TooManyRequestsException
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
//
// * ResourceNotFoundException
// The specified resource doesn't exist.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/ListAccountRoles
func (c *SSO) ListAccountRoles(input *ListAccountRolesInput) (*ListAccountRolesOutput, error) {
req, out := c.ListAccountRolesRequest(input)
return out, req.Send()
}
// ListAccountRolesWithContext is the same as ListAccountRoles with the addition of
// the ability to pass a context and additional request options.
//
// See ListAccountRoles for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) ListAccountRolesWithContext(ctx aws.Context, input *ListAccountRolesInput, opts ...request.Option) (*ListAccountRolesOutput, error) {
req, out := c.ListAccountRolesRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListAccountRolesPages iterates over the pages of a ListAccountRoles operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListAccountRoles method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListAccountRoles operation.
// pageNum := 0
// err := client.ListAccountRolesPages(params,
// func(page *sso.ListAccountRolesOutput, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *SSO) ListAccountRolesPages(input *ListAccountRolesInput, fn func(*ListAccountRolesOutput, bool) bool) error {
return c.ListAccountRolesPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListAccountRolesPagesWithContext same as ListAccountRolesPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) ListAccountRolesPagesWithContext(ctx aws.Context, input *ListAccountRolesInput, fn func(*ListAccountRolesOutput, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListAccountRolesInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListAccountRolesRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListAccountRolesOutput), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opListAccounts = "ListAccounts"
// ListAccountsRequest generates a "aws/request.Request" representing the
// client's request for the ListAccounts operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See ListAccounts for more information on using the ListAccounts
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the ListAccountsRequest method.
// req, resp := client.ListAccountsRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/ListAccounts
func (c *SSO) ListAccountsRequest(input *ListAccountsInput) (req *request.Request, output *ListAccountsOutput) {
op := &request.Operation{
Name: opListAccounts,
HTTPMethod: "GET",
HTTPPath: "/assignment/accounts",
Paginator: &request.Paginator{
InputTokens: []string{"nextToken"},
OutputTokens: []string{"nextToken"},
LimitToken: "maxResults",
TruncationToken: "",
},
}
if input == nil {
input = &ListAccountsInput{}
}
output = &ListAccountsOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
return
}
// ListAccounts API operation for AWS Single Sign-On.
//
// Lists all AWS accounts assigned to the user. These AWS accounts are assigned
// by the administrator of the account. For more information, see Assign User
// Access (https://docs.aws.amazon.com/singlesignon/latest/userguide/useraccess.html#assignusers)
// in the AWS SSO User Guide. This operation returns a paginated response.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Single Sign-On's
// API operation ListAccounts for usage and error information.
//
// Returned Error Types:
// * InvalidRequestException
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
//
// * UnauthorizedException
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
//
// * TooManyRequestsException
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
//
// * ResourceNotFoundException
// The specified resource doesn't exist.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/ListAccounts
func (c *SSO) ListAccounts(input *ListAccountsInput) (*ListAccountsOutput, error) {
req, out := c.ListAccountsRequest(input)
return out, req.Send()
}
// ListAccountsWithContext is the same as ListAccounts with the addition of
// the ability to pass a context and additional request options.
//
// See ListAccounts for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) ListAccountsWithContext(ctx aws.Context, input *ListAccountsInput, opts ...request.Option) (*ListAccountsOutput, error) {
req, out := c.ListAccountsRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// ListAccountsPages iterates over the pages of a ListAccounts operation,
// calling the "fn" function with the response data for each page. To stop
// iterating, return false from the fn function.
//
// See ListAccounts method for more information on how to use this operation.
//
// Note: This operation can generate multiple requests to a service.
//
// // Example iterating over at most 3 pages of a ListAccounts operation.
// pageNum := 0
// err := client.ListAccountsPages(params,
// func(page *sso.ListAccountsOutput, lastPage bool) bool {
// pageNum++
// fmt.Println(page)
// return pageNum <= 3
// })
//
func (c *SSO) ListAccountsPages(input *ListAccountsInput, fn func(*ListAccountsOutput, bool) bool) error {
return c.ListAccountsPagesWithContext(aws.BackgroundContext(), input, fn)
}
// ListAccountsPagesWithContext same as ListAccountsPages except
// it takes a Context and allows setting request options on the pages.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) ListAccountsPagesWithContext(ctx aws.Context, input *ListAccountsInput, fn func(*ListAccountsOutput, bool) bool, opts ...request.Option) error {
p := request.Pagination{
NewRequest: func() (*request.Request, error) {
var inCpy *ListAccountsInput
if input != nil {
tmp := *input
inCpy = &tmp
}
req, _ := c.ListAccountsRequest(inCpy)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return req, nil
},
}
for p.Next() {
if !fn(p.Page().(*ListAccountsOutput), !p.HasNextPage()) {
break
}
}
return p.Err()
}
const opLogout = "Logout"
// LogoutRequest generates a "aws/request.Request" representing the
// client's request for the Logout operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See Logout for more information on using the Logout
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the LogoutRequest method.
// req, resp := client.LogoutRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/Logout
func (c *SSO) LogoutRequest(input *LogoutInput) (req *request.Request, output *LogoutOutput) {
op := &request.Operation{
Name: opLogout,
HTTPMethod: "POST",
HTTPPath: "/logout",
}
if input == nil {
input = &LogoutInput{}
}
output = &LogoutOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
req.Handlers.Unmarshal.Swap(restjson.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler)
return
}
// Logout API operation for AWS Single Sign-On.
//
// Removes the client- and server-side session that is associated with the user.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Single Sign-On's
// API operation Logout for usage and error information.
//
// Returned Error Types:
// * InvalidRequestException
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
//
// * UnauthorizedException
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
//
// * TooManyRequestsException
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10/Logout
func (c *SSO) Logout(input *LogoutInput) (*LogoutOutput, error) {
req, out := c.LogoutRequest(input)
return out, req.Send()
}
// LogoutWithContext is the same as Logout with the addition of
// the ability to pass a context and additional request options.
//
// See Logout for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *SSO) LogoutWithContext(ctx aws.Context, input *LogoutInput, opts ...request.Option) (*LogoutOutput, error) {
req, out := c.LogoutRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
// Provides information about your AWS account.
type AccountInfo struct {
_ struct{} `type:"structure"`
// The identifier of the AWS account that is assigned to the user.
AccountId *string `locationName:"accountId" type:"string"`
// The display name of the AWS account that is assigned to the user.
AccountName *string `locationName:"accountName" type:"string"`
// The email address of the AWS account that is assigned to the user.
EmailAddress *string `locationName:"emailAddress" min:"1" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AccountInfo) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AccountInfo) GoString() string {
return s.String()
}
// SetAccountId sets the AccountId field's value.
func (s *AccountInfo) SetAccountId(v string) *AccountInfo {
s.AccountId = &v
return s
}
// SetAccountName sets the AccountName field's value.
func (s *AccountInfo) SetAccountName(v string) *AccountInfo {
s.AccountName = &v
return s
}
// SetEmailAddress sets the EmailAddress field's value.
func (s *AccountInfo) SetEmailAddress(v string) *AccountInfo {
s.EmailAddress = &v
return s
}
type GetRoleCredentialsInput struct {
_ struct{} `type:"structure" nopayload:"true"`
// The token issued by the CreateToken API call. For more information, see CreateToken
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by GetRoleCredentialsInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
// The identifier for the AWS account that is assigned to the user.
//
// AccountId is a required field
AccountId *string `location:"querystring" locationName:"account_id" type:"string" required:"true"`
// The friendly name of the role that is assigned to the user.
//
// RoleName is a required field
RoleName *string `location:"querystring" locationName:"role_name" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetRoleCredentialsInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetRoleCredentialsInput"}
if s.AccessToken == nil {
invalidParams.Add(request.NewErrParamRequired("AccessToken"))
}
if s.AccountId == nil {
invalidParams.Add(request.NewErrParamRequired("AccountId"))
}
if s.RoleName == nil {
invalidParams.Add(request.NewErrParamRequired("RoleName"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAccessToken sets the AccessToken field's value.
func (s *GetRoleCredentialsInput) SetAccessToken(v string) *GetRoleCredentialsInput {
s.AccessToken = &v
return s
}
// SetAccountId sets the AccountId field's value.
func (s *GetRoleCredentialsInput) SetAccountId(v string) *GetRoleCredentialsInput {
s.AccountId = &v
return s
}
// SetRoleName sets the RoleName field's value.
func (s *GetRoleCredentialsInput) SetRoleName(v string) *GetRoleCredentialsInput {
s.RoleName = &v
return s
}
type GetRoleCredentialsOutput struct {
_ struct{} `type:"structure"`
// The credentials for the role that is assigned to the user.
RoleCredentials *RoleCredentials `locationName:"roleCredentials" type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetRoleCredentialsOutput) GoString() string {
return s.String()
}
// SetRoleCredentials sets the RoleCredentials field's value.
func (s *GetRoleCredentialsOutput) SetRoleCredentials(v *RoleCredentials) *GetRoleCredentialsOutput {
s.RoleCredentials = v
return s
}
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
type InvalidRequestException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidRequestException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s InvalidRequestException) GoString() string {
return s.String()
}
func newErrorInvalidRequestException(v protocol.ResponseMetadata) error {
return &InvalidRequestException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *InvalidRequestException) Code() string {
return "InvalidRequestException"
}
// Message returns the exception's message.
func (s *InvalidRequestException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *InvalidRequestException) OrigErr() error {
return nil
}
func (s *InvalidRequestException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *InvalidRequestException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *InvalidRequestException) RequestID() string {
return s.RespMetadata.RequestID
}
type ListAccountRolesInput struct {
_ struct{} `type:"structure" nopayload:"true"`
// The token issued by the CreateToken API call. For more information, see CreateToken
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by ListAccountRolesInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
// The identifier for the AWS account that is assigned to the user.
//
// AccountId is a required field
AccountId *string `location:"querystring" locationName:"account_id" type:"string" required:"true"`
// The number of items that clients can request per page.
MaxResults *int64 `location:"querystring" locationName:"max_result" min:"1" type:"integer"`
// The page token from the previous response output when you request subsequent
// pages.
NextToken *string `location:"querystring" locationName:"next_token" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListAccountRolesInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListAccountRolesInput"}
if s.AccessToken == nil {
invalidParams.Add(request.NewErrParamRequired("AccessToken"))
}
if s.AccountId == nil {
invalidParams.Add(request.NewErrParamRequired("AccountId"))
}
if s.MaxResults != nil && *s.MaxResults < 1 {
invalidParams.Add(request.NewErrParamMinValue("MaxResults", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAccessToken sets the AccessToken field's value.
func (s *ListAccountRolesInput) SetAccessToken(v string) *ListAccountRolesInput {
s.AccessToken = &v
return s
}
// SetAccountId sets the AccountId field's value.
func (s *ListAccountRolesInput) SetAccountId(v string) *ListAccountRolesInput {
s.AccountId = &v
return s
}
// SetMaxResults sets the MaxResults field's value.
func (s *ListAccountRolesInput) SetMaxResults(v int64) *ListAccountRolesInput {
s.MaxResults = &v
return s
}
// SetNextToken sets the NextToken field's value.
func (s *ListAccountRolesInput) SetNextToken(v string) *ListAccountRolesInput {
s.NextToken = &v
return s
}
type ListAccountRolesOutput struct {
_ struct{} `type:"structure"`
// The page token client that is used to retrieve the list of accounts.
NextToken *string `locationName:"nextToken" type:"string"`
// A paginated response with the list of roles and the next token if more results
// are available.
RoleList []*RoleInfo `locationName:"roleList" type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountRolesOutput) GoString() string {
return s.String()
}
// SetNextToken sets the NextToken field's value.
func (s *ListAccountRolesOutput) SetNextToken(v string) *ListAccountRolesOutput {
s.NextToken = &v
return s
}
// SetRoleList sets the RoleList field's value.
func (s *ListAccountRolesOutput) SetRoleList(v []*RoleInfo) *ListAccountRolesOutput {
s.RoleList = v
return s
}
type ListAccountsInput struct {
_ struct{} `type:"structure" nopayload:"true"`
// The token issued by the CreateToken API call. For more information, see CreateToken
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by ListAccountsInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
// This is the number of items clients can request per page.
MaxResults *int64 `location:"querystring" locationName:"max_result" min:"1" type:"integer"`
// (Optional) When requesting subsequent pages, this is the page token from
// the previous response output.
NextToken *string `location:"querystring" locationName:"next_token" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *ListAccountsInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "ListAccountsInput"}
if s.AccessToken == nil {
invalidParams.Add(request.NewErrParamRequired("AccessToken"))
}
if s.MaxResults != nil && *s.MaxResults < 1 {
invalidParams.Add(request.NewErrParamMinValue("MaxResults", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAccessToken sets the AccessToken field's value.
func (s *ListAccountsInput) SetAccessToken(v string) *ListAccountsInput {
s.AccessToken = &v
return s
}
// SetMaxResults sets the MaxResults field's value.
func (s *ListAccountsInput) SetMaxResults(v int64) *ListAccountsInput {
s.MaxResults = &v
return s
}
// SetNextToken sets the NextToken field's value.
func (s *ListAccountsInput) SetNextToken(v string) *ListAccountsInput {
s.NextToken = &v
return s
}
type ListAccountsOutput struct {
_ struct{} `type:"structure"`
// A paginated response with the list of account information and the next token
// if more results are available.
AccountList []*AccountInfo `locationName:"accountList" type:"list"`
// The page token client that is used to retrieve the list of accounts.
NextToken *string `locationName:"nextToken" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ListAccountsOutput) GoString() string {
return s.String()
}
// SetAccountList sets the AccountList field's value.
func (s *ListAccountsOutput) SetAccountList(v []*AccountInfo) *ListAccountsOutput {
s.AccountList = v
return s
}
// SetNextToken sets the NextToken field's value.
func (s *ListAccountsOutput) SetNextToken(v string) *ListAccountsOutput {
s.NextToken = &v
return s
}
type LogoutInput struct {
_ struct{} `type:"structure" nopayload:"true"`
// The token issued by the CreateToken API call. For more information, see CreateToken
// (https://docs.aws.amazon.com/singlesignon/latest/OIDCAPIReference/API_CreateToken.html)
// in the AWS SSO OIDC API Reference Guide.
//
// AccessToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by LogoutInput's
// String and GoString methods.
//
// AccessToken is a required field
AccessToken *string `location:"header" locationName:"x-amz-sso_bearer_token" type:"string" required:"true" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *LogoutInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "LogoutInput"}
if s.AccessToken == nil {
invalidParams.Add(request.NewErrParamRequired("AccessToken"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAccessToken sets the AccessToken field's value.
func (s *LogoutInput) SetAccessToken(v string) *LogoutInput {
s.AccessToken = &v
return s
}
type LogoutOutput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s LogoutOutput) GoString() string {
return s.String()
}
// The specified resource doesn't exist.
type ResourceNotFoundException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ResourceNotFoundException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s ResourceNotFoundException) GoString() string {
return s.String()
}
func newErrorResourceNotFoundException(v protocol.ResponseMetadata) error {
return &ResourceNotFoundException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *ResourceNotFoundException) Code() string {
return "ResourceNotFoundException"
}
// Message returns the exception's message.
func (s *ResourceNotFoundException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *ResourceNotFoundException) OrigErr() error {
return nil
}
func (s *ResourceNotFoundException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *ResourceNotFoundException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *ResourceNotFoundException) RequestID() string {
return s.RespMetadata.RequestID
}
// Provides information about the role credentials that are assigned to the
// user.
type RoleCredentials struct {
_ struct{} `type:"structure"`
// The identifier used for the temporary security credentials. For more information,
// see Using Temporary Security Credentials to Request Access to AWS Resources
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
// in the AWS IAM User Guide.
AccessKeyId *string `locationName:"accessKeyId" type:"string"`
// The date on which temporary security credentials expire.
Expiration *int64 `locationName:"expiration" type:"long"`
// The key that is used to sign the request. For more information, see Using
// Temporary Security Credentials to Request Access to AWS Resources (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
// in the AWS IAM User Guide.
//
// SecretAccessKey is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by RoleCredentials's
// String and GoString methods.
SecretAccessKey *string `locationName:"secretAccessKey" type:"string" sensitive:"true"`
// The token used for temporary credentials. For more information, see Using
// Temporary Security Credentials to Request Access to AWS Resources (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html)
// in the AWS IAM User Guide.
//
// SessionToken is a sensitive parameter and its value will be
// replaced with "sensitive" in string returned by RoleCredentials's
// String and GoString methods.
SessionToken *string `locationName:"sessionToken" type:"string" sensitive:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleCredentials) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleCredentials) GoString() string {
return s.String()
}
// SetAccessKeyId sets the AccessKeyId field's value.
func (s *RoleCredentials) SetAccessKeyId(v string) *RoleCredentials {
s.AccessKeyId = &v
return s
}
// SetExpiration sets the Expiration field's value.
func (s *RoleCredentials) SetExpiration(v int64) *RoleCredentials {
s.Expiration = &v
return s
}
// SetSecretAccessKey sets the SecretAccessKey field's value.
func (s *RoleCredentials) SetSecretAccessKey(v string) *RoleCredentials {
s.SecretAccessKey = &v
return s
}
// SetSessionToken sets the SessionToken field's value.
func (s *RoleCredentials) SetSessionToken(v string) *RoleCredentials {
s.SessionToken = &v
return s
}
// Provides information about the role that is assigned to the user.
type RoleInfo struct {
_ struct{} `type:"structure"`
// The identifier of the AWS account assigned to the user.
AccountId *string `locationName:"accountId" type:"string"`
// The friendly name of the role that is assigned to the user.
RoleName *string `locationName:"roleName" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleInfo) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s RoleInfo) GoString() string {
return s.String()
}
// SetAccountId sets the AccountId field's value.
func (s *RoleInfo) SetAccountId(v string) *RoleInfo {
s.AccountId = &v
return s
}
// SetRoleName sets the RoleName field's value.
func (s *RoleInfo) SetRoleName(v string) *RoleInfo {
s.RoleName = &v
return s
}
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
type TooManyRequestsException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TooManyRequestsException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s TooManyRequestsException) GoString() string {
return s.String()
}
func newErrorTooManyRequestsException(v protocol.ResponseMetadata) error {
return &TooManyRequestsException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *TooManyRequestsException) Code() string {
return "TooManyRequestsException"
}
// Message returns the exception's message.
func (s *TooManyRequestsException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *TooManyRequestsException) OrigErr() error {
return nil
}
func (s *TooManyRequestsException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *TooManyRequestsException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *TooManyRequestsException) RequestID() string {
return s.RespMetadata.RequestID
}
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
type UnauthorizedException struct {
_ struct{} `type:"structure"`
RespMetadata protocol.ResponseMetadata `json:"-" xml:"-"`
Message_ *string `locationName:"message" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnauthorizedException) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s UnauthorizedException) GoString() string {
return s.String()
}
func newErrorUnauthorizedException(v protocol.ResponseMetadata) error {
return &UnauthorizedException{
RespMetadata: v,
}
}
// Code returns the exception type name.
func (s *UnauthorizedException) Code() string {
return "UnauthorizedException"
}
// Message returns the exception's message.
func (s *UnauthorizedException) Message() string {
if s.Message_ != nil {
return *s.Message_
}
return ""
}
// OrigErr always returns nil, satisfies awserr.Error interface.
func (s *UnauthorizedException) OrigErr() error {
return nil
}
func (s *UnauthorizedException) Error() string {
return fmt.Sprintf("%s: %s", s.Code(), s.Message())
}
// Status code returns the HTTP status code for the request's response error.
func (s *UnauthorizedException) StatusCode() int {
return s.RespMetadata.StatusCode
}
// RequestID returns the service's response RequestID for request.
func (s *UnauthorizedException) RequestID() string {
return s.RespMetadata.RequestID
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sso/doc.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package sso provides the client and types for making API
// requests to AWS Single Sign-On.
//
// AWS Single Sign-On Portal is a web service that makes it easy for you to
// assign user access to AWS SSO resources such as the user portal. Users can
// get AWS account applications and roles assigned to them and get federated
// into the application.
//
// For general information about AWS SSO, see What is AWS Single Sign-On? (https://docs.aws.amazon.com/singlesignon/latest/userguide/what-is.html)
// in the AWS SSO User Guide.
//
// This API reference guide describes the AWS SSO Portal operations that you
// can call programatically and includes detailed information on data types
// and errors.
//
// AWS provides SDKs that consist of libraries and sample code for various programming
// languages and platforms, such as Java, Ruby, .Net, iOS, or Android. The SDKs
// provide a convenient way to create programmatic access to AWS SSO and other
// AWS services. For more information about the AWS SDKs, including how to download
// and install them, see Tools for Amazon Web Services (http://aws.amazon.com/tools/).
//
// See https://docs.aws.amazon.com/goto/WebAPI/sso-2019-06-10 for more information on this service.
//
// See sso package documentation for more information.
// https://docs.aws.amazon.com/sdk-for-go/api/service/sso/
//
// Using the Client
//
// To contact AWS Single Sign-On with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
// See the SDK's documentation for more information on how to use the SDK.
// https://docs.aws.amazon.com/sdk-for-go/api/
//
// See aws.Config documentation for more information on configuring SDK clients.
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
//
// See the AWS Single Sign-On client SSO for more
// information on creating client for this service.
// https://docs.aws.amazon.com/sdk-for-go/api/service/sso/#New
package sso
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sso/errors.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sso
import (
"github.com/aws/aws-sdk-go/private/protocol"
)
const (
// ErrCodeInvalidRequestException for service response error code
// "InvalidRequestException".
//
// Indicates that a problem occurred with the input to the request. For example,
// a required parameter might be missing or out of range.
ErrCodeInvalidRequestException = "InvalidRequestException"
// ErrCodeResourceNotFoundException for service response error code
// "ResourceNotFoundException".
//
// The specified resource doesn't exist.
ErrCodeResourceNotFoundException = "ResourceNotFoundException"
// ErrCodeTooManyRequestsException for service response error code
// "TooManyRequestsException".
//
// Indicates that the request is being made too frequently and is more than
// what the server can handle.
ErrCodeTooManyRequestsException = "TooManyRequestsException"
// ErrCodeUnauthorizedException for service response error code
// "UnauthorizedException".
//
// Indicates that the request is not authorized. This can happen due to an invalid
// access token in the request.
ErrCodeUnauthorizedException = "UnauthorizedException"
)
var exceptionFromCode = map[string]func(protocol.ResponseMetadata) error{
"InvalidRequestException": newErrorInvalidRequestException,
"ResourceNotFoundException": newErrorResourceNotFoundException,
"TooManyRequestsException": newErrorTooManyRequestsException,
"UnauthorizedException": newErrorUnauthorizedException,
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sso/service.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sso
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol"
"github.com/aws/aws-sdk-go/private/protocol/restjson"
)
// SSO provides the API operation methods for making requests to
// AWS Single Sign-On. See this package's package overview docs
// for details on the service.
//
// SSO methods are safe to use concurrently. It is not safe to
// modify mutate any of the struct's properties though.
type SSO struct {
*client.Client
}
// Used for custom client initialization logic
var initClient func(*client.Client)
// Used for custom request initialization logic
var initRequest func(*request.Request)
// Service information constants
const (
ServiceName = "SSO" // Name of service.
EndpointsID = "portal.sso" // ID to lookup a service endpoint with.
ServiceID = "SSO" // ServiceID is a unique identifier of a specific service.
)
// New creates a new instance of the SSO client with a session.
// If additional configuration is needed for the client instance use the optional
// aws.Config parameter to add your extra config.
//
// Example:
// mySession := session.Must(session.NewSession())
//
// // Create a SSO client from just a session.
// svc := sso.New(mySession)
//
// // Create a SSO client with additional configuration
// svc := sso.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *SSO {
c := p.ClientConfig(EndpointsID, cfgs...)
if c.SigningNameDerived || len(c.SigningName) == 0 {
c.SigningName = "awsssoportal"
}
return newClient(*c.Config, c.Handlers, c.PartitionID, c.Endpoint, c.SigningRegion, c.SigningName, c.ResolvedRegion)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, partitionID, endpoint, signingRegion, signingName, resolvedRegion string) *SSO {
svc := &SSO{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceID,
SigningName: signingName,
SigningRegion: signingRegion,
PartitionID: partitionID,
Endpoint: endpoint,
APIVersion: "2019-06-10",
ResolvedRegion: resolvedRegion,
},
handlers,
),
}
// Handlers
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
svc.Handlers.Build.PushBackNamed(restjson.BuildHandler)
svc.Handlers.Unmarshal.PushBackNamed(restjson.UnmarshalHandler)
svc.Handlers.UnmarshalMeta.PushBackNamed(restjson.UnmarshalMetaHandler)
svc.Handlers.UnmarshalError.PushBackNamed(
protocol.NewUnmarshalErrorHandler(restjson.NewUnmarshalTypedError(exceptionFromCode)).NamedHandler(),
)
// Run custom client initialization if present
if initClient != nil {
initClient(svc.Client)
}
return svc
}
// newRequest creates a new request for a SSO operation and runs any
// custom request initialization.
func (c *SSO) newRequest(op *request.Operation, params, data interface{}) *request.Request {
req := c.NewRequest(op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sso/ssoiface/interface.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package ssoiface provides an interface to enable mocking the AWS Single Sign-On service client
// for testing your code.
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters.
package ssoiface
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/sso"
)
// SSOAPI provides an interface to enable mocking the
// sso.SSO service client's API operation,
// paginators, and waiters. This make unit testing your code that calls out
// to the SDK's service client's calls easier.
//
// The best way to use this interface is so the SDK's service client's calls
// can be stubbed out for unit testing your code with the SDK without needing
// to inject custom request handlers into the SDK's request pipeline.
//
// // myFunc uses an SDK service client to make a request to
// // AWS Single Sign-On.
// func myFunc(svc ssoiface.SSOAPI) bool {
// // Make svc.GetRoleCredentials request
// }
//
// func main() {
// sess := session.New()
// svc := sso.New(sess)
//
// myFunc(svc)
// }
//
// In your _test.go file:
//
// // Define a mock struct to be used in your unit tests of myFunc.
// type mockSSOClient struct {
// ssoiface.SSOAPI
// }
// func (m *mockSSOClient) GetRoleCredentials(input *sso.GetRoleCredentialsInput) (*sso.GetRoleCredentialsOutput, error) {
// // mock response/functionality
// }
//
// func TestMyFunc(t *testing.T) {
// // Setup Test
// mockSvc := &mockSSOClient{}
//
// myfunc(mockSvc)
//
// // Verify myFunc's functionality
// }
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters. Its suggested to use the pattern above for testing, or using
// tooling to generate mocks to satisfy the interfaces.
type SSOAPI interface {
GetRoleCredentials(*sso.GetRoleCredentialsInput) (*sso.GetRoleCredentialsOutput, error)
GetRoleCredentialsWithContext(aws.Context, *sso.GetRoleCredentialsInput, ...request.Option) (*sso.GetRoleCredentialsOutput, error)
GetRoleCredentialsRequest(*sso.GetRoleCredentialsInput) (*request.Request, *sso.GetRoleCredentialsOutput)
ListAccountRoles(*sso.ListAccountRolesInput) (*sso.ListAccountRolesOutput, error)
ListAccountRolesWithContext(aws.Context, *sso.ListAccountRolesInput, ...request.Option) (*sso.ListAccountRolesOutput, error)
ListAccountRolesRequest(*sso.ListAccountRolesInput) (*request.Request, *sso.ListAccountRolesOutput)
ListAccountRolesPages(*sso.ListAccountRolesInput, func(*sso.ListAccountRolesOutput, bool) bool) error
ListAccountRolesPagesWithContext(aws.Context, *sso.ListAccountRolesInput, func(*sso.ListAccountRolesOutput, bool) bool, ...request.Option) error
ListAccounts(*sso.ListAccountsInput) (*sso.ListAccountsOutput, error)
ListAccountsWithContext(aws.Context, *sso.ListAccountsInput, ...request.Option) (*sso.ListAccountsOutput, error)
ListAccountsRequest(*sso.ListAccountsInput) (*request.Request, *sso.ListAccountsOutput)
ListAccountsPages(*sso.ListAccountsInput, func(*sso.ListAccountsOutput, bool) bool) error
ListAccountsPagesWithContext(aws.Context, *sso.ListAccountsInput, func(*sso.ListAccountsOutput, bool) bool, ...request.Option) error
Logout(*sso.LogoutInput) (*sso.LogoutOutput, error)
LogoutWithContext(aws.Context, *sso.LogoutInput, ...request.Option) (*sso.LogoutOutput, error)
LogoutRequest(*sso.LogoutInput) (*request.Request, *sso.LogoutOutput)
}
var _ SSOAPI = (*sso.SSO)(nil)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/api.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sts
import (
"fmt"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/request"
)
const opAssumeRole = "AssumeRole"
// AssumeRoleRequest generates a "aws/request.Request" representing the
// client's request for the AssumeRole operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See AssumeRole for more information on using the AssumeRole
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the AssumeRoleRequest method.
// req, resp := client.AssumeRoleRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole
func (c *STS) AssumeRoleRequest(input *AssumeRoleInput) (req *request.Request, output *AssumeRoleOutput) {
op := &request.Operation{
Name: opAssumeRole,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &AssumeRoleInput{}
}
output = &AssumeRoleOutput{}
req = c.newRequest(op, input, output)
return
}
// AssumeRole API operation for AWS Security Token Service.
//
// Returns a set of temporary security credentials that you can use to access
// Amazon Web Services resources that you might not normally have access to.
// These temporary credentials consist of an access key ID, a secret access
// key, and a security token. Typically, you use AssumeRole within your account
// or for cross-account access. For a comparison of AssumeRole with other API
// operations that produce temporary credentials, see Requesting Temporary Security
// Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
// and Comparing the Amazon Web Services STS API operations (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison)
// in the IAM User Guide.
//
// Permissions
//
// The temporary security credentials created by AssumeRole can be used to make
// API calls to any Amazon Web Services service with the following exception:
// You cannot call the Amazon Web Services STS GetFederationToken or GetSessionToken
// API operations.
//
// (Optional) You can pass inline or managed session policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies. The plaintext that you use for both inline
// and managed session policies can't exceed 2,048 characters. Passing policies
// to this operation returns new temporary credentials. The resulting session's
// permissions are the intersection of the role's identity-based policy and
// the session policies. You can use the role's temporary credentials in subsequent
// Amazon Web Services API calls to access resources in the account that owns
// the role. You cannot use session policies to grant more permissions than
// those allowed by the identity-based policy of the role that is being assumed.
// For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// When you create a role, you create two policies: A role trust policy that
// specifies who can assume the role and a permissions policy that specifies
// what can be done with the role. You specify the trusted principal who is
// allowed to assume the role in the role trust policy.
//
// To assume a role from a different account, your Amazon Web Services account
// must be trusted by the role. The trust relationship is defined in the role's
// trust policy when the role is created. That trust policy states which accounts
// are allowed to delegate that access to users in the account.
//
// A user who wants to access a role in a different account must also have permissions
// that are delegated from the user account administrator. The administrator
// must attach a policy that allows the user to call AssumeRole for the ARN
// of the role in the other account.
//
// To allow a user to assume a role in the same account, you can do either of
// the following:
//
// * Attach a policy to the user that allows the user to call AssumeRole
// (as long as the role's trust policy trusts the account).
//
// * Add the user as a principal directly in the role's trust policy.
//
// You can do either because the role’s trust policy acts as an IAM resource-based
// policy. When a resource-based policy grants access to a principal in the
// same account, no additional identity-based policy is required. For more information
// about trust policies and resource-based policies, see IAM Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)
// in the IAM User Guide.
//
// Tags
//
// (Optional) You can pass tag key-value pairs to your session. These tags are
// called session tags. For more information about session tags, see Passing
// Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// An administrator must grant you the permissions necessary to pass session
// tags. The administrator can also create granular permissions to allow you
// to pass only specific session tags. For more information, see Tutorial: Using
// Tags for Attribute-Based Access Control (https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)
// in the IAM User Guide.
//
// You can set the session tags as transitive. Transitive tags persist during
// role chaining. For more information, see Chaining Roles with Session Tags
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining)
// in the IAM User Guide.
//
// Using MFA with AssumeRole
//
// (Optional) You can include multi-factor authentication (MFA) information
// when you call AssumeRole. This is useful for cross-account scenarios to ensure
// that the user that assumes the role has been authenticated with an Amazon
// Web Services MFA device. In that scenario, the trust policy of the role being
// assumed includes a condition that tests for MFA authentication. If the caller
// does not include valid MFA information, the request to assume the role is
// denied. The condition in a trust policy that tests for MFA authentication
// might look like the following example.
//
// "Condition": {"Bool": {"aws:MultiFactorAuthPresent": true}}
//
// For more information, see Configuring MFA-Protected API Access (https://docs.aws.amazon.com/IAM/latest/UserGuide/MFAProtectedAPI.html)
// in the IAM User Guide guide.
//
// To use MFA with AssumeRole, you pass values for the SerialNumber and TokenCode
// parameters. The SerialNumber value identifies the user's hardware or virtual
// MFA device. The TokenCode is the time-based one-time password (TOTP) that
// the MFA device produces.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation AssumeRole for usage and error information.
//
// Returned Error Codes:
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
//
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
// The request was rejected because the total packed size of the session policies
// and session tags combined was too large. An Amazon Web Services conversion
// compresses the session policy document, session policy ARNs, and session
// tags into a packed binary format that has a separate limit. The error message
// indicates by percentage how close the policies and tags are to the upper
// size limit. For more information, see Passing Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You could receive this error even though you meet other defined session policy
// and session tag limits. For more information, see IAM and STS Entity Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// * ErrCodeRegionDisabledException "RegionDisabledException"
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
//
// * ErrCodeExpiredTokenException "ExpiredTokenException"
// The web identity token that was passed is expired or is not valid. Get a
// new identity token from the identity provider and then retry the request.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRole
func (c *STS) AssumeRole(input *AssumeRoleInput) (*AssumeRoleOutput, error) {
req, out := c.AssumeRoleRequest(input)
return out, req.Send()
}
// AssumeRoleWithContext is the same as AssumeRole with the addition of
// the ability to pass a context and additional request options.
//
// See AssumeRole for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) AssumeRoleWithContext(ctx aws.Context, input *AssumeRoleInput, opts ...request.Option) (*AssumeRoleOutput, error) {
req, out := c.AssumeRoleRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opAssumeRoleWithSAML = "AssumeRoleWithSAML"
// AssumeRoleWithSAMLRequest generates a "aws/request.Request" representing the
// client's request for the AssumeRoleWithSAML operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See AssumeRoleWithSAML for more information on using the AssumeRoleWithSAML
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the AssumeRoleWithSAMLRequest method.
// req, resp := client.AssumeRoleWithSAMLRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML
func (c *STS) AssumeRoleWithSAMLRequest(input *AssumeRoleWithSAMLInput) (req *request.Request, output *AssumeRoleWithSAMLOutput) {
op := &request.Operation{
Name: opAssumeRoleWithSAML,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &AssumeRoleWithSAMLInput{}
}
output = &AssumeRoleWithSAMLOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
return
}
// AssumeRoleWithSAML API operation for AWS Security Token Service.
//
// Returns a set of temporary security credentials for users who have been authenticated
// via a SAML authentication response. This operation provides a mechanism for
// tying an enterprise identity store or directory to role-based Amazon Web
// Services access without user-specific credentials or configuration. For a
// comparison of AssumeRoleWithSAML with the other API operations that produce
// temporary credentials, see Requesting Temporary Security Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
// and Comparing the Amazon Web Services STS API operations (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison)
// in the IAM User Guide.
//
// The temporary security credentials returned by this operation consist of
// an access key ID, a secret access key, and a security token. Applications
// can use these temporary security credentials to sign calls to Amazon Web
// Services services.
//
// Session Duration
//
// By default, the temporary security credentials created by AssumeRoleWithSAML
// last for one hour. However, you can use the optional DurationSeconds parameter
// to specify the duration of your session. Your role session lasts for the
// duration that you specify, or until the time specified in the SAML authentication
// response's SessionNotOnOrAfter value, whichever is shorter. You can provide
// a DurationSeconds value from 900 seconds (15 minutes) up to the maximum session
// duration setting for the role. This setting can have a value from 1 hour
// to 12 hours. To learn how to view the maximum value for your role, see View
// the Maximum Session Duration Setting for a Role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session)
// in the IAM User Guide. The maximum session duration limit applies when you
// use the AssumeRole* API operations or the assume-role* CLI commands. However
// the limit does not apply when you use those operations to create a console
// URL. For more information, see Using IAM Roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html)
// in the IAM User Guide.
//
// Role chaining (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-role-chaining)
// limits your CLI or Amazon Web Services API role session to a maximum of one
// hour. When you use the AssumeRole API operation to assume a role, you can
// specify the duration of your role session with the DurationSeconds parameter.
// You can specify a parameter value of up to 43200 seconds (12 hours), depending
// on the maximum session duration setting for your role. However, if you assume
// a role using role chaining and provide a DurationSeconds parameter value
// greater than one hour, the operation fails.
//
// Permissions
//
// The temporary security credentials created by AssumeRoleWithSAML can be used
// to make API calls to any Amazon Web Services service with the following exception:
// you cannot call the STS GetFederationToken or GetSessionToken API operations.
//
// (Optional) You can pass inline or managed session policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies. The plaintext that you use for both inline
// and managed session policies can't exceed 2,048 characters. Passing policies
// to this operation returns new temporary credentials. The resulting session's
// permissions are the intersection of the role's identity-based policy and
// the session policies. You can use the role's temporary credentials in subsequent
// Amazon Web Services API calls to access resources in the account that owns
// the role. You cannot use session policies to grant more permissions than
// those allowed by the identity-based policy of the role that is being assumed.
// For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// Calling AssumeRoleWithSAML does not require the use of Amazon Web Services
// security credentials. The identity of the caller is validated by using keys
// in the metadata document that is uploaded for the SAML provider entity for
// your identity provider.
//
// Calling AssumeRoleWithSAML can result in an entry in your CloudTrail logs.
// The entry includes the value in the NameID element of the SAML assertion.
// We recommend that you use a NameIDType that is not associated with any personally
// identifiable information (PII). For example, you could instead use the persistent
// identifier (urn:oasis:names:tc:SAML:2.0:nameid-format:persistent).
//
// Tags
//
// (Optional) You can configure your IdP to pass attributes into your SAML assertion
// as session tags. Each session tag consists of a key name and an associated
// value. For more information about session tags, see Passing Session Tags
// in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You can pass up to 50 session tags. The plaintext session tag keys can’t
// exceed 128 characters and the values can’t exceed 256 characters. For these
// and additional limits, see IAM and STS Character Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// You can pass a session tag with the same key as a tag that is attached to
// the role. When you do, session tags override the role's tags with the same
// key.
//
// An administrator must grant you the permissions necessary to pass session
// tags. The administrator can also create granular permissions to allow you
// to pass only specific session tags. For more information, see Tutorial: Using
// Tags for Attribute-Based Access Control (https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)
// in the IAM User Guide.
//
// You can set the session tags as transitive. Transitive tags persist during
// role chaining. For more information, see Chaining Roles with Session Tags
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining)
// in the IAM User Guide.
//
// SAML Configuration
//
// Before your application can call AssumeRoleWithSAML, you must configure your
// SAML identity provider (IdP) to issue the claims required by Amazon Web Services.
// Additionally, you must use Identity and Access Management (IAM) to create
// a SAML provider entity in your Amazon Web Services account that represents
// your identity provider. You must also create an IAM role that specifies this
// SAML provider in its trust policy.
//
// For more information, see the following resources:
//
// * About SAML 2.0-based Federation (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_saml.html)
// in the IAM User Guide.
//
// * Creating SAML Identity Providers (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html)
// in the IAM User Guide.
//
// * Configuring a Relying Party and Claims (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml_relying-party.html)
// in the IAM User Guide.
//
// * Creating a Role for SAML 2.0 Federation (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-idp_saml.html)
// in the IAM User Guide.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation AssumeRoleWithSAML for usage and error information.
//
// Returned Error Codes:
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
//
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
// The request was rejected because the total packed size of the session policies
// and session tags combined was too large. An Amazon Web Services conversion
// compresses the session policy document, session policy ARNs, and session
// tags into a packed binary format that has a separate limit. The error message
// indicates by percentage how close the policies and tags are to the upper
// size limit. For more information, see Passing Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You could receive this error even though you meet other defined session policy
// and session tag limits. For more information, see IAM and STS Entity Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
// The identity provider (IdP) reported that authentication failed. This might
// be because the claim is invalid.
//
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
// can also mean that the claim has expired or has been explicitly revoked.
//
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
// The web identity token that was passed could not be validated by Amazon Web
// Services. Get a new identity token from the identity provider and then retry
// the request.
//
// * ErrCodeExpiredTokenException "ExpiredTokenException"
// The web identity token that was passed is expired or is not valid. Get a
// new identity token from the identity provider and then retry the request.
//
// * ErrCodeRegionDisabledException "RegionDisabledException"
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithSAML
func (c *STS) AssumeRoleWithSAML(input *AssumeRoleWithSAMLInput) (*AssumeRoleWithSAMLOutput, error) {
req, out := c.AssumeRoleWithSAMLRequest(input)
return out, req.Send()
}
// AssumeRoleWithSAMLWithContext is the same as AssumeRoleWithSAML with the addition of
// the ability to pass a context and additional request options.
//
// See AssumeRoleWithSAML for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) AssumeRoleWithSAMLWithContext(ctx aws.Context, input *AssumeRoleWithSAMLInput, opts ...request.Option) (*AssumeRoleWithSAMLOutput, error) {
req, out := c.AssumeRoleWithSAMLRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opAssumeRoleWithWebIdentity = "AssumeRoleWithWebIdentity"
// AssumeRoleWithWebIdentityRequest generates a "aws/request.Request" representing the
// client's request for the AssumeRoleWithWebIdentity operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See AssumeRoleWithWebIdentity for more information on using the AssumeRoleWithWebIdentity
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the AssumeRoleWithWebIdentityRequest method.
// req, resp := client.AssumeRoleWithWebIdentityRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity
func (c *STS) AssumeRoleWithWebIdentityRequest(input *AssumeRoleWithWebIdentityInput) (req *request.Request, output *AssumeRoleWithWebIdentityOutput) {
op := &request.Operation{
Name: opAssumeRoleWithWebIdentity,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &AssumeRoleWithWebIdentityInput{}
}
output = &AssumeRoleWithWebIdentityOutput{}
req = c.newRequest(op, input, output)
req.Config.Credentials = credentials.AnonymousCredentials
return
}
// AssumeRoleWithWebIdentity API operation for AWS Security Token Service.
//
// Returns a set of temporary security credentials for users who have been authenticated
// in a mobile or web application with a web identity provider. Example providers
// include the OAuth 2.0 providers Login with Amazon and Facebook, or any OpenID
// Connect-compatible identity provider such as Google or Amazon Cognito federated
// identities (https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html).
//
// For mobile applications, we recommend that you use Amazon Cognito. You can
// use Amazon Cognito with the Amazon Web Services SDK for iOS Developer Guide
// (http://aws.amazon.com/sdkforios/) and the Amazon Web Services SDK for Android
// Developer Guide (http://aws.amazon.com/sdkforandroid/) to uniquely identify
// a user. You can also supply the user with a consistent identity throughout
// the lifetime of an application.
//
// To learn more about Amazon Cognito, see Amazon Cognito Overview (https://docs.aws.amazon.com/mobile/sdkforandroid/developerguide/cognito-auth.html#d0e840)
// in Amazon Web Services SDK for Android Developer Guide and Amazon Cognito
// Overview (https://docs.aws.amazon.com/mobile/sdkforios/developerguide/cognito-auth.html#d0e664)
// in the Amazon Web Services SDK for iOS Developer Guide.
//
// Calling AssumeRoleWithWebIdentity does not require the use of Amazon Web
// Services security credentials. Therefore, you can distribute an application
// (for example, on mobile devices) that requests temporary security credentials
// without including long-term Amazon Web Services credentials in the application.
// You also don't need to deploy server-based proxy services that use long-term
// Amazon Web Services credentials. Instead, the identity of the caller is validated
// by using a token from the web identity provider. For a comparison of AssumeRoleWithWebIdentity
// with the other API operations that produce temporary credentials, see Requesting
// Temporary Security Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
// and Comparing the Amazon Web Services STS API operations (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison)
// in the IAM User Guide.
//
// The temporary security credentials returned by this API consist of an access
// key ID, a secret access key, and a security token. Applications can use these
// temporary security credentials to sign calls to Amazon Web Services service
// API operations.
//
// Session Duration
//
// By default, the temporary security credentials created by AssumeRoleWithWebIdentity
// last for one hour. However, you can use the optional DurationSeconds parameter
// to specify the duration of your session. You can provide a value from 900
// seconds (15 minutes) up to the maximum session duration setting for the role.
// This setting can have a value from 1 hour to 12 hours. To learn how to view
// the maximum value for your role, see View the Maximum Session Duration Setting
// for a Role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session)
// in the IAM User Guide. The maximum session duration limit applies when you
// use the AssumeRole* API operations or the assume-role* CLI commands. However
// the limit does not apply when you use those operations to create a console
// URL. For more information, see Using IAM Roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html)
// in the IAM User Guide.
//
// Permissions
//
// The temporary security credentials created by AssumeRoleWithWebIdentity can
// be used to make API calls to any Amazon Web Services service with the following
// exception: you cannot call the STS GetFederationToken or GetSessionToken
// API operations.
//
// (Optional) You can pass inline or managed session policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies. The plaintext that you use for both inline
// and managed session policies can't exceed 2,048 characters. Passing policies
// to this operation returns new temporary credentials. The resulting session's
// permissions are the intersection of the role's identity-based policy and
// the session policies. You can use the role's temporary credentials in subsequent
// Amazon Web Services API calls to access resources in the account that owns
// the role. You cannot use session policies to grant more permissions than
// those allowed by the identity-based policy of the role that is being assumed.
// For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// Tags
//
// (Optional) You can configure your IdP to pass attributes into your web identity
// token as session tags. Each session tag consists of a key name and an associated
// value. For more information about session tags, see Passing Session Tags
// in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You can pass up to 50 session tags. The plaintext session tag keys can’t
// exceed 128 characters and the values can’t exceed 256 characters. For these
// and additional limits, see IAM and STS Character Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// You can pass a session tag with the same key as a tag that is attached to
// the role. When you do, the session tag overrides the role tag with the same
// key.
//
// An administrator must grant you the permissions necessary to pass session
// tags. The administrator can also create granular permissions to allow you
// to pass only specific session tags. For more information, see Tutorial: Using
// Tags for Attribute-Based Access Control (https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)
// in the IAM User Guide.
//
// You can set the session tags as transitive. Transitive tags persist during
// role chaining. For more information, see Chaining Roles with Session Tags
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining)
// in the IAM User Guide.
//
// Identities
//
// Before your application can call AssumeRoleWithWebIdentity, you must have
// an identity token from a supported identity provider and create a role that
// the application can assume. The role that your application assumes must trust
// the identity provider that is associated with the identity token. In other
// words, the identity provider must be specified in the role's trust policy.
//
// Calling AssumeRoleWithWebIdentity can result in an entry in your CloudTrail
// logs. The entry includes the Subject (http://openid.net/specs/openid-connect-core-1_0.html#Claims)
// of the provided web identity token. We recommend that you avoid using any
// personally identifiable information (PII) in this field. For example, you
// could instead use a GUID or a pairwise identifier, as suggested in the OIDC
// specification (http://openid.net/specs/openid-connect-core-1_0.html#SubjectIDTypes).
//
// For more information about how to use web identity federation and the AssumeRoleWithWebIdentity
// API, see the following resources:
//
// * Using Web Identity Federation API Operations for Mobile Apps (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_oidc_manual.html)
// and Federation Through a Web-based Identity Provider (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity).
//
// * Web Identity Federation Playground (https://aws.amazon.com/blogs/aws/the-aws-web-identity-federation-playground/).
// Walk through the process of authenticating through Login with Amazon,
// Facebook, or Google, getting temporary security credentials, and then
// using those credentials to make a request to Amazon Web Services.
//
// * Amazon Web Services SDK for iOS Developer Guide (http://aws.amazon.com/sdkforios/)
// and Amazon Web Services SDK for Android Developer Guide (http://aws.amazon.com/sdkforandroid/).
// These toolkits contain sample apps that show how to invoke the identity
// providers. The toolkits then show how to use the information from these
// providers to get and use temporary security credentials.
//
// * Web Identity Federation with Mobile Applications (http://aws.amazon.com/articles/web-identity-federation-with-mobile-applications).
// This article discusses web identity federation and shows an example of
// how to use web identity federation to get access to content in Amazon
// S3.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation AssumeRoleWithWebIdentity for usage and error information.
//
// Returned Error Codes:
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
//
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
// The request was rejected because the total packed size of the session policies
// and session tags combined was too large. An Amazon Web Services conversion
// compresses the session policy document, session policy ARNs, and session
// tags into a packed binary format that has a separate limit. The error message
// indicates by percentage how close the policies and tags are to the upper
// size limit. For more information, see Passing Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You could receive this error even though you meet other defined session policy
// and session tag limits. For more information, see IAM and STS Entity Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// * ErrCodeIDPRejectedClaimException "IDPRejectedClaim"
// The identity provider (IdP) reported that authentication failed. This might
// be because the claim is invalid.
//
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
// can also mean that the claim has expired or has been explicitly revoked.
//
// * ErrCodeIDPCommunicationErrorException "IDPCommunicationError"
// The request could not be fulfilled because the identity provider (IDP) that
// was asked to verify the incoming identity token could not be reached. This
// is often a transient error caused by network conditions. Retry the request
// a limited number of times so that you don't exceed the request rate. If the
// error persists, the identity provider might be down or not responding.
//
// * ErrCodeInvalidIdentityTokenException "InvalidIdentityToken"
// The web identity token that was passed could not be validated by Amazon Web
// Services. Get a new identity token from the identity provider and then retry
// the request.
//
// * ErrCodeExpiredTokenException "ExpiredTokenException"
// The web identity token that was passed is expired or is not valid. Get a
// new identity token from the identity provider and then retry the request.
//
// * ErrCodeRegionDisabledException "RegionDisabledException"
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/AssumeRoleWithWebIdentity
func (c *STS) AssumeRoleWithWebIdentity(input *AssumeRoleWithWebIdentityInput) (*AssumeRoleWithWebIdentityOutput, error) {
req, out := c.AssumeRoleWithWebIdentityRequest(input)
return out, req.Send()
}
// AssumeRoleWithWebIdentityWithContext is the same as AssumeRoleWithWebIdentity with the addition of
// the ability to pass a context and additional request options.
//
// See AssumeRoleWithWebIdentity for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) AssumeRoleWithWebIdentityWithContext(ctx aws.Context, input *AssumeRoleWithWebIdentityInput, opts ...request.Option) (*AssumeRoleWithWebIdentityOutput, error) {
req, out := c.AssumeRoleWithWebIdentityRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opDecodeAuthorizationMessage = "DecodeAuthorizationMessage"
// DecodeAuthorizationMessageRequest generates a "aws/request.Request" representing the
// client's request for the DecodeAuthorizationMessage operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See DecodeAuthorizationMessage for more information on using the DecodeAuthorizationMessage
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the DecodeAuthorizationMessageRequest method.
// req, resp := client.DecodeAuthorizationMessageRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage
func (c *STS) DecodeAuthorizationMessageRequest(input *DecodeAuthorizationMessageInput) (req *request.Request, output *DecodeAuthorizationMessageOutput) {
op := &request.Operation{
Name: opDecodeAuthorizationMessage,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &DecodeAuthorizationMessageInput{}
}
output = &DecodeAuthorizationMessageOutput{}
req = c.newRequest(op, input, output)
return
}
// DecodeAuthorizationMessage API operation for AWS Security Token Service.
//
// Decodes additional information about the authorization status of a request
// from an encoded message returned in response to an Amazon Web Services request.
//
// For example, if a user is not authorized to perform an operation that he
// or she has requested, the request returns a Client.UnauthorizedOperation
// response (an HTTP 403 response). Some Amazon Web Services operations additionally
// return an encoded message that can provide details about this authorization
// failure.
//
// Only certain Amazon Web Services operations return an encoded authorization
// message. The documentation for an individual operation indicates whether
// that operation returns an encoded message in addition to returning an HTTP
// code.
//
// The message is encoded because the details of the authorization status can
// contain privileged information that the user who requested the operation
// should not see. To decode an authorization status message, a user must be
// granted permissions through an IAM policy (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html)
// to request the DecodeAuthorizationMessage (sts:DecodeAuthorizationMessage)
// action.
//
// The decoded message includes the following type of information:
//
// * Whether the request was denied due to an explicit deny or due to the
// absence of an explicit allow. For more information, see Determining Whether
// a Request is Allowed or Denied (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow)
// in the IAM User Guide.
//
// * The principal who made the request.
//
// * The requested action.
//
// * The requested resource.
//
// * The values of condition keys in the context of the user's request.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation DecodeAuthorizationMessage for usage and error information.
//
// Returned Error Codes:
// * ErrCodeInvalidAuthorizationMessageException "InvalidAuthorizationMessageException"
// The error returned if the message passed to DecodeAuthorizationMessage was
// invalid. This can happen if the token contains invalid characters, such as
// linebreaks.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/DecodeAuthorizationMessage
func (c *STS) DecodeAuthorizationMessage(input *DecodeAuthorizationMessageInput) (*DecodeAuthorizationMessageOutput, error) {
req, out := c.DecodeAuthorizationMessageRequest(input)
return out, req.Send()
}
// DecodeAuthorizationMessageWithContext is the same as DecodeAuthorizationMessage with the addition of
// the ability to pass a context and additional request options.
//
// See DecodeAuthorizationMessage for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) DecodeAuthorizationMessageWithContext(ctx aws.Context, input *DecodeAuthorizationMessageInput, opts ...request.Option) (*DecodeAuthorizationMessageOutput, error) {
req, out := c.DecodeAuthorizationMessageRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetAccessKeyInfo = "GetAccessKeyInfo"
// GetAccessKeyInfoRequest generates a "aws/request.Request" representing the
// client's request for the GetAccessKeyInfo operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetAccessKeyInfo for more information on using the GetAccessKeyInfo
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetAccessKeyInfoRequest method.
// req, resp := client.GetAccessKeyInfoRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetAccessKeyInfo
func (c *STS) GetAccessKeyInfoRequest(input *GetAccessKeyInfoInput) (req *request.Request, output *GetAccessKeyInfoOutput) {
op := &request.Operation{
Name: opGetAccessKeyInfo,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetAccessKeyInfoInput{}
}
output = &GetAccessKeyInfoOutput{}
req = c.newRequest(op, input, output)
return
}
// GetAccessKeyInfo API operation for AWS Security Token Service.
//
// Returns the account identifier for the specified access key ID.
//
// Access keys consist of two parts: an access key ID (for example, AKIAIOSFODNN7EXAMPLE)
// and a secret access key (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY).
// For more information about access keys, see Managing Access Keys for IAM
// Users (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html)
// in the IAM User Guide.
//
// When you pass an access key ID to this operation, it returns the ID of the
// Amazon Web Services account to which the keys belong. Access key IDs beginning
// with AKIA are long-term credentials for an IAM user or the Amazon Web Services
// account root user. Access key IDs beginning with ASIA are temporary credentials
// that are created using STS operations. If the account in the response belongs
// to you, you can sign in as the root user and review your root user access
// keys. Then, you can pull a credentials report (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_getting-report.html)
// to learn which IAM user owns the keys. To learn who requested the temporary
// credentials for an ASIA access key, view the STS events in your CloudTrail
// logs (https://docs.aws.amazon.com/IAM/latest/UserGuide/cloudtrail-integration.html)
// in the IAM User Guide.
//
// This operation does not indicate the state of the access key. The key might
// be active, inactive, or deleted. Active keys might not have permissions to
// perform an operation. Providing a deleted access key might return an error
// that the key doesn't exist.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation GetAccessKeyInfo for usage and error information.
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetAccessKeyInfo
func (c *STS) GetAccessKeyInfo(input *GetAccessKeyInfoInput) (*GetAccessKeyInfoOutput, error) {
req, out := c.GetAccessKeyInfoRequest(input)
return out, req.Send()
}
// GetAccessKeyInfoWithContext is the same as GetAccessKeyInfo with the addition of
// the ability to pass a context and additional request options.
//
// See GetAccessKeyInfo for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) GetAccessKeyInfoWithContext(ctx aws.Context, input *GetAccessKeyInfoInput, opts ...request.Option) (*GetAccessKeyInfoOutput, error) {
req, out := c.GetAccessKeyInfoRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetCallerIdentity = "GetCallerIdentity"
// GetCallerIdentityRequest generates a "aws/request.Request" representing the
// client's request for the GetCallerIdentity operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetCallerIdentity for more information on using the GetCallerIdentity
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetCallerIdentityRequest method.
// req, resp := client.GetCallerIdentityRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity
func (c *STS) GetCallerIdentityRequest(input *GetCallerIdentityInput) (req *request.Request, output *GetCallerIdentityOutput) {
op := &request.Operation{
Name: opGetCallerIdentity,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetCallerIdentityInput{}
}
output = &GetCallerIdentityOutput{}
req = c.newRequest(op, input, output)
return
}
// GetCallerIdentity API operation for AWS Security Token Service.
//
// Returns details about the IAM user or role whose credentials are used to
// call the operation.
//
// No permissions are required to perform this operation. If an administrator
// adds a policy to your IAM user or role that explicitly denies access to the
// sts:GetCallerIdentity action, you can still perform this operation. Permissions
// are not required because the same information is returned when an IAM user
// or role is denied access. To view an example response, see I Am Not Authorized
// to Perform: iam:DeleteVirtualMFADevice (https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_access-denied-delete-mfa)
// in the IAM User Guide.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation GetCallerIdentity for usage and error information.
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetCallerIdentity
func (c *STS) GetCallerIdentity(input *GetCallerIdentityInput) (*GetCallerIdentityOutput, error) {
req, out := c.GetCallerIdentityRequest(input)
return out, req.Send()
}
// GetCallerIdentityWithContext is the same as GetCallerIdentity with the addition of
// the ability to pass a context and additional request options.
//
// See GetCallerIdentity for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) GetCallerIdentityWithContext(ctx aws.Context, input *GetCallerIdentityInput, opts ...request.Option) (*GetCallerIdentityOutput, error) {
req, out := c.GetCallerIdentityRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetFederationToken = "GetFederationToken"
// GetFederationTokenRequest generates a "aws/request.Request" representing the
// client's request for the GetFederationToken operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetFederationToken for more information on using the GetFederationToken
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetFederationTokenRequest method.
// req, resp := client.GetFederationTokenRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken
func (c *STS) GetFederationTokenRequest(input *GetFederationTokenInput) (req *request.Request, output *GetFederationTokenOutput) {
op := &request.Operation{
Name: opGetFederationToken,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetFederationTokenInput{}
}
output = &GetFederationTokenOutput{}
req = c.newRequest(op, input, output)
return
}
// GetFederationToken API operation for AWS Security Token Service.
//
// Returns a set of temporary security credentials (consisting of an access
// key ID, a secret access key, and a security token) for a federated user.
// A typical use is in a proxy application that gets temporary security credentials
// on behalf of distributed applications inside a corporate network. You must
// call the GetFederationToken operation using the long-term security credentials
// of an IAM user. As a result, this call is appropriate in contexts where those
// credentials can be safely stored, usually in a server-based application.
// For a comparison of GetFederationToken with the other API operations that
// produce temporary credentials, see Requesting Temporary Security Credentials
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
// and Comparing the Amazon Web Services STS API operations (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison)
// in the IAM User Guide.
//
// You can create a mobile-based or browser-based app that can authenticate
// users using a web identity provider like Login with Amazon, Facebook, Google,
// or an OpenID Connect-compatible identity provider. In this case, we recommend
// that you use Amazon Cognito (http://aws.amazon.com/cognito/) or AssumeRoleWithWebIdentity.
// For more information, see Federation Through a Web-based Identity Provider
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity)
// in the IAM User Guide.
//
// You can also call GetFederationToken using the security credentials of an
// Amazon Web Services account root user, but we do not recommend it. Instead,
// we recommend that you create an IAM user for the purpose of the proxy application.
// Then attach a policy to the IAM user that limits federated users to only
// the actions and resources that they need to access. For more information,
// see IAM Best Practices (https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
// in the IAM User Guide.
//
// Session duration
//
// The temporary credentials are valid for the specified duration, from 900
// seconds (15 minutes) up to a maximum of 129,600 seconds (36 hours). The default
// session duration is 43,200 seconds (12 hours). Temporary credentials obtained
// by using the Amazon Web Services account root user credentials have a maximum
// duration of 3,600 seconds (1 hour).
//
// Permissions
//
// You can use the temporary credentials created by GetFederationToken in any
// Amazon Web Services service except the following:
//
// * You cannot call any IAM operations using the CLI or the Amazon Web Services
// API.
//
// * You cannot call any STS operations except GetCallerIdentity.
//
// You must pass an inline or managed session policy (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies. The plaintext that you use for both inline
// and managed session policies can't exceed 2,048 characters.
//
// Though the session policy parameters are optional, if you do not pass a policy,
// then the resulting federated user session has no permissions. When you pass
// session policies, the session permissions are the intersection of the IAM
// user policies and the session policies that you pass. This gives you a way
// to further restrict the permissions for a federated user. You cannot use
// session policies to grant more permissions than those that are defined in
// the permissions policy of the IAM user. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide. For information about using GetFederationToken to
// create temporary security credentials, see GetFederationToken—Federation
// Through a Custom Identity Broker (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getfederationtoken).
//
// You can use the credentials to access a resource that has a resource-based
// policy. If that policy specifically references the federated user session
// in the Principal element of the policy, the session has the permissions allowed
// by the policy. These permissions are granted in addition to the permissions
// granted by the session policies.
//
// Tags
//
// (Optional) You can pass tag key-value pairs to your session. These are called
// session tags. For more information about session tags, see Passing Session
// Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You can create a mobile-based or browser-based app that can authenticate
// users using a web identity provider like Login with Amazon, Facebook, Google,
// or an OpenID Connect-compatible identity provider. In this case, we recommend
// that you use Amazon Cognito (http://aws.amazon.com/cognito/) or AssumeRoleWithWebIdentity.
// For more information, see Federation Through a Web-based Identity Provider
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_assumerolewithwebidentity)
// in the IAM User Guide.
//
// An administrator must grant you the permissions necessary to pass session
// tags. The administrator can also create granular permissions to allow you
// to pass only specific session tags. For more information, see Tutorial: Using
// Tags for Attribute-Based Access Control (https://docs.aws.amazon.com/IAM/latest/UserGuide/tutorial_attribute-based-access-control.html)
// in the IAM User Guide.
//
// Tag key–value pairs are not case sensitive, but case is preserved. This
// means that you cannot have separate Department and department tag keys. Assume
// that the user that you are federating has the Department=Marketing tag and
// you pass the department=engineering session tag. Department and department
// are not saved as separate tags, and the session tag passed in the request
// takes precedence over the user tag.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation GetFederationToken for usage and error information.
//
// Returned Error Codes:
// * ErrCodeMalformedPolicyDocumentException "MalformedPolicyDocument"
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
//
// * ErrCodePackedPolicyTooLargeException "PackedPolicyTooLarge"
// The request was rejected because the total packed size of the session policies
// and session tags combined was too large. An Amazon Web Services conversion
// compresses the session policy document, session policy ARNs, and session
// tags into a packed binary format that has a separate limit. The error message
// indicates by percentage how close the policies and tags are to the upper
// size limit. For more information, see Passing Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You could receive this error even though you meet other defined session policy
// and session tag limits. For more information, see IAM and STS Entity Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// * ErrCodeRegionDisabledException "RegionDisabledException"
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetFederationToken
func (c *STS) GetFederationToken(input *GetFederationTokenInput) (*GetFederationTokenOutput, error) {
req, out := c.GetFederationTokenRequest(input)
return out, req.Send()
}
// GetFederationTokenWithContext is the same as GetFederationToken with the addition of
// the ability to pass a context and additional request options.
//
// See GetFederationToken for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) GetFederationTokenWithContext(ctx aws.Context, input *GetFederationTokenInput, opts ...request.Option) (*GetFederationTokenOutput, error) {
req, out := c.GetFederationTokenRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
const opGetSessionToken = "GetSessionToken"
// GetSessionTokenRequest generates a "aws/request.Request" representing the
// client's request for the GetSessionToken operation. The "output" return
// value will be populated with the request's response once the request completes
// successfully.
//
// Use "Send" method on the returned Request to send the API call to the service.
// the "output" return value is not valid until after Send returns without error.
//
// See GetSessionToken for more information on using the GetSessionToken
// API call, and error handling.
//
// This method is useful when you want to inject custom logic or configuration
// into the SDK's request lifecycle. Such as custom headers, or retry logic.
//
//
// // Example sending a request using the GetSessionTokenRequest method.
// req, resp := client.GetSessionTokenRequest(params)
//
// err := req.Send()
// if err == nil { // resp is now filled
// fmt.Println(resp)
// }
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken
func (c *STS) GetSessionTokenRequest(input *GetSessionTokenInput) (req *request.Request, output *GetSessionTokenOutput) {
op := &request.Operation{
Name: opGetSessionToken,
HTTPMethod: "POST",
HTTPPath: "/",
}
if input == nil {
input = &GetSessionTokenInput{}
}
output = &GetSessionTokenOutput{}
req = c.newRequest(op, input, output)
return
}
// GetSessionToken API operation for AWS Security Token Service.
//
// Returns a set of temporary credentials for an Amazon Web Services account
// or IAM user. The credentials consist of an access key ID, a secret access
// key, and a security token. Typically, you use GetSessionToken if you want
// to use MFA to protect programmatic calls to specific Amazon Web Services
// API operations like Amazon EC2 StopInstances. MFA-enabled IAM users would
// need to call GetSessionToken and submit an MFA code that is associated with
// their MFA device. Using the temporary security credentials that are returned
// from the call, IAM users can then make programmatic calls to API operations
// that require MFA authentication. If you do not supply a correct MFA code,
// then the API returns an access denied error. For a comparison of GetSessionToken
// with the other API operations that produce temporary credentials, see Requesting
// Temporary Security Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html)
// and Comparing the Amazon Web Services STS API operations (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#stsapi_comparison)
// in the IAM User Guide.
//
// Session Duration
//
// The GetSessionToken operation must be called by using the long-term Amazon
// Web Services security credentials of the Amazon Web Services account root
// user or an IAM user. Credentials that are created by IAM users are valid
// for the duration that you specify. This duration can range from 900 seconds
// (15 minutes) up to a maximum of 129,600 seconds (36 hours), with a default
// of 43,200 seconds (12 hours). Credentials based on account credentials can
// range from 900 seconds (15 minutes) up to 3,600 seconds (1 hour), with a
// default of 1 hour.
//
// Permissions
//
// The temporary security credentials created by GetSessionToken can be used
// to make API calls to any Amazon Web Services service with the following exceptions:
//
// * You cannot call any IAM API operations unless MFA authentication information
// is included in the request.
//
// * You cannot call any STS API except AssumeRole or GetCallerIdentity.
//
// We recommend that you do not call GetSessionToken with Amazon Web Services
// account root user credentials. Instead, follow our best practices (https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users)
// by creating one or more IAM users, giving them the necessary permissions,
// and using IAM users for everyday interaction with Amazon Web Services.
//
// The credentials that are returned by GetSessionToken are based on permissions
// associated with the user whose credentials were used to call the operation.
// If GetSessionToken is called using Amazon Web Services account root user
// credentials, the temporary credentials have root user permissions. Similarly,
// if GetSessionToken is called using the credentials of an IAM user, the temporary
// credentials have the same permissions as the IAM user.
//
// For more information about using GetSessionToken to create temporary credentials,
// go to Temporary Credentials for Users in Untrusted Environments (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html#api_getsessiontoken)
// in the IAM User Guide.
//
// Returns awserr.Error for service API and SDK errors. Use runtime type assertions
// with awserr.Error's Code and Message methods to get detailed information about
// the error.
//
// See the AWS API reference guide for AWS Security Token Service's
// API operation GetSessionToken for usage and error information.
//
// Returned Error Codes:
// * ErrCodeRegionDisabledException "RegionDisabledException"
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
//
// See also, https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15/GetSessionToken
func (c *STS) GetSessionToken(input *GetSessionTokenInput) (*GetSessionTokenOutput, error) {
req, out := c.GetSessionTokenRequest(input)
return out, req.Send()
}
// GetSessionTokenWithContext is the same as GetSessionToken with the addition of
// the ability to pass a context and additional request options.
//
// See GetSessionToken for details on how to use this API operation.
//
// The context must be non-nil and will be used for request cancellation. If
// the context is nil a panic will occur. In the future the SDK may create
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
// for more information on using Contexts.
func (c *STS) GetSessionTokenWithContext(ctx aws.Context, input *GetSessionTokenInput, opts ...request.Option) (*GetSessionTokenOutput, error) {
req, out := c.GetSessionTokenRequest(input)
req.SetContext(ctx)
req.ApplyOptions(opts...)
return out, req.Send()
}
type AssumeRoleInput struct {
_ struct{} `type:"structure"`
// The duration, in seconds, of the role session. The value specified can range
// from 900 seconds (15 minutes) up to the maximum session duration set for
// the role. The maximum session duration setting can have a value from 1 hour
// to 12 hours. If you specify a value higher than this setting or the administrator
// setting (whichever is lower), the operation fails. For example, if you specify
// a session duration of 12 hours, but your administrator set the maximum session
// duration to 6 hours, your operation fails.
//
// Role chaining limits your Amazon Web Services CLI or Amazon Web Services
// API role session to a maximum of one hour. When you use the AssumeRole API
// operation to assume a role, you can specify the duration of your role session
// with the DurationSeconds parameter. You can specify a parameter value of
// up to 43200 seconds (12 hours), depending on the maximum session duration
// setting for your role. However, if you assume a role using role chaining
// and provide a DurationSeconds parameter value greater than one hour, the
// operation fails. To learn how to view the maximum value for your role, see
// View the Maximum Session Duration Setting for a Role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session)
// in the IAM User Guide.
//
// By default, the value is set to 3600 seconds.
//
// The DurationSeconds parameter is separate from the duration of a console
// session that you might request using the returned credentials. The request
// to the federation endpoint for a console sign-in token takes a SessionDuration
// parameter that specifies the maximum length of the console session. For more
// information, see Creating a URL that Enables Federated Users to Access the
// Amazon Web Services Management Console (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html)
// in the IAM User Guide.
DurationSeconds *int64 `min:"900" type:"integer"`
// A unique identifier that might be required when you assume a role in another
// account. If the administrator of the account to which the role belongs provided
// you with an external ID, then provide that value in the ExternalId parameter.
// This value can be any string, such as a passphrase or account number. A cross-account
// role is usually set up to trust everyone in an account. Therefore, the administrator
// of the trusting account might send an external ID to the administrator of
// the trusted account. That way, only someone with the ID can assume the role,
// rather than everyone in the account. For more information about the external
// ID, see How to Use an External ID When Granting Access to Your Amazon Web
// Services Resources to a Third Party (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html)
// in the IAM User Guide.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@:/-
ExternalId *string `min:"2" type:"string"`
// An IAM policy in JSON format that you want to use as an inline session policy.
//
// This parameter is optional. Passing policies to this operation returns new
// temporary credentials. The resulting session's permissions are the intersection
// of the role's identity-based policy and the session policies. You can use
// the role's temporary credentials in subsequent Amazon Web Services API calls
// to access resources in the account that owns the role. You cannot use session
// policies to grant more permissions than those allowed by the identity-based
// policy of the role that is being assumed. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// The plaintext that you use for both inline and managed session policies can't
// exceed 2,048 characters. The JSON policy characters can be any ASCII character
// from the space character to the end of the valid character list (\u0020 through
// \u00FF). It can also include the tab (\u0009), linefeed (\u000A), and carriage
// return (\u000D) characters.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
Policy *string `min:"1" type:"string"`
// The Amazon Resource Names (ARNs) of the IAM managed policies that you want
// to use as managed session policies. The policies must exist in the same account
// as the role.
//
// This parameter is optional. You can provide up to 10 managed policy ARNs.
// However, the plaintext that you use for both inline and managed session policies
// can't exceed 2,048 characters. For more information about ARNs, see Amazon
// Resource Names (ARNs) and Amazon Web Services Service Namespaces (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// Passing policies to this operation returns new temporary credentials. The
// resulting session's permissions are the intersection of the role's identity-based
// policy and the session policies. You can use the role's temporary credentials
// in subsequent Amazon Web Services API calls to access resources in the account
// that owns the role. You cannot use session policies to grant more permissions
// than those allowed by the identity-based policy of the role that is being
// assumed. For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
PolicyArns []*PolicyDescriptorType `type:"list"`
// The Amazon Resource Name (ARN) of the role to assume.
//
// RoleArn is a required field
RoleArn *string `min:"20" type:"string" required:"true"`
// An identifier for the assumed role session.
//
// Use the role session name to uniquely identify a session when the same role
// is assumed by different principals or for different reasons. In cross-account
// scenarios, the role session name is visible to, and can be logged by the
// account that owns the role. The role session name is also used in the ARN
// of the assumed role principal. This means that subsequent cross-account API
// requests that use the temporary security credentials will expose the role
// session name to the external account in their CloudTrail logs.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
//
// RoleSessionName is a required field
RoleSessionName *string `min:"2" type:"string" required:"true"`
// The identification number of the MFA device that is associated with the user
// who is making the AssumeRole call. Specify this value if the trust policy
// of the role being assumed includes a condition that requires MFA authentication.
// The value is either the serial number for a hardware device (such as GAHT12345678)
// or an Amazon Resource Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
SerialNumber *string `min:"9" type:"string"`
// The source identity specified by the principal that is calling the AssumeRole
// operation.
//
// You can require users to specify a source identity when they assume a role.
// You do this by using the sts:SourceIdentity condition key in a role trust
// policy. You can use source identity information in CloudTrail logs to determine
// who took actions with a role. You can use the aws:SourceIdentity condition
// key to further control access to Amazon Web Services resources based on the
// value of source identity. For more information about using source identity,
// see Monitor and control actions taken with assumed roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html)
// in the IAM User Guide.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-. You cannot
// use a value that begins with the text aws:. This prefix is reserved for Amazon
// Web Services internal use.
SourceIdentity *string `min:"2" type:"string"`
// A list of session tags that you want to pass. Each session tag consists of
// a key name and an associated value. For more information about session tags,
// see Tagging Amazon Web Services STS Sessions (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// This parameter is optional. You can pass up to 50 session tags. The plaintext
// session tag keys can’t exceed 128 characters, and the values can’t exceed
// 256 characters. For these and additional limits, see IAM and STS Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// You can pass a session tag with the same key as a tag that is already attached
// to the role. When you do, session tags override a role tag with the same
// key.
//
// Tag key–value pairs are not case sensitive, but case is preserved. This
// means that you cannot have separate Department and department tag keys. Assume
// that the role has the Department=Marketing tag and you pass the department=engineering
// session tag. Department and department are not saved as separate tags, and
// the session tag passed in the request takes precedence over the role tag.
//
// Additionally, if you used temporary credentials to perform this operation,
// the new session inherits any transitive session tags from the calling session.
// If you pass a session tag with the same key as an inherited tag, the operation
// fails. To view the inherited tags for a session, see the CloudTrail logs.
// For more information, see Viewing Session Tags in CloudTrail (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_ctlogs)
// in the IAM User Guide.
Tags []*Tag `type:"list"`
// The value provided by the MFA device, if the trust policy of the role being
// assumed requires MFA. (In other words, if the policy includes a condition
// that tests for MFA). If the role being assumed requires MFA and if the TokenCode
// value is missing or expired, the AssumeRole call returns an "access denied"
// error.
//
// The format for this parameter, as described by its regex pattern, is a sequence
// of six numeric digits.
TokenCode *string `min:"6" type:"string"`
// A list of keys for session tags that you want to set as transitive. If you
// set a tag key as transitive, the corresponding key and value passes to subsequent
// sessions in a role chain. For more information, see Chaining Roles with Session
// Tags (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining)
// in the IAM User Guide.
//
// This parameter is optional. When you set session tags as transitive, the
// session policy and session tags packed binary limit is not affected.
//
// If you choose not to specify a transitive tag key, then no tags are passed
// from this session to any subsequent sessions.
TransitiveTagKeys []*string `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *AssumeRoleInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "AssumeRoleInput"}
if s.DurationSeconds != nil && *s.DurationSeconds < 900 {
invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900))
}
if s.ExternalId != nil && len(*s.ExternalId) < 2 {
invalidParams.Add(request.NewErrParamMinLen("ExternalId", 2))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.RoleArn == nil {
invalidParams.Add(request.NewErrParamRequired("RoleArn"))
}
if s.RoleArn != nil && len(*s.RoleArn) < 20 {
invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20))
}
if s.RoleSessionName == nil {
invalidParams.Add(request.NewErrParamRequired("RoleSessionName"))
}
if s.RoleSessionName != nil && len(*s.RoleSessionName) < 2 {
invalidParams.Add(request.NewErrParamMinLen("RoleSessionName", 2))
}
if s.SerialNumber != nil && len(*s.SerialNumber) < 9 {
invalidParams.Add(request.NewErrParamMinLen("SerialNumber", 9))
}
if s.SourceIdentity != nil && len(*s.SourceIdentity) < 2 {
invalidParams.Add(request.NewErrParamMinLen("SourceIdentity", 2))
}
if s.TokenCode != nil && len(*s.TokenCode) < 6 {
invalidParams.Add(request.NewErrParamMinLen("TokenCode", 6))
}
if s.PolicyArns != nil {
for i, v := range s.PolicyArns {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "PolicyArns", i), err.(request.ErrInvalidParams))
}
}
}
if s.Tags != nil {
for i, v := range s.Tags {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDurationSeconds sets the DurationSeconds field's value.
func (s *AssumeRoleInput) SetDurationSeconds(v int64) *AssumeRoleInput {
s.DurationSeconds = &v
return s
}
// SetExternalId sets the ExternalId field's value.
func (s *AssumeRoleInput) SetExternalId(v string) *AssumeRoleInput {
s.ExternalId = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *AssumeRoleInput) SetPolicy(v string) *AssumeRoleInput {
s.Policy = &v
return s
}
// SetPolicyArns sets the PolicyArns field's value.
func (s *AssumeRoleInput) SetPolicyArns(v []*PolicyDescriptorType) *AssumeRoleInput {
s.PolicyArns = v
return s
}
// SetRoleArn sets the RoleArn field's value.
func (s *AssumeRoleInput) SetRoleArn(v string) *AssumeRoleInput {
s.RoleArn = &v
return s
}
// SetRoleSessionName sets the RoleSessionName field's value.
func (s *AssumeRoleInput) SetRoleSessionName(v string) *AssumeRoleInput {
s.RoleSessionName = &v
return s
}
// SetSerialNumber sets the SerialNumber field's value.
func (s *AssumeRoleInput) SetSerialNumber(v string) *AssumeRoleInput {
s.SerialNumber = &v
return s
}
// SetSourceIdentity sets the SourceIdentity field's value.
func (s *AssumeRoleInput) SetSourceIdentity(v string) *AssumeRoleInput {
s.SourceIdentity = &v
return s
}
// SetTags sets the Tags field's value.
func (s *AssumeRoleInput) SetTags(v []*Tag) *AssumeRoleInput {
s.Tags = v
return s
}
// SetTokenCode sets the TokenCode field's value.
func (s *AssumeRoleInput) SetTokenCode(v string) *AssumeRoleInput {
s.TokenCode = &v
return s
}
// SetTransitiveTagKeys sets the TransitiveTagKeys field's value.
func (s *AssumeRoleInput) SetTransitiveTagKeys(v []*string) *AssumeRoleInput {
s.TransitiveTagKeys = v
return s
}
// Contains the response to a successful AssumeRole request, including temporary
// Amazon Web Services credentials that can be used to make Amazon Web Services
// requests.
type AssumeRoleOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers
// that you can use to refer to the resulting temporary security credentials.
// For example, you can reference these credentials as a principal in a resource-based
// policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName
// that you specified when you called AssumeRole.
AssumedRoleUser *AssumedRoleUser `type:"structure"`
// The temporary security credentials, which include an access key ID, a secret
// access key, and a security (or session) token.
//
// The size of the security token that STS API operations return is not fixed.
// We strongly recommend that you make no assumptions about the maximum size.
Credentials *Credentials `type:"structure"`
// A percentage value that indicates the packed size of the session policies
// and session tags combined passed in the request. The request fails if the
// packed size is greater than 100 percent, which means the policies and tags
// exceeded the allowed space.
PackedPolicySize *int64 `type:"integer"`
// The source identity specified by the principal that is calling the AssumeRole
// operation.
//
// You can require users to specify a source identity when they assume a role.
// You do this by using the sts:SourceIdentity condition key in a role trust
// policy. You can use source identity information in CloudTrail logs to determine
// who took actions with a role. You can use the aws:SourceIdentity condition
// key to further control access to Amazon Web Services resources based on the
// value of source identity. For more information about using source identity,
// see Monitor and control actions taken with assumed roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html)
// in the IAM User Guide.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
SourceIdentity *string `min:"2" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleOutput) GoString() string {
return s.String()
}
// SetAssumedRoleUser sets the AssumedRoleUser field's value.
func (s *AssumeRoleOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleOutput {
s.AssumedRoleUser = v
return s
}
// SetCredentials sets the Credentials field's value.
func (s *AssumeRoleOutput) SetCredentials(v *Credentials) *AssumeRoleOutput {
s.Credentials = v
return s
}
// SetPackedPolicySize sets the PackedPolicySize field's value.
func (s *AssumeRoleOutput) SetPackedPolicySize(v int64) *AssumeRoleOutput {
s.PackedPolicySize = &v
return s
}
// SetSourceIdentity sets the SourceIdentity field's value.
func (s *AssumeRoleOutput) SetSourceIdentity(v string) *AssumeRoleOutput {
s.SourceIdentity = &v
return s
}
type AssumeRoleWithSAMLInput struct {
_ struct{} `type:"structure"`
// The duration, in seconds, of the role session. Your role session lasts for
// the duration that you specify for the DurationSeconds parameter, or until
// the time specified in the SAML authentication response's SessionNotOnOrAfter
// value, whichever is shorter. You can provide a DurationSeconds value from
// 900 seconds (15 minutes) up to the maximum session duration setting for the
// role. This setting can have a value from 1 hour to 12 hours. If you specify
// a value higher than this setting, the operation fails. For example, if you
// specify a session duration of 12 hours, but your administrator set the maximum
// session duration to 6 hours, your operation fails. To learn how to view the
// maximum value for your role, see View the Maximum Session Duration Setting
// for a Role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session)
// in the IAM User Guide.
//
// By default, the value is set to 3600 seconds.
//
// The DurationSeconds parameter is separate from the duration of a console
// session that you might request using the returned credentials. The request
// to the federation endpoint for a console sign-in token takes a SessionDuration
// parameter that specifies the maximum length of the console session. For more
// information, see Creating a URL that Enables Federated Users to Access the
// Amazon Web Services Management Console (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html)
// in the IAM User Guide.
DurationSeconds *int64 `min:"900" type:"integer"`
// An IAM policy in JSON format that you want to use as an inline session policy.
//
// This parameter is optional. Passing policies to this operation returns new
// temporary credentials. The resulting session's permissions are the intersection
// of the role's identity-based policy and the session policies. You can use
// the role's temporary credentials in subsequent Amazon Web Services API calls
// to access resources in the account that owns the role. You cannot use session
// policies to grant more permissions than those allowed by the identity-based
// policy of the role that is being assumed. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// The plaintext that you use for both inline and managed session policies can't
// exceed 2,048 characters. The JSON policy characters can be any ASCII character
// from the space character to the end of the valid character list (\u0020 through
// \u00FF). It can also include the tab (\u0009), linefeed (\u000A), and carriage
// return (\u000D) characters.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
Policy *string `min:"1" type:"string"`
// The Amazon Resource Names (ARNs) of the IAM managed policies that you want
// to use as managed session policies. The policies must exist in the same account
// as the role.
//
// This parameter is optional. You can provide up to 10 managed policy ARNs.
// However, the plaintext that you use for both inline and managed session policies
// can't exceed 2,048 characters. For more information about ARNs, see Amazon
// Resource Names (ARNs) and Amazon Web Services Service Namespaces (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// Passing policies to this operation returns new temporary credentials. The
// resulting session's permissions are the intersection of the role's identity-based
// policy and the session policies. You can use the role's temporary credentials
// in subsequent Amazon Web Services API calls to access resources in the account
// that owns the role. You cannot use session policies to grant more permissions
// than those allowed by the identity-based policy of the role that is being
// assumed. For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
PolicyArns []*PolicyDescriptorType `type:"list"`
// The Amazon Resource Name (ARN) of the SAML provider in IAM that describes
// the IdP.
//
// PrincipalArn is a required field
PrincipalArn *string `min:"20" type:"string" required:"true"`
// The Amazon Resource Name (ARN) of the role that the caller is assuming.
//
// RoleArn is a required field
RoleArn *string `min:"20" type:"string" required:"true"`
// The base64 encoded SAML authentication response provided by the IdP.
//
// For more information, see Configuring a Relying Party and Adding Claims (https://docs.aws.amazon.com/IAM/latest/UserGuide/create-role-saml-IdP-tasks.html)
// in the IAM User Guide.
//
// SAMLAssertion is a required field
SAMLAssertion *string `min:"4" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *AssumeRoleWithSAMLInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "AssumeRoleWithSAMLInput"}
if s.DurationSeconds != nil && *s.DurationSeconds < 900 {
invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.PrincipalArn == nil {
invalidParams.Add(request.NewErrParamRequired("PrincipalArn"))
}
if s.PrincipalArn != nil && len(*s.PrincipalArn) < 20 {
invalidParams.Add(request.NewErrParamMinLen("PrincipalArn", 20))
}
if s.RoleArn == nil {
invalidParams.Add(request.NewErrParamRequired("RoleArn"))
}
if s.RoleArn != nil && len(*s.RoleArn) < 20 {
invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20))
}
if s.SAMLAssertion == nil {
invalidParams.Add(request.NewErrParamRequired("SAMLAssertion"))
}
if s.SAMLAssertion != nil && len(*s.SAMLAssertion) < 4 {
invalidParams.Add(request.NewErrParamMinLen("SAMLAssertion", 4))
}
if s.PolicyArns != nil {
for i, v := range s.PolicyArns {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "PolicyArns", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDurationSeconds sets the DurationSeconds field's value.
func (s *AssumeRoleWithSAMLInput) SetDurationSeconds(v int64) *AssumeRoleWithSAMLInput {
s.DurationSeconds = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *AssumeRoleWithSAMLInput) SetPolicy(v string) *AssumeRoleWithSAMLInput {
s.Policy = &v
return s
}
// SetPolicyArns sets the PolicyArns field's value.
func (s *AssumeRoleWithSAMLInput) SetPolicyArns(v []*PolicyDescriptorType) *AssumeRoleWithSAMLInput {
s.PolicyArns = v
return s
}
// SetPrincipalArn sets the PrincipalArn field's value.
func (s *AssumeRoleWithSAMLInput) SetPrincipalArn(v string) *AssumeRoleWithSAMLInput {
s.PrincipalArn = &v
return s
}
// SetRoleArn sets the RoleArn field's value.
func (s *AssumeRoleWithSAMLInput) SetRoleArn(v string) *AssumeRoleWithSAMLInput {
s.RoleArn = &v
return s
}
// SetSAMLAssertion sets the SAMLAssertion field's value.
func (s *AssumeRoleWithSAMLInput) SetSAMLAssertion(v string) *AssumeRoleWithSAMLInput {
s.SAMLAssertion = &v
return s
}
// Contains the response to a successful AssumeRoleWithSAML request, including
// temporary Amazon Web Services credentials that can be used to make Amazon
// Web Services requests.
type AssumeRoleWithSAMLOutput struct {
_ struct{} `type:"structure"`
// The identifiers for the temporary security credentials that the operation
// returns.
AssumedRoleUser *AssumedRoleUser `type:"structure"`
// The value of the Recipient attribute of the SubjectConfirmationData element
// of the SAML assertion.
Audience *string `type:"string"`
// The temporary security credentials, which include an access key ID, a secret
// access key, and a security (or session) token.
//
// The size of the security token that STS API operations return is not fixed.
// We strongly recommend that you make no assumptions about the maximum size.
Credentials *Credentials `type:"structure"`
// The value of the Issuer element of the SAML assertion.
Issuer *string `type:"string"`
// A hash value based on the concatenation of the following:
//
// * The Issuer response value.
//
// * The Amazon Web Services account ID.
//
// * The friendly name (the last part of the ARN) of the SAML provider in
// IAM.
//
// The combination of NameQualifier and Subject can be used to uniquely identify
// a federated user.
//
// The following pseudocode shows how the hash value is calculated:
//
// BASE64 ( SHA1 ( "https://example.com/saml" + "123456789012" + "/MySAMLIdP"
// ) )
NameQualifier *string `type:"string"`
// A percentage value that indicates the packed size of the session policies
// and session tags combined passed in the request. The request fails if the
// packed size is greater than 100 percent, which means the policies and tags
// exceeded the allowed space.
PackedPolicySize *int64 `type:"integer"`
// The value in the SourceIdentity attribute in the SAML assertion.
//
// You can require users to set a source identity value when they assume a role.
// You do this by using the sts:SourceIdentity condition key in a role trust
// policy. That way, actions that are taken with the role are associated with
// that user. After the source identity is set, the value cannot be changed.
// It is present in the request for all actions that are taken by the role and
// persists across chained role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts#iam-term-role-chaining)
// sessions. You can configure your SAML identity provider to use an attribute
// associated with your users, like user name or email, as the source identity
// when calling AssumeRoleWithSAML. You do this by adding an attribute to the
// SAML assertion. For more information about using source identity, see Monitor
// and control actions taken with assumed roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html)
// in the IAM User Guide.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
SourceIdentity *string `min:"2" type:"string"`
// The value of the NameID element in the Subject element of the SAML assertion.
Subject *string `type:"string"`
// The format of the name ID, as defined by the Format attribute in the NameID
// element of the SAML assertion. Typical examples of the format are transient
// or persistent.
//
// If the format includes the prefix urn:oasis:names:tc:SAML:2.0:nameid-format,
// that prefix is removed. For example, urn:oasis:names:tc:SAML:2.0:nameid-format:transient
// is returned as transient. If the format includes any other prefix, the format
// is returned with no modifications.
SubjectType *string `type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithSAMLOutput) GoString() string {
return s.String()
}
// SetAssumedRoleUser sets the AssumedRoleUser field's value.
func (s *AssumeRoleWithSAMLOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleWithSAMLOutput {
s.AssumedRoleUser = v
return s
}
// SetAudience sets the Audience field's value.
func (s *AssumeRoleWithSAMLOutput) SetAudience(v string) *AssumeRoleWithSAMLOutput {
s.Audience = &v
return s
}
// SetCredentials sets the Credentials field's value.
func (s *AssumeRoleWithSAMLOutput) SetCredentials(v *Credentials) *AssumeRoleWithSAMLOutput {
s.Credentials = v
return s
}
// SetIssuer sets the Issuer field's value.
func (s *AssumeRoleWithSAMLOutput) SetIssuer(v string) *AssumeRoleWithSAMLOutput {
s.Issuer = &v
return s
}
// SetNameQualifier sets the NameQualifier field's value.
func (s *AssumeRoleWithSAMLOutput) SetNameQualifier(v string) *AssumeRoleWithSAMLOutput {
s.NameQualifier = &v
return s
}
// SetPackedPolicySize sets the PackedPolicySize field's value.
func (s *AssumeRoleWithSAMLOutput) SetPackedPolicySize(v int64) *AssumeRoleWithSAMLOutput {
s.PackedPolicySize = &v
return s
}
// SetSourceIdentity sets the SourceIdentity field's value.
func (s *AssumeRoleWithSAMLOutput) SetSourceIdentity(v string) *AssumeRoleWithSAMLOutput {
s.SourceIdentity = &v
return s
}
// SetSubject sets the Subject field's value.
func (s *AssumeRoleWithSAMLOutput) SetSubject(v string) *AssumeRoleWithSAMLOutput {
s.Subject = &v
return s
}
// SetSubjectType sets the SubjectType field's value.
func (s *AssumeRoleWithSAMLOutput) SetSubjectType(v string) *AssumeRoleWithSAMLOutput {
s.SubjectType = &v
return s
}
type AssumeRoleWithWebIdentityInput struct {
_ struct{} `type:"structure"`
// The duration, in seconds, of the role session. The value can range from 900
// seconds (15 minutes) up to the maximum session duration setting for the role.
// This setting can have a value from 1 hour to 12 hours. If you specify a value
// higher than this setting, the operation fails. For example, if you specify
// a session duration of 12 hours, but your administrator set the maximum session
// duration to 6 hours, your operation fails. To learn how to view the maximum
// value for your role, see View the Maximum Session Duration Setting for a
// Role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use.html#id_roles_use_view-role-max-session)
// in the IAM User Guide.
//
// By default, the value is set to 3600 seconds.
//
// The DurationSeconds parameter is separate from the duration of a console
// session that you might request using the returned credentials. The request
// to the federation endpoint for a console sign-in token takes a SessionDuration
// parameter that specifies the maximum length of the console session. For more
// information, see Creating a URL that Enables Federated Users to Access the
// Amazon Web Services Management Console (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_enable-console-custom-url.html)
// in the IAM User Guide.
DurationSeconds *int64 `min:"900" type:"integer"`
// An IAM policy in JSON format that you want to use as an inline session policy.
//
// This parameter is optional. Passing policies to this operation returns new
// temporary credentials. The resulting session's permissions are the intersection
// of the role's identity-based policy and the session policies. You can use
// the role's temporary credentials in subsequent Amazon Web Services API calls
// to access resources in the account that owns the role. You cannot use session
// policies to grant more permissions than those allowed by the identity-based
// policy of the role that is being assumed. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// The plaintext that you use for both inline and managed session policies can't
// exceed 2,048 characters. The JSON policy characters can be any ASCII character
// from the space character to the end of the valid character list (\u0020 through
// \u00FF). It can also include the tab (\u0009), linefeed (\u000A), and carriage
// return (\u000D) characters.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
Policy *string `min:"1" type:"string"`
// The Amazon Resource Names (ARNs) of the IAM managed policies that you want
// to use as managed session policies. The policies must exist in the same account
// as the role.
//
// This parameter is optional. You can provide up to 10 managed policy ARNs.
// However, the plaintext that you use for both inline and managed session policies
// can't exceed 2,048 characters. For more information about ARNs, see Amazon
// Resource Names (ARNs) and Amazon Web Services Service Namespaces (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// Passing policies to this operation returns new temporary credentials. The
// resulting session's permissions are the intersection of the role's identity-based
// policy and the session policies. You can use the role's temporary credentials
// in subsequent Amazon Web Services API calls to access resources in the account
// that owns the role. You cannot use session policies to grant more permissions
// than those allowed by the identity-based policy of the role that is being
// assumed. For more information, see Session Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
PolicyArns []*PolicyDescriptorType `type:"list"`
// The fully qualified host component of the domain name of the OAuth 2.0 identity
// provider. Do not specify this value for an OpenID Connect identity provider.
//
// Currently www.amazon.com and graph.facebook.com are the only supported identity
// providers for OAuth 2.0 access tokens. Do not include URL schemes and port
// numbers.
//
// Do not specify this value for OpenID Connect ID tokens.
ProviderId *string `min:"4" type:"string"`
// The Amazon Resource Name (ARN) of the role that the caller is assuming.
//
// RoleArn is a required field
RoleArn *string `min:"20" type:"string" required:"true"`
// An identifier for the assumed role session. Typically, you pass the name
// or identifier that is associated with the user who is using your application.
// That way, the temporary security credentials that your application will use
// are associated with that user. This session name is included as part of the
// ARN and assumed role ID in the AssumedRoleUser response element.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
//
// RoleSessionName is a required field
RoleSessionName *string `min:"2" type:"string" required:"true"`
// The OAuth 2.0 access token or OpenID Connect ID token that is provided by
// the identity provider. Your application must get this token by authenticating
// the user who is using your application with a web identity provider before
// the application makes an AssumeRoleWithWebIdentity call.
//
// WebIdentityToken is a required field
WebIdentityToken *string `min:"4" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *AssumeRoleWithWebIdentityInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "AssumeRoleWithWebIdentityInput"}
if s.DurationSeconds != nil && *s.DurationSeconds < 900 {
invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.ProviderId != nil && len(*s.ProviderId) < 4 {
invalidParams.Add(request.NewErrParamMinLen("ProviderId", 4))
}
if s.RoleArn == nil {
invalidParams.Add(request.NewErrParamRequired("RoleArn"))
}
if s.RoleArn != nil && len(*s.RoleArn) < 20 {
invalidParams.Add(request.NewErrParamMinLen("RoleArn", 20))
}
if s.RoleSessionName == nil {
invalidParams.Add(request.NewErrParamRequired("RoleSessionName"))
}
if s.RoleSessionName != nil && len(*s.RoleSessionName) < 2 {
invalidParams.Add(request.NewErrParamMinLen("RoleSessionName", 2))
}
if s.WebIdentityToken == nil {
invalidParams.Add(request.NewErrParamRequired("WebIdentityToken"))
}
if s.WebIdentityToken != nil && len(*s.WebIdentityToken) < 4 {
invalidParams.Add(request.NewErrParamMinLen("WebIdentityToken", 4))
}
if s.PolicyArns != nil {
for i, v := range s.PolicyArns {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "PolicyArns", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDurationSeconds sets the DurationSeconds field's value.
func (s *AssumeRoleWithWebIdentityInput) SetDurationSeconds(v int64) *AssumeRoleWithWebIdentityInput {
s.DurationSeconds = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *AssumeRoleWithWebIdentityInput) SetPolicy(v string) *AssumeRoleWithWebIdentityInput {
s.Policy = &v
return s
}
// SetPolicyArns sets the PolicyArns field's value.
func (s *AssumeRoleWithWebIdentityInput) SetPolicyArns(v []*PolicyDescriptorType) *AssumeRoleWithWebIdentityInput {
s.PolicyArns = v
return s
}
// SetProviderId sets the ProviderId field's value.
func (s *AssumeRoleWithWebIdentityInput) SetProviderId(v string) *AssumeRoleWithWebIdentityInput {
s.ProviderId = &v
return s
}
// SetRoleArn sets the RoleArn field's value.
func (s *AssumeRoleWithWebIdentityInput) SetRoleArn(v string) *AssumeRoleWithWebIdentityInput {
s.RoleArn = &v
return s
}
// SetRoleSessionName sets the RoleSessionName field's value.
func (s *AssumeRoleWithWebIdentityInput) SetRoleSessionName(v string) *AssumeRoleWithWebIdentityInput {
s.RoleSessionName = &v
return s
}
// SetWebIdentityToken sets the WebIdentityToken field's value.
func (s *AssumeRoleWithWebIdentityInput) SetWebIdentityToken(v string) *AssumeRoleWithWebIdentityInput {
s.WebIdentityToken = &v
return s
}
// Contains the response to a successful AssumeRoleWithWebIdentity request,
// including temporary Amazon Web Services credentials that can be used to make
// Amazon Web Services requests.
type AssumeRoleWithWebIdentityOutput struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (ARN) and the assumed role ID, which are identifiers
// that you can use to refer to the resulting temporary security credentials.
// For example, you can reference these credentials as a principal in a resource-based
// policy by using the ARN or assumed role ID. The ARN and ID include the RoleSessionName
// that you specified when you called AssumeRole.
AssumedRoleUser *AssumedRoleUser `type:"structure"`
// The intended audience (also known as client ID) of the web identity token.
// This is traditionally the client identifier issued to the application that
// requested the web identity token.
Audience *string `type:"string"`
// The temporary security credentials, which include an access key ID, a secret
// access key, and a security token.
//
// The size of the security token that STS API operations return is not fixed.
// We strongly recommend that you make no assumptions about the maximum size.
Credentials *Credentials `type:"structure"`
// A percentage value that indicates the packed size of the session policies
// and session tags combined passed in the request. The request fails if the
// packed size is greater than 100 percent, which means the policies and tags
// exceeded the allowed space.
PackedPolicySize *int64 `type:"integer"`
// The issuing authority of the web identity token presented. For OpenID Connect
// ID tokens, this contains the value of the iss field. For OAuth 2.0 access
// tokens, this contains the value of the ProviderId parameter that was passed
// in the AssumeRoleWithWebIdentity request.
Provider *string `type:"string"`
// The value of the source identity that is returned in the JSON web token (JWT)
// from the identity provider.
//
// You can require users to set a source identity value when they assume a role.
// You do this by using the sts:SourceIdentity condition key in a role trust
// policy. That way, actions that are taken with the role are associated with
// that user. After the source identity is set, the value cannot be changed.
// It is present in the request for all actions that are taken by the role and
// persists across chained role (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts#iam-term-role-chaining)
// sessions. You can configure your identity provider to use an attribute associated
// with your users, like user name or email, as the source identity when calling
// AssumeRoleWithWebIdentity. You do this by adding a claim to the JSON web
// token. To learn more about OIDC tokens and claims, see Using Tokens with
// User Pools (https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html)
// in the Amazon Cognito Developer Guide. For more information about using source
// identity, see Monitor and control actions taken with assumed roles (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_control-access_monitor.html)
// in the IAM User Guide.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
SourceIdentity *string `min:"2" type:"string"`
// The unique user identifier that is returned by the identity provider. This
// identifier is associated with the WebIdentityToken that was submitted with
// the AssumeRoleWithWebIdentity call. The identifier is typically unique to
// the user and the application that acquired the WebIdentityToken (pairwise
// identifier). For OpenID Connect ID tokens, this field contains the value
// returned by the identity provider as the token's sub (Subject) claim.
SubjectFromWebIdentityToken *string `min:"6" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumeRoleWithWebIdentityOutput) GoString() string {
return s.String()
}
// SetAssumedRoleUser sets the AssumedRoleUser field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetAssumedRoleUser(v *AssumedRoleUser) *AssumeRoleWithWebIdentityOutput {
s.AssumedRoleUser = v
return s
}
// SetAudience sets the Audience field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetAudience(v string) *AssumeRoleWithWebIdentityOutput {
s.Audience = &v
return s
}
// SetCredentials sets the Credentials field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetCredentials(v *Credentials) *AssumeRoleWithWebIdentityOutput {
s.Credentials = v
return s
}
// SetPackedPolicySize sets the PackedPolicySize field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetPackedPolicySize(v int64) *AssumeRoleWithWebIdentityOutput {
s.PackedPolicySize = &v
return s
}
// SetProvider sets the Provider field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetProvider(v string) *AssumeRoleWithWebIdentityOutput {
s.Provider = &v
return s
}
// SetSourceIdentity sets the SourceIdentity field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetSourceIdentity(v string) *AssumeRoleWithWebIdentityOutput {
s.SourceIdentity = &v
return s
}
// SetSubjectFromWebIdentityToken sets the SubjectFromWebIdentityToken field's value.
func (s *AssumeRoleWithWebIdentityOutput) SetSubjectFromWebIdentityToken(v string) *AssumeRoleWithWebIdentityOutput {
s.SubjectFromWebIdentityToken = &v
return s
}
// The identifiers for the temporary security credentials that the operation
// returns.
type AssumedRoleUser struct {
_ struct{} `type:"structure"`
// The ARN of the temporary security credentials that are returned from the
// AssumeRole action. For more information about ARNs and how to use them in
// policies, see IAM Identifiers (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html)
// in the IAM User Guide.
//
// Arn is a required field
Arn *string `min:"20" type:"string" required:"true"`
// A unique identifier that contains the role ID and the role session name of
// the role that is being assumed. The role ID is generated by Amazon Web Services
// when the role is created.
//
// AssumedRoleId is a required field
AssumedRoleId *string `min:"2" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumedRoleUser) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s AssumedRoleUser) GoString() string {
return s.String()
}
// SetArn sets the Arn field's value.
func (s *AssumedRoleUser) SetArn(v string) *AssumedRoleUser {
s.Arn = &v
return s
}
// SetAssumedRoleId sets the AssumedRoleId field's value.
func (s *AssumedRoleUser) SetAssumedRoleId(v string) *AssumedRoleUser {
s.AssumedRoleId = &v
return s
}
// Amazon Web Services credentials for API authentication.
type Credentials struct {
_ struct{} `type:"structure"`
// The access key ID that identifies the temporary security credentials.
//
// AccessKeyId is a required field
AccessKeyId *string `min:"16" type:"string" required:"true"`
// The date on which the current credentials expire.
//
// Expiration is a required field
Expiration *time.Time `type:"timestamp" required:"true"`
// The secret access key that can be used to sign requests.
//
// SecretAccessKey is a required field
SecretAccessKey *string `type:"string" required:"true"`
// The token that users must pass to the service API to use the temporary credentials.
//
// SessionToken is a required field
SessionToken *string `type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Credentials) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Credentials) GoString() string {
return s.String()
}
// SetAccessKeyId sets the AccessKeyId field's value.
func (s *Credentials) SetAccessKeyId(v string) *Credentials {
s.AccessKeyId = &v
return s
}
// SetExpiration sets the Expiration field's value.
func (s *Credentials) SetExpiration(v time.Time) *Credentials {
s.Expiration = &v
return s
}
// SetSecretAccessKey sets the SecretAccessKey field's value.
func (s *Credentials) SetSecretAccessKey(v string) *Credentials {
s.SecretAccessKey = &v
return s
}
// SetSessionToken sets the SessionToken field's value.
func (s *Credentials) SetSessionToken(v string) *Credentials {
s.SessionToken = &v
return s
}
type DecodeAuthorizationMessageInput struct {
_ struct{} `type:"structure"`
// The encoded message that was returned with the response.
//
// EncodedMessage is a required field
EncodedMessage *string `min:"1" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *DecodeAuthorizationMessageInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "DecodeAuthorizationMessageInput"}
if s.EncodedMessage == nil {
invalidParams.Add(request.NewErrParamRequired("EncodedMessage"))
}
if s.EncodedMessage != nil && len(*s.EncodedMessage) < 1 {
invalidParams.Add(request.NewErrParamMinLen("EncodedMessage", 1))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetEncodedMessage sets the EncodedMessage field's value.
func (s *DecodeAuthorizationMessageInput) SetEncodedMessage(v string) *DecodeAuthorizationMessageInput {
s.EncodedMessage = &v
return s
}
// A document that contains additional information about the authorization status
// of a request from an encoded message that is returned in response to an Amazon
// Web Services request.
type DecodeAuthorizationMessageOutput struct {
_ struct{} `type:"structure"`
// The API returns a response with the decoded message.
DecodedMessage *string `type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s DecodeAuthorizationMessageOutput) GoString() string {
return s.String()
}
// SetDecodedMessage sets the DecodedMessage field's value.
func (s *DecodeAuthorizationMessageOutput) SetDecodedMessage(v string) *DecodeAuthorizationMessageOutput {
s.DecodedMessage = &v
return s
}
// Identifiers for the federated user that is associated with the credentials.
type FederatedUser struct {
_ struct{} `type:"structure"`
// The ARN that specifies the federated user that is associated with the credentials.
// For more information about ARNs and how to use them in policies, see IAM
// Identifiers (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html)
// in the IAM User Guide.
//
// Arn is a required field
Arn *string `min:"20" type:"string" required:"true"`
// The string that identifies the federated user associated with the credentials,
// similar to the unique ID of an IAM user.
//
// FederatedUserId is a required field
FederatedUserId *string `min:"2" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s FederatedUser) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s FederatedUser) GoString() string {
return s.String()
}
// SetArn sets the Arn field's value.
func (s *FederatedUser) SetArn(v string) *FederatedUser {
s.Arn = &v
return s
}
// SetFederatedUserId sets the FederatedUserId field's value.
func (s *FederatedUser) SetFederatedUserId(v string) *FederatedUser {
s.FederatedUserId = &v
return s
}
type GetAccessKeyInfoInput struct {
_ struct{} `type:"structure"`
// The identifier of an access key.
//
// This parameter allows (through its regex pattern) a string of characters
// that can consist of any upper- or lowercase letter or digit.
//
// AccessKeyId is a required field
AccessKeyId *string `min:"16" type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetAccessKeyInfoInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetAccessKeyInfoInput"}
if s.AccessKeyId == nil {
invalidParams.Add(request.NewErrParamRequired("AccessKeyId"))
}
if s.AccessKeyId != nil && len(*s.AccessKeyId) < 16 {
invalidParams.Add(request.NewErrParamMinLen("AccessKeyId", 16))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetAccessKeyId sets the AccessKeyId field's value.
func (s *GetAccessKeyInfoInput) SetAccessKeyId(v string) *GetAccessKeyInfoInput {
s.AccessKeyId = &v
return s
}
type GetAccessKeyInfoOutput struct {
_ struct{} `type:"structure"`
// The number used to identify the Amazon Web Services account.
Account *string `type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetAccessKeyInfoOutput) GoString() string {
return s.String()
}
// SetAccount sets the Account field's value.
func (s *GetAccessKeyInfoOutput) SetAccount(v string) *GetAccessKeyInfoOutput {
s.Account = &v
return s
}
type GetCallerIdentityInput struct {
_ struct{} `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityInput) GoString() string {
return s.String()
}
// Contains the response to a successful GetCallerIdentity request, including
// information about the entity making the request.
type GetCallerIdentityOutput struct {
_ struct{} `type:"structure"`
// The Amazon Web Services account ID number of the account that owns or contains
// the calling entity.
Account *string `type:"string"`
// The Amazon Web Services ARN associated with the calling entity.
Arn *string `min:"20" type:"string"`
// The unique identifier of the calling entity. The exact value depends on the
// type of entity that is making the call. The values returned are those listed
// in the aws:userid column in the Principal table (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#principaltable)
// found on the Policy Variables reference page in the IAM User Guide.
UserId *string `type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetCallerIdentityOutput) GoString() string {
return s.String()
}
// SetAccount sets the Account field's value.
func (s *GetCallerIdentityOutput) SetAccount(v string) *GetCallerIdentityOutput {
s.Account = &v
return s
}
// SetArn sets the Arn field's value.
func (s *GetCallerIdentityOutput) SetArn(v string) *GetCallerIdentityOutput {
s.Arn = &v
return s
}
// SetUserId sets the UserId field's value.
func (s *GetCallerIdentityOutput) SetUserId(v string) *GetCallerIdentityOutput {
s.UserId = &v
return s
}
type GetFederationTokenInput struct {
_ struct{} `type:"structure"`
// The duration, in seconds, that the session should last. Acceptable durations
// for federation sessions range from 900 seconds (15 minutes) to 129,600 seconds
// (36 hours), with 43,200 seconds (12 hours) as the default. Sessions obtained
// using Amazon Web Services account root user credentials are restricted to
// a maximum of 3,600 seconds (one hour). If the specified duration is longer
// than one hour, the session obtained by using root user credentials defaults
// to one hour.
DurationSeconds *int64 `min:"900" type:"integer"`
// The name of the federated user. The name is used as an identifier for the
// temporary security credentials (such as Bob). For example, you can reference
// the federated user name in a resource-based policy, such as in an Amazon
// S3 bucket policy.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@-
//
// Name is a required field
Name *string `min:"2" type:"string" required:"true"`
// An IAM policy in JSON format that you want to use as an inline session policy.
//
// You must pass an inline or managed session policy (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies.
//
// This parameter is optional. However, if you do not pass any session policies,
// then the resulting federated user session has no permissions.
//
// When you pass session policies, the session permissions are the intersection
// of the IAM user policies and the session policies that you pass. This gives
// you a way to further restrict the permissions for a federated user. You cannot
// use session policies to grant more permissions than those that are defined
// in the permissions policy of the IAM user. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// The resulting credentials can be used to access a resource that has a resource-based
// policy. If that policy specifically references the federated user session
// in the Principal element of the policy, the session has the permissions allowed
// by the policy. These permissions are granted in addition to the permissions
// that are granted by the session policies.
//
// The plaintext that you use for both inline and managed session policies can't
// exceed 2,048 characters. The JSON policy characters can be any ASCII character
// from the space character to the end of the valid character list (\u0020 through
// \u00FF). It can also include the tab (\u0009), linefeed (\u000A), and carriage
// return (\u000D) characters.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
Policy *string `min:"1" type:"string"`
// The Amazon Resource Names (ARNs) of the IAM managed policies that you want
// to use as a managed session policy. The policies must exist in the same account
// as the IAM user that is requesting federated access.
//
// You must pass an inline or managed session policy (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// to this operation. You can pass a single JSON policy document to use as an
// inline session policy. You can also specify up to 10 managed policies to
// use as managed session policies. The plaintext that you use for both inline
// and managed session policies can't exceed 2,048 characters. You can provide
// up to 10 managed policy ARNs. For more information about ARNs, see Amazon
// Resource Names (ARNs) and Amazon Web Services Service Namespaces (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference.
//
// This parameter is optional. However, if you do not pass any session policies,
// then the resulting federated user session has no permissions.
//
// When you pass session policies, the session permissions are the intersection
// of the IAM user policies and the session policies that you pass. This gives
// you a way to further restrict the permissions for a federated user. You cannot
// use session policies to grant more permissions than those that are defined
// in the permissions policy of the IAM user. For more information, see Session
// Policies (https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session)
// in the IAM User Guide.
//
// The resulting credentials can be used to access a resource that has a resource-based
// policy. If that policy specifically references the federated user session
// in the Principal element of the policy, the session has the permissions allowed
// by the policy. These permissions are granted in addition to the permissions
// that are granted by the session policies.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
PolicyArns []*PolicyDescriptorType `type:"list"`
// A list of session tags. Each session tag consists of a key name and an associated
// value. For more information about session tags, see Passing Session Tags
// in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// This parameter is optional. You can pass up to 50 session tags. The plaintext
// session tag keys can’t exceed 128 characters and the values can’t exceed
// 256 characters. For these and additional limits, see IAM and STS Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// An Amazon Web Services conversion compresses the passed session policies
// and session tags into a packed binary format that has a separate limit. Your
// request can fail for this limit even if your plaintext meets the other requirements.
// The PackedPolicySize response element indicates by percentage how close the
// policies and tags for your request are to the upper size limit.
//
// You can pass a session tag with the same key as a tag that is already attached
// to the user you are federating. When you do, session tags override a user
// tag with the same key.
//
// Tag key–value pairs are not case sensitive, but case is preserved. This
// means that you cannot have separate Department and department tag keys. Assume
// that the role has the Department=Marketing tag and you pass the department=engineering
// session tag. Department and department are not saved as separate tags, and
// the session tag passed in the request takes precedence over the role tag.
Tags []*Tag `type:"list"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetFederationTokenInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetFederationTokenInput"}
if s.DurationSeconds != nil && *s.DurationSeconds < 900 {
invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900))
}
if s.Name == nil {
invalidParams.Add(request.NewErrParamRequired("Name"))
}
if s.Name != nil && len(*s.Name) < 2 {
invalidParams.Add(request.NewErrParamMinLen("Name", 2))
}
if s.Policy != nil && len(*s.Policy) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Policy", 1))
}
if s.PolicyArns != nil {
for i, v := range s.PolicyArns {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "PolicyArns", i), err.(request.ErrInvalidParams))
}
}
}
if s.Tags != nil {
for i, v := range s.Tags {
if v == nil {
continue
}
if err := v.Validate(); err != nil {
invalidParams.AddNested(fmt.Sprintf("%s[%v]", "Tags", i), err.(request.ErrInvalidParams))
}
}
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDurationSeconds sets the DurationSeconds field's value.
func (s *GetFederationTokenInput) SetDurationSeconds(v int64) *GetFederationTokenInput {
s.DurationSeconds = &v
return s
}
// SetName sets the Name field's value.
func (s *GetFederationTokenInput) SetName(v string) *GetFederationTokenInput {
s.Name = &v
return s
}
// SetPolicy sets the Policy field's value.
func (s *GetFederationTokenInput) SetPolicy(v string) *GetFederationTokenInput {
s.Policy = &v
return s
}
// SetPolicyArns sets the PolicyArns field's value.
func (s *GetFederationTokenInput) SetPolicyArns(v []*PolicyDescriptorType) *GetFederationTokenInput {
s.PolicyArns = v
return s
}
// SetTags sets the Tags field's value.
func (s *GetFederationTokenInput) SetTags(v []*Tag) *GetFederationTokenInput {
s.Tags = v
return s
}
// Contains the response to a successful GetFederationToken request, including
// temporary Amazon Web Services credentials that can be used to make Amazon
// Web Services requests.
type GetFederationTokenOutput struct {
_ struct{} `type:"structure"`
// The temporary security credentials, which include an access key ID, a secret
// access key, and a security (or session) token.
//
// The size of the security token that STS API operations return is not fixed.
// We strongly recommend that you make no assumptions about the maximum size.
Credentials *Credentials `type:"structure"`
// Identifiers for the federated user associated with the credentials (such
// as arn:aws:sts::123456789012:federated-user/Bob or 123456789012:Bob). You
// can use the federated user's ARN in your resource-based policies, such as
// an Amazon S3 bucket policy.
FederatedUser *FederatedUser `type:"structure"`
// A percentage value that indicates the packed size of the session policies
// and session tags combined passed in the request. The request fails if the
// packed size is greater than 100 percent, which means the policies and tags
// exceeded the allowed space.
PackedPolicySize *int64 `type:"integer"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetFederationTokenOutput) GoString() string {
return s.String()
}
// SetCredentials sets the Credentials field's value.
func (s *GetFederationTokenOutput) SetCredentials(v *Credentials) *GetFederationTokenOutput {
s.Credentials = v
return s
}
// SetFederatedUser sets the FederatedUser field's value.
func (s *GetFederationTokenOutput) SetFederatedUser(v *FederatedUser) *GetFederationTokenOutput {
s.FederatedUser = v
return s
}
// SetPackedPolicySize sets the PackedPolicySize field's value.
func (s *GetFederationTokenOutput) SetPackedPolicySize(v int64) *GetFederationTokenOutput {
s.PackedPolicySize = &v
return s
}
type GetSessionTokenInput struct {
_ struct{} `type:"structure"`
// The duration, in seconds, that the credentials should remain valid. Acceptable
// durations for IAM user sessions range from 900 seconds (15 minutes) to 129,600
// seconds (36 hours), with 43,200 seconds (12 hours) as the default. Sessions
// for Amazon Web Services account owners are restricted to a maximum of 3,600
// seconds (one hour). If the duration is longer than one hour, the session
// for Amazon Web Services account owners defaults to one hour.
DurationSeconds *int64 `min:"900" type:"integer"`
// The identification number of the MFA device that is associated with the IAM
// user who is making the GetSessionToken call. Specify this value if the IAM
// user has a policy that requires MFA authentication. The value is either the
// serial number for a hardware device (such as GAHT12345678) or an Amazon Resource
// Name (ARN) for a virtual device (such as arn:aws:iam::123456789012:mfa/user).
// You can find the device for an IAM user by going to the Amazon Web Services
// Management Console and viewing the user's security credentials.
//
// The regex used to validate this parameter is a string of characters consisting
// of upper- and lower-case alphanumeric characters with no spaces. You can
// also include underscores or any of the following characters: =,.@:/-
SerialNumber *string `min:"9" type:"string"`
// The value provided by the MFA device, if MFA is required. If any policy requires
// the IAM user to submit an MFA code, specify this value. If MFA authentication
// is required, the user must provide a code when requesting a set of temporary
// security credentials. A user who fails to provide the code receives an "access
// denied" response when requesting resources that require MFA authentication.
//
// The format for this parameter, as described by its regex pattern, is a sequence
// of six numeric digits.
TokenCode *string `min:"6" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenInput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenInput) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *GetSessionTokenInput) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "GetSessionTokenInput"}
if s.DurationSeconds != nil && *s.DurationSeconds < 900 {
invalidParams.Add(request.NewErrParamMinValue("DurationSeconds", 900))
}
if s.SerialNumber != nil && len(*s.SerialNumber) < 9 {
invalidParams.Add(request.NewErrParamMinLen("SerialNumber", 9))
}
if s.TokenCode != nil && len(*s.TokenCode) < 6 {
invalidParams.Add(request.NewErrParamMinLen("TokenCode", 6))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetDurationSeconds sets the DurationSeconds field's value.
func (s *GetSessionTokenInput) SetDurationSeconds(v int64) *GetSessionTokenInput {
s.DurationSeconds = &v
return s
}
// SetSerialNumber sets the SerialNumber field's value.
func (s *GetSessionTokenInput) SetSerialNumber(v string) *GetSessionTokenInput {
s.SerialNumber = &v
return s
}
// SetTokenCode sets the TokenCode field's value.
func (s *GetSessionTokenInput) SetTokenCode(v string) *GetSessionTokenInput {
s.TokenCode = &v
return s
}
// Contains the response to a successful GetSessionToken request, including
// temporary Amazon Web Services credentials that can be used to make Amazon
// Web Services requests.
type GetSessionTokenOutput struct {
_ struct{} `type:"structure"`
// The temporary security credentials, which include an access key ID, a secret
// access key, and a security (or session) token.
//
// The size of the security token that STS API operations return is not fixed.
// We strongly recommend that you make no assumptions about the maximum size.
Credentials *Credentials `type:"structure"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenOutput) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s GetSessionTokenOutput) GoString() string {
return s.String()
}
// SetCredentials sets the Credentials field's value.
func (s *GetSessionTokenOutput) SetCredentials(v *Credentials) *GetSessionTokenOutput {
s.Credentials = v
return s
}
// A reference to the IAM managed policy that is passed as a session policy
// for a role session or a federated user session.
type PolicyDescriptorType struct {
_ struct{} `type:"structure"`
// The Amazon Resource Name (ARN) of the IAM managed policy to use as a session
// policy for the role. For more information about ARNs, see Amazon Resource
// Names (ARNs) and Amazon Web Services Service Namespaces (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html)
// in the Amazon Web Services General Reference.
Arn *string `locationName:"arn" min:"20" type:"string"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PolicyDescriptorType) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s PolicyDescriptorType) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *PolicyDescriptorType) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "PolicyDescriptorType"}
if s.Arn != nil && len(*s.Arn) < 20 {
invalidParams.Add(request.NewErrParamMinLen("Arn", 20))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetArn sets the Arn field's value.
func (s *PolicyDescriptorType) SetArn(v string) *PolicyDescriptorType {
s.Arn = &v
return s
}
// You can pass custom key-value pair attributes when you assume a role or federate
// a user. These are called session tags. You can then use the session tags
// to control access to resources. For more information, see Tagging Amazon
// Web Services STS Sessions (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
type Tag struct {
_ struct{} `type:"structure"`
// The key for a session tag.
//
// You can pass up to 50 session tags. The plain text session tag keys can’t
// exceed 128 characters. For these and additional limits, see IAM and STS Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// Key is a required field
Key *string `min:"1" type:"string" required:"true"`
// The value for a session tag.
//
// You can pass up to 50 session tags. The plain text session tag values can’t
// exceed 256 characters. For these and additional limits, see IAM and STS Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-limits.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
//
// Value is a required field
Value *string `type:"string" required:"true"`
}
// String returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) String() string {
return awsutil.Prettify(s)
}
// GoString returns the string representation.
//
// API parameter values that are decorated as "sensitive" in the API will not
// be included in the string output. The member name will be present, but the
// value will be replaced with "sensitive".
func (s Tag) GoString() string {
return s.String()
}
// Validate inspects the fields of the type to determine if they are valid.
func (s *Tag) Validate() error {
invalidParams := request.ErrInvalidParams{Context: "Tag"}
if s.Key == nil {
invalidParams.Add(request.NewErrParamRequired("Key"))
}
if s.Key != nil && len(*s.Key) < 1 {
invalidParams.Add(request.NewErrParamMinLen("Key", 1))
}
if s.Value == nil {
invalidParams.Add(request.NewErrParamRequired("Value"))
}
if invalidParams.Len() > 0 {
return invalidParams
}
return nil
}
// SetKey sets the Key field's value.
func (s *Tag) SetKey(v string) *Tag {
s.Key = &v
return s
}
// SetValue sets the Value field's value.
func (s *Tag) SetValue(v string) *Tag {
s.Value = &v
return s
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/customizations.go
================================================
package sts
import "github.com/aws/aws-sdk-go/aws/request"
func init() {
initRequest = customizeRequest
}
func customizeRequest(r *request.Request) {
r.RetryErrorCodes = append(r.RetryErrorCodes, ErrCodeIDPCommunicationErrorException)
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/doc.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package sts provides the client and types for making API
// requests to AWS Security Token Service.
//
// Security Token Service (STS) enables you to request temporary, limited-privilege
// credentials for Identity and Access Management (IAM) users or for users that
// you authenticate (federated users). This guide provides descriptions of the
// STS API. For more information about using this service, see Temporary Security
// Credentials (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html).
//
// See https://docs.aws.amazon.com/goto/WebAPI/sts-2011-06-15 for more information on this service.
//
// See sts package documentation for more information.
// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/
//
// Using the Client
//
// To contact AWS Security Token Service with the SDK use the New function to create
// a new service client. With that client you can make API requests to the service.
// These clients are safe to use concurrently.
//
// See the SDK's documentation for more information on how to use the SDK.
// https://docs.aws.amazon.com/sdk-for-go/api/
//
// See aws.Config documentation for more information on configuring SDK clients.
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
//
// See the AWS Security Token Service client STS for more
// information on creating client for this service.
// https://docs.aws.amazon.com/sdk-for-go/api/service/sts/#New
package sts
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/errors.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sts
const (
// ErrCodeExpiredTokenException for service response error code
// "ExpiredTokenException".
//
// The web identity token that was passed is expired or is not valid. Get a
// new identity token from the identity provider and then retry the request.
ErrCodeExpiredTokenException = "ExpiredTokenException"
// ErrCodeIDPCommunicationErrorException for service response error code
// "IDPCommunicationError".
//
// The request could not be fulfilled because the identity provider (IDP) that
// was asked to verify the incoming identity token could not be reached. This
// is often a transient error caused by network conditions. Retry the request
// a limited number of times so that you don't exceed the request rate. If the
// error persists, the identity provider might be down or not responding.
ErrCodeIDPCommunicationErrorException = "IDPCommunicationError"
// ErrCodeIDPRejectedClaimException for service response error code
// "IDPRejectedClaim".
//
// The identity provider (IdP) reported that authentication failed. This might
// be because the claim is invalid.
//
// If this error is returned for the AssumeRoleWithWebIdentity operation, it
// can also mean that the claim has expired or has been explicitly revoked.
ErrCodeIDPRejectedClaimException = "IDPRejectedClaim"
// ErrCodeInvalidAuthorizationMessageException for service response error code
// "InvalidAuthorizationMessageException".
//
// The error returned if the message passed to DecodeAuthorizationMessage was
// invalid. This can happen if the token contains invalid characters, such as
// linebreaks.
ErrCodeInvalidAuthorizationMessageException = "InvalidAuthorizationMessageException"
// ErrCodeInvalidIdentityTokenException for service response error code
// "InvalidIdentityToken".
//
// The web identity token that was passed could not be validated by Amazon Web
// Services. Get a new identity token from the identity provider and then retry
// the request.
ErrCodeInvalidIdentityTokenException = "InvalidIdentityToken"
// ErrCodeMalformedPolicyDocumentException for service response error code
// "MalformedPolicyDocument".
//
// The request was rejected because the policy document was malformed. The error
// message describes the specific error.
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument"
// ErrCodePackedPolicyTooLargeException for service response error code
// "PackedPolicyTooLarge".
//
// The request was rejected because the total packed size of the session policies
// and session tags combined was too large. An Amazon Web Services conversion
// compresses the session policy document, session policy ARNs, and session
// tags into a packed binary format that has a separate limit. The error message
// indicates by percentage how close the policies and tags are to the upper
// size limit. For more information, see Passing Session Tags in STS (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html)
// in the IAM User Guide.
//
// You could receive this error even though you meet other defined session policy
// and session tag limits. For more information, see IAM and STS Entity Character
// Limits (https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_iam-quotas.html#reference_iam-limits-entity-length)
// in the IAM User Guide.
ErrCodePackedPolicyTooLargeException = "PackedPolicyTooLarge"
// ErrCodeRegionDisabledException for service response error code
// "RegionDisabledException".
//
// STS is not activated in the requested region for the account that is being
// asked to generate credentials. The account administrator must use the IAM
// console to activate STS in that region. For more information, see Activating
// and Deactivating Amazon Web Services STS in an Amazon Web Services Region
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html)
// in the IAM User Guide.
ErrCodeRegionDisabledException = "RegionDisabledException"
)
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/service.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
package sts
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
)
// STS provides the API operation methods for making requests to
// AWS Security Token Service. See this package's package overview docs
// for details on the service.
//
// STS methods are safe to use concurrently. It is not safe to
// modify mutate any of the struct's properties though.
type STS struct {
*client.Client
}
// Used for custom client initialization logic
var initClient func(*client.Client)
// Used for custom request initialization logic
var initRequest func(*request.Request)
// Service information constants
const (
ServiceName = "sts" // Name of service.
EndpointsID = ServiceName // ID to lookup a service endpoint with.
ServiceID = "STS" // ServiceID is a unique identifier of a specific service.
)
// New creates a new instance of the STS client with a session.
// If additional configuration is needed for the client instance use the optional
// aws.Config parameter to add your extra config.
//
// Example:
// mySession := session.Must(session.NewSession())
//
// // Create a STS client from just a session.
// svc := sts.New(mySession)
//
// // Create a STS client with additional configuration
// svc := sts.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
func New(p client.ConfigProvider, cfgs ...*aws.Config) *STS {
c := p.ClientConfig(EndpointsID, cfgs...)
if c.SigningNameDerived || len(c.SigningName) == 0 {
c.SigningName = EndpointsID
// No Fallback
}
return newClient(*c.Config, c.Handlers, c.PartitionID, c.Endpoint, c.SigningRegion, c.SigningName, c.ResolvedRegion)
}
// newClient creates, initializes and returns a new service client instance.
func newClient(cfg aws.Config, handlers request.Handlers, partitionID, endpoint, signingRegion, signingName, resolvedRegion string) *STS {
svc := &STS{
Client: client.New(
cfg,
metadata.ClientInfo{
ServiceName: ServiceName,
ServiceID: ServiceID,
SigningName: signingName,
SigningRegion: signingRegion,
PartitionID: partitionID,
Endpoint: endpoint,
APIVersion: "2011-06-15",
ResolvedRegion: resolvedRegion,
},
handlers,
),
}
// Handlers
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
svc.Handlers.Build.PushBackNamed(query.BuildHandler)
svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler)
svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
// Run custom client initialization if present
if initClient != nil {
initClient(svc.Client)
}
return svc
}
// newRequest creates a new request for a STS operation and runs any
// custom request initialization.
func (c *STS) newRequest(op *request.Operation, params, data interface{}) *request.Request {
req := c.NewRequest(op, params, data)
// Run custom request initialization if present
if initRequest != nil {
initRequest(req)
}
return req
}
================================================
FILE: vendor/github.com/aws/aws-sdk-go/service/sts/stsiface/interface.go
================================================
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
// Package stsiface provides an interface to enable mocking the AWS Security Token Service service client
// for testing your code.
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters.
package stsiface
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/sts"
)
// STSAPI provides an interface to enable mocking the
// sts.STS service client's API operation,
// paginators, and waiters. This make unit testing your code that calls out
// to the SDK's service client's calls easier.
//
// The best way to use this interface is so the SDK's service client's calls
// can be stubbed out for unit testing your code with the SDK without needing
// to inject custom request handlers into the SDK's request pipeline.
//
// // myFunc uses an SDK service client to make a request to
// // AWS Security Token Service.
// func myFunc(svc stsiface.STSAPI) bool {
// // Make svc.AssumeRole request
// }
//
// func main() {
// sess := session.New()
// svc := sts.New(sess)
//
// myFunc(svc)
// }
//
// In your _test.go file:
//
// // Define a mock struct to be used in your unit tests of myFunc.
// type mockSTSClient struct {
// stsiface.STSAPI
// }
// func (m *mockSTSClient) AssumeRole(input *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
// // mock response/functionality
// }
//
// func TestMyFunc(t *testing.T) {
// // Setup Test
// mockSvc := &mockSTSClient{}
//
// myfunc(mockSvc)
//
// // Verify myFunc's functionality
// }
//
// It is important to note that this interface will have breaking changes
// when the service model is updated and adds new API operations, paginators,
// and waiters. Its suggested to use the pattern above for testing, or using
// tooling to generate mocks to satisfy the interfaces.
type STSAPI interface {
AssumeRole(*sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error)
AssumeRoleWithContext(aws.Context, *sts.AssumeRoleInput, ...request.Option) (*sts.AssumeRoleOutput, error)
AssumeRoleRequest(*sts.AssumeRoleInput) (*request.Request, *sts.AssumeRoleOutput)
AssumeRoleWithSAML(*sts.AssumeRoleWithSAMLInput) (*sts.AssumeRoleWithSAMLOutput, error)
AssumeRoleWithSAMLWithContext(aws.Context, *sts.AssumeRoleWithSAMLInput, ...request.Option) (*sts.AssumeRoleWithSAMLOutput, error)
AssumeRoleWithSAMLRequest(*sts.AssumeRoleWithSAMLInput) (*request.Request, *sts.AssumeRoleWithSAMLOutput)
AssumeRoleWithWebIdentity(*sts.AssumeRoleWithWebIdentityInput) (*sts.AssumeRoleWithWebIdentityOutput, error)
AssumeRoleWithWebIdentityWithContext(aws.Context, *sts.AssumeRoleWithWebIdentityInput, ...request.Option) (*sts.AssumeRoleWithWebIdentityOutput, error)
AssumeRoleWithWebIdentityRequest(*sts.AssumeRoleWithWebIdentityInput) (*request.Request, *sts.AssumeRoleWithWebIdentityOutput)
DecodeAuthorizationMessage(*sts.DecodeAuthorizationMessageInput) (*sts.DecodeAuthorizationMessageOutput, error)
DecodeAuthorizationMessageWithContext(aws.Context, *sts.DecodeAuthorizationMessageInput, ...request.Option) (*sts.DecodeAuthorizationMessageOutput, error)
DecodeAuthorizationMessageRequest(*sts.DecodeAuthorizationMessageInput) (*request.Request, *sts.DecodeAuthorizationMessageOutput)
GetAccessKeyInfo(*sts.GetAccessKeyInfoInput) (*sts.GetAccessKeyInfoOutput, error)
GetAccessKeyInfoWithContext(aws.Context, *sts.GetAccessKeyInfoInput, ...request.Option) (*sts.GetAccessKeyInfoOutput, error)
GetAccessKeyInfoRequest(*sts.GetAccessKeyInfoInput) (*request.Request, *sts.GetAccessKeyInfoOutput)
GetCallerIdentity(*sts.GetCallerIdentityInput) (*sts.GetCallerIdentityOutput, error)
GetCallerIdentityWithContext(aws.Context, *sts.GetCallerIdentityInput, ...request.Option) (*sts.GetCallerIdentityOutput, error)
GetCallerIdentityRequest(*sts.GetCallerIdentityInput) (*request.Request, *sts.GetCallerIdentityOutput)
GetFederationToken(*sts.GetFederationTokenInput) (*sts.GetFederationTokenOutput, error)
GetFederationTokenWithContext(aws.Context, *sts.GetFederationTokenInput, ...request.Option) (*sts.GetFederationTokenOutput, error)
GetFederationTokenRequest(*sts.GetFederationTokenInput) (*request.Request, *sts.GetFederationTokenOutput)
GetSessionToken(*sts.GetSessionTokenInput) (*sts.GetSessionTokenOutput, error)
GetSessionTokenWithContext(aws.Context, *sts.GetSessionTokenInput, ...request.Option) (*sts.GetSessionTokenOutput, error)
GetSessionTokenRequest(*sts.GetSessionTokenInput) (*request.Request, *sts.GetSessionTokenOutput)
}
var _ STSAPI = (*sts.STS)(nil)
================================================
FILE: vendor/github.com/blang/semver/.travis.yml
================================================
language: go
matrix:
include:
- go: 1.4.3
- go: 1.5.4
- go: 1.6.3
- go: 1.7
- go: tip
allow_failures:
- go: tip
install:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
script:
- echo "Test and track coverage" ; $HOME/gopath/bin/goveralls -package "." -service=travis-ci
-repotoken $COVERALLS_TOKEN
- echo "Build examples" ; cd examples && go build
- echo "Check if gofmt'd" ; diff -u <(echo -n) <(gofmt -d -s .)
env:
global:
secure: HroGEAUQpVq9zX1b1VIkraLiywhGbzvNnTZq2TMxgK7JHP8xqNplAeF1izrR2i4QLL9nsY+9WtYss4QuPvEtZcVHUobw6XnL6radF7jS1LgfYZ9Y7oF+zogZ2I5QUMRLGA7rcxQ05s7mKq3XZQfeqaNts4bms/eZRefWuaFZbkw=
================================================
FILE: vendor/github.com/blang/semver/LICENSE
================================================
The MIT License
Copyright (c) 2014 Benedikt Lang
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: vendor/github.com/blang/semver/README.md
================================================
semver for golang [](https://travis-ci.org/blang/semver) [](https://godoc.org/github.com/blang/semver) [](https://coveralls.io/r/blang/semver?branch=master)
======
semver is a [Semantic Versioning](http://semver.org/) library written in golang. It fully covers spec version `2.0.0`.
Usage
-----
```bash
$ go get github.com/blang/semver
```
Note: Always vendor your dependencies or fix on a specific version tag.
```go
import github.com/blang/semver
v1, err := semver.Make("1.0.0-beta")
v2, err := semver.Make("2.0.0-beta")
v1.Compare(v2)
```
Also check the [GoDocs](http://godoc.org/github.com/blang/semver).
Why should I use this lib?
-----
- Fully spec compatible
- No reflection
- No regex
- Fully tested (Coverage >99%)
- Readable parsing/validation errors
- Fast (See [Benchmarks](#benchmarks))
- Only Stdlib
- Uses values instead of pointers
- Many features, see below
Features
-----
- Parsing and validation at all levels
- Comparator-like comparisons
- Compare Helper Methods
- InPlace manipulation
- Ranges `>=1.0.0 <2.0.0 || >=3.0.0 !3.0.1-beta.1`
- Wildcards `>=1.x`, `<=2.5.x`
- Sortable (implements sort.Interface)
- database/sql compatible (sql.Scanner/Valuer)
- encoding/json compatible (json.Marshaler/Unmarshaler)
Ranges
------
A `Range` is a set of conditions which specify which versions satisfy the range.
A condition is composed of an operator and a version. The supported operators are:
- `<1.0.0` Less than `1.0.0`
- `<=1.0.0` Less than or equal to `1.0.0`
- `>1.0.0` Greater than `1.0.0`
- `>=1.0.0` Greater than or equal to `1.0.0`
- `1.0.0`, `=1.0.0`, `==1.0.0` Equal to `1.0.0`
- `!1.0.0`, `!=1.0.0` Not equal to `1.0.0`. Excludes version `1.0.0`.
Note that spaces between the operator and the version will be gracefully tolerated.
A `Range` can link multiple `Ranges` separated by space:
Ranges can be linked by logical AND:
- `>1.0.0 <2.0.0` would match between both ranges, so `1.1.1` and `1.8.7` but not `1.0.0` or `2.0.0`
- `>1.0.0 <3.0.0 !2.0.3-beta.2` would match every version between `1.0.0` and `3.0.0` except `2.0.3-beta.2`
Ranges can also be linked by logical OR:
- `<2.0.0 || >=3.0.0` would match `1.x.x` and `3.x.x` but not `2.x.x`
AND has a higher precedence than OR. It's not possible to use brackets.
Ranges can be combined by both AND and OR
- `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
Range usage:
```
v, err := semver.Parse("1.2.3")
range, err := semver.ParseRange(">1.0.0 <2.0.0 || >=3.0.0")
if range(v) {
//valid
}
```
Example
-----
Have a look at full examples in [examples/main.go](examples/main.go)
```go
import github.com/blang/semver
v, err := semver.Make("0.0.1-alpha.preview+123.github")
fmt.Printf("Major: %d\n", v.Major)
fmt.Printf("Minor: %d\n", v.Minor)
fmt.Printf("Patch: %d\n", v.Patch)
fmt.Printf("Pre: %s\n", v.Pre)
fmt.Printf("Build: %s\n", v.Build)
// Prerelease versions array
if len(v.Pre) > 0 {
fmt.Println("Prerelease versions:")
for i, pre := range v.Pre {
fmt.Printf("%d: %q\n", i, pre)
}
}
// Build meta data array
if len(v.Build) > 0 {
fmt.Println("Build meta data:")
for i, build := range v.Build {
fmt.Printf("%d: %q\n", i, build)
}
}
v001, err := semver.Make("0.0.1")
// Compare using helpers: v.GT(v2), v.LT, v.GTE, v.LTE
v001.GT(v) == true
v.LT(v001) == true
v.GTE(v) == true
v.LTE(v) == true
// Or use v.Compare(v2) for comparisons (-1, 0, 1):
v001.Compare(v) == 1
v.Compare(v001) == -1
v.Compare(v) == 0
// Manipulate Version in place:
v.Pre[0], err = semver.NewPRVersion("beta")
if err != nil {
fmt.Printf("Error parsing pre release version: %q", err)
}
fmt.Println("\nValidate versions:")
v.Build[0] = "?"
err = v.Validate()
if err != nil {
fmt.Printf("Validation failed: %s\n", err)
}
```
Benchmarks
-----
BenchmarkParseSimple-4 5000000 390 ns/op 48 B/op 1 allocs/op
BenchmarkParseComplex-4 1000000 1813 ns/op 256 B/op 7 allocs/op
BenchmarkParseAverage-4 1000000 1171 ns/op 163 B/op 4 allocs/op
BenchmarkStringSimple-4 20000000 119 ns/op 16 B/op 1 allocs/op
BenchmarkStringLarger-4 10000000 206 ns/op 32 B/op 2 allocs/op
BenchmarkStringComplex-4 5000000 324 ns/op 80 B/op 3 allocs/op
BenchmarkStringAverage-4 5000000 273 ns/op 53 B/op 2 allocs/op
BenchmarkValidateSimple-4 200000000 9.33 ns/op 0 B/op 0 allocs/op
BenchmarkValidateComplex-4 3000000 469 ns/op 0 B/op 0 allocs/op
BenchmarkValidateAverage-4 5000000 256 ns/op 0 B/op 0 allocs/op
BenchmarkCompareSimple-4 100000000 11.8 ns/op 0 B/op 0 allocs/op
BenchmarkCompareComplex-4 50000000 30.8 ns/op 0 B/op 0 allocs/op
BenchmarkCompareAverage-4 30000000 41.5 ns/op 0 B/op 0 allocs/op
BenchmarkSort-4 3000000 419 ns/op 256 B/op 2 allocs/op
BenchmarkRangeParseSimple-4 2000000 850 ns/op 192 B/op 5 allocs/op
BenchmarkRangeParseAverage-4 1000000 1677 ns/op 400 B/op 10 allocs/op
BenchmarkRangeParseComplex-4 300000 5214 ns/op 1440 B/op 30 allocs/op
BenchmarkRangeMatchSimple-4 50000000 25.6 ns/op 0 B/op 0 allocs/op
BenchmarkRangeMatchAverage-4 30000000 56.4 ns/op 0 B/op 0 allocs/op
BenchmarkRangeMatchComplex-4 10000000 153 ns/op 0 B/op 0 allocs/op
See benchmark cases at [semver_test.go](semver_test.go)
Motivation
-----
I simply couldn't find any lib supporting the full spec. Others were just wrong or used reflection and regex which i don't like.
Contribution
-----
Feel free to make a pull request. For bigger changes create a issue first to discuss about it.
License
-----
See [LICENSE](LICENSE) file.
================================================
FILE: vendor/github.com/blang/semver/json.go
================================================
package semver
import (
"encoding/json"
)
// MarshalJSON implements the encoding/json.Marshaler interface.
func (v Version) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
func (v *Version) UnmarshalJSON(data []byte) (err error) {
var versionString string
if err = json.Unmarshal(data, &versionString); err != nil {
return
}
*v, err = Parse(versionString)
return
}
================================================
FILE: vendor/github.com/blang/semver/package.json
================================================
{
"author": "blang",
"bugs": {
"URL": "https://github.com/blang/semver/issues",
"url": "https://github.com/blang/semver/issues"
},
"gx": {
"dvcsimport": "github.com/blang/semver"
},
"gxVersion": "0.10.0",
"language": "go",
"license": "MIT",
"name": "semver",
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
"version": "3.5.1"
}
================================================
FILE: vendor/github.com/blang/semver/range.go
================================================
package semver
import (
"fmt"
"strconv"
"strings"
"unicode"
)
type wildcardType int
const (
noneWildcard wildcardType = iota
majorWildcard wildcardType = 1
minorWildcard wildcardType = 2
patchWildcard wildcardType = 3
)
func wildcardTypefromInt(i int) wildcardType {
switch i {
case 1:
return majorWildcard
case 2:
return minorWildcard
case 3:
return patchWildcard
default:
return noneWildcard
}
}
type comparator func(Version, Version) bool
var (
compEQ comparator = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == 0
}
compNE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) != 0
}
compGT = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == 1
}
compGE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) >= 0
}
compLT = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) == -1
}
compLE = func(v1 Version, v2 Version) bool {
return v1.Compare(v2) <= 0
}
)
type versionRange struct {
v Version
c comparator
}
// rangeFunc creates a Range from the given versionRange.
func (vr *versionRange) rangeFunc() Range {
return Range(func(v Version) bool {
return vr.c(v, vr.v)
})
}
// Range represents a range of versions.
// A Range can be used to check if a Version satisfies it:
//
// range, err := semver.ParseRange(">1.0.0 <2.0.0")
// range(semver.MustParse("1.1.1") // returns true
type Range func(Version) bool
// OR combines the existing Range with another Range using logical OR.
func (rf Range) OR(f Range) Range {
return Range(func(v Version) bool {
return rf(v) || f(v)
})
}
// AND combines the existing Range with another Range using logical AND.
func (rf Range) AND(f Range) Range {
return Range(func(v Version) bool {
return rf(v) && f(v)
})
}
// ParseRange parses a range and returns a Range.
// If the range could not be parsed an error is returned.
//
// Valid ranges are:
// - "<1.0.0"
// - "<=1.0.0"
// - ">1.0.0"
// - ">=1.0.0"
// - "1.0.0", "=1.0.0", "==1.0.0"
// - "!1.0.0", "!=1.0.0"
//
// A Range can consist of multiple ranges separated by space:
// Ranges can be linked by logical AND:
// - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
// - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
//
// Ranges can also be linked by logical OR:
// - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
//
// AND has a higher precedence than OR. It's not possible to use brackets.
//
// Ranges can be combined by both AND and OR
//
// - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
func ParseRange(s string) (Range, error) {
parts := splitAndTrim(s)
orParts, err := splitORParts(parts)
if err != nil {
return nil, err
}
expandedParts, err := expandWildcardVersion(orParts)
if err != nil {
return nil, err
}
var orFn Range
for _, p := range expandedParts {
var andFn Range
for _, ap := range p {
opStr, vStr, err := splitComparatorVersion(ap)
if err != nil {
return nil, err
}
vr, err := buildVersionRange(opStr, vStr)
if err != nil {
return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
}
rf := vr.rangeFunc()
// Set function
if andFn == nil {
andFn = rf
} else { // Combine with existing function
andFn = andFn.AND(rf)
}
}
if orFn == nil {
orFn = andFn
} else {
orFn = orFn.OR(andFn)
}
}
return orFn, nil
}
// splitORParts splits the already cleaned parts by '||'.
// Checks for invalid positions of the operator and returns an
// error if found.
func splitORParts(parts []string) ([][]string, error) {
var ORparts [][]string
last := 0
for i, p := range parts {
if p == "||" {
if i == 0 {
return nil, fmt.Errorf("First element in range is '||'")
}
ORparts = append(ORparts, parts[last:i])
last = i + 1
}
}
if last == len(parts) {
return nil, fmt.Errorf("Last element in range is '||'")
}
ORparts = append(ORparts, parts[last:])
return ORparts, nil
}
// buildVersionRange takes a slice of 2: operator and version
// and builds a versionRange, otherwise an error.
func buildVersionRange(opStr, vStr string) (*versionRange, error) {
c := parseComparator(opStr)
if c == nil {
return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
}
v, err := Parse(vStr)
if err != nil {
return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
}
return &versionRange{
v: v,
c: c,
}, nil
}
// inArray checks if a byte is contained in an array of bytes
func inArray(s byte, list []byte) bool {
for _, el := range list {
if el == s {
return true
}
}
return false
}
// splitAndTrim splits a range string by spaces and cleans whitespaces
func splitAndTrim(s string) (result []string) {
last := 0
var lastChar byte
excludeFromSplit := []byte{'>', '<', '='}
for i := 0; i < len(s); i++ {
if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
if last < i-1 {
result = append(result, s[last:i])
}
last = i + 1
} else if s[i] != ' ' {
lastChar = s[i]
}
}
if last < len(s)-1 {
result = append(result, s[last:])
}
for i, v := range result {
result[i] = strings.Replace(v, " ", "", -1)
}
// parts := strings.Split(s, " ")
// for _, x := range parts {
// if s := strings.TrimSpace(x); len(s) != 0 {
// result = append(result, s)
// }
// }
return
}
// splitComparatorVersion splits the comparator from the version.
// Input must be free of leading or trailing spaces.
func splitComparatorVersion(s string) (string, string, error) {
i := strings.IndexFunc(s, unicode.IsDigit)
if i == -1 {
return "", "", fmt.Errorf("Could not get version from string: %q", s)
}
return strings.TrimSpace(s[0:i]), s[i:], nil
}
// getWildcardType will return the type of wildcard that the
// passed version contains
func getWildcardType(vStr string) wildcardType {
parts := strings.Split(vStr, ".")
nparts := len(parts)
wildcard := parts[nparts-1]
possibleWildcardType := wildcardTypefromInt(nparts)
if wildcard == "x" {
return possibleWildcardType
}
return noneWildcard
}
// createVersionFromWildcard will convert a wildcard version
// into a regular version, replacing 'x's with '0's, handling
// special cases like '1.x.x' and '1.x'
func createVersionFromWildcard(vStr string) string {
// handle 1.x.x
vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
parts := strings.Split(vStr2, ".")
// handle 1.x
if len(parts) == 2 {
return vStr2 + ".0"
}
return vStr2
}
// incrementMajorVersion will increment the major version
// of the passed version
func incrementMajorVersion(vStr string) (string, error) {
parts := strings.Split(vStr, ".")
i, err := strconv.Atoi(parts[0])
if err != nil {
return "", err
}
parts[0] = strconv.Itoa(i + 1)
return strings.Join(parts, "."), nil
}
// incrementMajorVersion will increment the minor version
// of the passed version
func incrementMinorVersion(vStr string) (string, error) {
parts := strings.Split(vStr, ".")
i, err := strconv.Atoi(parts[1])
if err != nil {
return "", err
}
parts[1] = strconv.Itoa(i + 1)
return strings.Join(parts, "."), nil
}
// expandWildcardVersion will expand wildcards inside versions
// following these rules:
//
// * when dealing with patch wildcards:
// >= 1.2.x will become >= 1.2.0
// <= 1.2.x will become < 1.3.0
// > 1.2.x will become >= 1.3.0
// < 1.2.x will become < 1.2.0
// != 1.2.x will become < 1.2.0 >= 1.3.0
//
// * when dealing with minor wildcards:
// >= 1.x will become >= 1.0.0
// <= 1.x will become < 2.0.0
// > 1.x will become >= 2.0.0
// < 1.0 will become < 1.0.0
// != 1.x will become < 1.0.0 >= 2.0.0
//
// * when dealing with wildcards without
// version operator:
// 1.2.x will become >= 1.2.0 < 1.3.0
// 1.x will become >= 1.0.0 < 2.0.0
func expandWildcardVersion(parts [][]string) ([][]string, error) {
var expandedParts [][]string
for _, p := range parts {
var newParts []string
for _, ap := range p {
if strings.Index(ap, "x") != -1 {
opStr, vStr, err := splitComparatorVersion(ap)
if err != nil {
return nil, err
}
versionWildcardType := getWildcardType(vStr)
flatVersion := createVersionFromWildcard(vStr)
var resultOperator string
var shouldIncrementVersion bool
switch opStr {
case ">":
resultOperator = ">="
shouldIncrementVersion = true
case ">=":
resultOperator = ">="
case "<":
resultOperator = "<"
case "<=":
resultOperator = "<"
shouldIncrementVersion = true
case "", "=", "==":
newParts = append(newParts, ">="+flatVersion)
resultOperator = "<"
shouldIncrementVersion = true
case "!=", "!":
newParts = append(newParts, "<"+flatVersion)
resultOperator = ">="
shouldIncrementVersion = true
}
var resultVersion string
if shouldIncrementVersion {
switch versionWildcardType {
case patchWildcard:
resultVersion, _ = incrementMinorVersion(flatVersion)
case minorWildcard:
resultVersion, _ = incrementMajorVersion(flatVersion)
}
} else {
resultVersion = flatVersion
}
ap = resultOperator + resultVersion
}
newParts = append(newParts, ap)
}
expandedParts = append(expandedParts, newParts)
}
return expandedParts, nil
}
func parseComparator(s string) comparator {
switch s {
case "==":
fallthrough
case "":
fallthrough
case "=":
return compEQ
case ">":
return compGT
case ">=":
return compGE
case "<":
return compLT
case "<=":
return compLE
case "!":
fallthrough
case "!=":
return compNE
}
return nil
}
// MustParseRange is like ParseRange but panics if the range cannot be parsed.
func MustParseRange(s string) Range {
r, err := ParseRange(s)
if err != nil {
panic(`semver: ParseRange(` + s + `): ` + err.Error())
}
return r
}
================================================
FILE: vendor/github.com/blang/semver/semver.go
================================================
package semver
import (
"errors"
"fmt"
"strconv"
"strings"
)
const (
numbers string = "0123456789"
alphas = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
alphanum = alphas + numbers
)
// SpecVersion is the latest fully supported spec version of semver
var SpecVersion = Version{
Major: 2,
Minor: 0,
Patch: 0,
}
// Version represents a semver compatible version
type Version struct {
Major uint64
Minor uint64
Patch uint64
Pre []PRVersion
Build []string //No Precendence
}
// Version to string
func (v Version) String() string {
b := make([]byte, 0, 5)
b = strconv.AppendUint(b, v.Major, 10)
b = append(b, '.')
b = strconv.AppendUint(b, v.Minor, 10)
b = append(b, '.')
b = strconv.AppendUint(b, v.Patch, 10)
if len(v.Pre) > 0 {
b = append(b, '-')
b = append(b, v.Pre[0].String()...)
for _, pre := range v.Pre[1:] {
b = append(b, '.')
b = append(b, pre.String()...)
}
}
if len(v.Build) > 0 {
b = append(b, '+')
b = append(b, v.Build[0]...)
for _, build := range v.Build[1:] {
b = append(b, '.')
b = append(b, build...)
}
}
return string(b)
}
// Equals checks if v is equal to o.
func (v Version) Equals(o Version) bool {
return (v.Compare(o) == 0)
}
// EQ checks if v is equal to o.
func (v Version) EQ(o Version) bool {
return (v.Compare(o) == 0)
}
// NE checks if v is not equal to o.
func (v Version) NE(o Version) bool {
return (v.Compare(o) != 0)
}
// GT checks if v is greater than o.
func (v Version) GT(o Version) bool {
return (v.Compare(o) == 1)
}
// GTE checks if v is greater than or equal to o.
func (v Version) GTE(o Version) bool {
return (v.Compare(o) >= 0)
}
// GE checks if v is greater than or equal to o.
func (v Version) GE(o Version) bool {
return (v.Compare(o) >= 0)
}
// LT checks if v is less than o.
func (v Version) LT(o Version) bool {
return (v.Compare(o) == -1)
}
// LTE checks if v is less than or equal to o.
func (v Version) LTE(o Version) bool {
return (v.Compare(o) <= 0)
}
// LE checks if v is less than or equal to o.
func (v Version) LE(o Version) bool {
return (v.Compare(o) <= 0)
}
// Compare compares Versions v to o:
// -1 == v is less than o
// 0 == v is equal to o
// 1 == v is greater than o
func (v Version) Compare(o Version) int {
if v.Major != o.Major {
if v.Major > o.Major {
return 1
}
return -1
}
if v.Minor != o.Minor {
if v.Minor > o.Minor {
return 1
}
return -1
}
if v.Patch != o.Patch {
if v.Patch > o.Patch {
return 1
}
return -1
}
// Quick comparison if a version has no prerelease versions
if len(v.Pre) == 0 && len(o.Pre) == 0 {
return 0
} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
return 1
} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
return -1
}
i := 0
for ; i < len(v.Pre) && i < len(o.Pre); i++ {
if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
continue
} else if comp == 1 {
return 1
} else {
return -1
}
}
// If all pr versions are the equal but one has further prversion, this one greater
if i == len(v.Pre) && i == len(o.Pre) {
return 0
} else if i == len(v.Pre) && i < len(o.Pre) {
return -1
} else {
return 1
}
}
// Validate validates v and returns error in case
func (v Version) Validate() error {
// Major, Minor, Patch already validated using uint64
for _, pre := range v.Pre {
if !pre.IsNum { //Numeric prerelease versions already uint64
if len(pre.VersionStr) == 0 {
return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
}
if !containsOnly(pre.VersionStr, alphanum) {
return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
}
}
}
for _, build := range v.Build {
if len(build) == 0 {
return fmt.Errorf("Build meta data can not be empty %q", build)
}
if !containsOnly(build, alphanum) {
return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
}
}
return nil
}
// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
func New(s string) (vp *Version, err error) {
v, err := Parse(s)
vp = &v
return
}
// Make is an alias for Parse, parses version string and returns a validated Version or error
func Make(s string) (Version, error) {
return Parse(s)
}
// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
// specs to be parsed by this library. It does so by normalizing versions before passing them to
// Parse(). It currently trims spaces, removes a "v" prefix, and adds a 0 patch number to versions
// with only major and minor components specified
func ParseTolerant(s string) (Version, error) {
s = strings.TrimSpace(s)
s = strings.TrimPrefix(s, "v")
// Split into major.minor.(patch+pr+meta)
parts := strings.SplitN(s, ".", 3)
if len(parts) < 3 {
if strings.ContainsAny(parts[len(parts)-1], "+-") {
return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
}
for len(parts) < 3 {
parts = append(parts, "0")
}
s = strings.Join(parts, ".")
}
return Parse(s)
}
// Parse parses version string and returns a validated Version or error
func Parse(s string) (Version, error) {
if len(s) == 0 {
return Version{}, errors.New("Version string empty")
}
// Split into major.minor.(patch+pr+meta)
parts := strings.SplitN(s, ".", 3)
if len(parts) != 3 {
return Version{}, errors.New("No Major.Minor.Patch elements found")
}
// Major
if !containsOnly(parts[0], numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
}
if hasLeadingZeroes(parts[0]) {
return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
}
major, err := strconv.ParseUint(parts[0], 10, 64)
if err != nil {
return Version{}, err
}
// Minor
if !containsOnly(parts[1], numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
}
if hasLeadingZeroes(parts[1]) {
return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
}
minor, err := strconv.ParseUint(parts[1], 10, 64)
if err != nil {
return Version{}, err
}
v := Version{}
v.Major = major
v.Minor = minor
var build, prerelease []string
patchStr := parts[2]
if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
build = strings.Split(patchStr[buildIndex+1:], ".")
patchStr = patchStr[:buildIndex]
}
if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
prerelease = strings.Split(patchStr[preIndex+1:], ".")
patchStr = patchStr[:preIndex]
}
if !containsOnly(patchStr, numbers) {
return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
}
if hasLeadingZeroes(patchStr) {
return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
}
patch, err := strconv.ParseUint(patchStr, 10, 64)
if err != nil {
return Version{}, err
}
v.Patch = patch
// Prerelease
for _, prstr := range prerelease {
parsedPR, err := NewPRVersion(prstr)
if err != nil {
return Version{}, err
}
v.Pre = append(v.Pre, parsedPR)
}
// Build meta data
for _, str := range build {
if len(str) == 0 {
return Version{}, errors.New("Build meta data is empty")
}
if !containsOnly(str, alphanum) {
return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
}
v.Build = append(v.Build, str)
}
return v, nil
}
// MustParse is like Parse but panics if the version cannot be parsed.
func MustParse(s string) Version {
v, err := Parse(s)
if err != nil {
panic(`semver: Parse(` + s + `): ` + err.Error())
}
return v
}
// PRVersion represents a PreRelease Version
type PRVersion struct {
VersionStr string
VersionNum uint64
IsNum bool
}
// NewPRVersion creates a new valid prerelease version
func NewPRVersion(s string) (PRVersion, error) {
if len(s) == 0 {
return PRVersion{}, errors.New("Prerelease is empty")
}
v := PRVersion{}
if containsOnly(s, numbers) {
if hasLeadingZeroes(s) {
return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
}
num, err := strconv.ParseUint(s, 10, 64)
// Might never be hit, but just in case
if err != nil {
return PRVersion{}, err
}
v.VersionNum = num
v.IsNum = true
} else if containsOnly(s, alphanum) {
v.VersionStr = s
v.IsNum = false
} else {
return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
}
return v, nil
}
// IsNumeric checks if prerelease-version is numeric
func (v PRVersion) IsNumeric() bool {
return v.IsNum
}
// Compare compares two PreRelease Versions v and o:
// -1 == v is less than o
// 0 == v is equal to o
// 1 == v is greater than o
func (v PRVersion) Compare(o PRVersion) int {
if v.IsNum && !o.IsNum {
return -1
} else if !v.IsNum && o.IsNum {
return 1
} else if v.IsNum && o.IsNum {
if v.VersionNum == o.VersionNum {
return 0
} else if v.VersionNum > o.VersionNum {
return 1
} else {
return -1
}
} else { // both are Alphas
if v.VersionStr == o.VersionStr {
return 0
} else if v.VersionStr > o.VersionStr {
return 1
} else {
return -1
}
}
}
// PreRelease version to string
func (v PRVersion) String() string {
if v.IsNum {
return strconv.FormatUint(v.VersionNum, 10)
}
return v.VersionStr
}
func containsOnly(s string, set string) bool {
return strings.IndexFunc(s, func(r rune) bool {
return !strings.ContainsRune(set, r)
}) == -1
}
func hasLeadingZeroes(s string) bool {
return len(s) > 1 && s[0] == '0'
}
// NewBuildVersion creates a new valid build version
func NewBuildVersion(s string) (string, error) {
if len(s) == 0 {
return "", errors.New("Buildversion is empty")
}
if !containsOnly(s, alphanum) {
return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
}
return s, nil
}
================================================
FILE: vendor/github.com/blang/semver/sort.go
================================================
package semver
import (
"sort"
)
// Versions represents multiple versions.
type Versions []Version
// Len returns length of version collection
func (s Versions) Len() int {
return len(s)
}
// Swap swaps two versions inside the collection by its indices
func (s Versions) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Less checks if version at index i is less than version at index j
func (s Versions) Less(i, j int) bool {
return s[i].LT(s[j])
}
// Sort sorts a slice of versions
func Sort(versions []Version) {
sort.Sort(Versions(versions))
}
================================================
FILE: vendor/github.com/blang/semver/sql.go
================================================
package semver
import (
"database/sql/driver"
"fmt"
)
// Scan implements the database/sql.Scanner interface.
func (v *Version) Scan(src interface{}) (err error) {
var str string
switch src := src.(type) {
case string:
str = src
case []byte:
str = string(src)
default:
return fmt.Errorf("Version.Scan: cannot convert %T to string.", src)
}
if t, err := Parse(str); err == nil {
*v = t
}
return
}
// Value implements the database/sql/driver.Valuer interface.
func (v Version) Value() (driver.Value, error) {
return v.String(), nil
}
================================================
FILE: vendor/github.com/bradleyfalzon/ghinstallation/AUTHORS
================================================
Billy Lynch
Bradley Falzon
Philippe Modard
Ricardo Chimal, Jr
Tatsuya Kamohara <17017563+kamontia@users.noreply.github.com>
rob boll
================================================
FILE: vendor/github.com/bradleyfalzon/ghinstallation/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright 2019 ghinstallation AUTHORS
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: vendor/github.com/bradleyfalzon/ghinstallation/README.md
================================================
# ghinstallation
[](https://godoc.org/github.com/bradleyfalzon/ghinstallation)
`ghinstallation` provides `Transport`, which implements `http.RoundTripper` to
provide authentication as an installation for GitHub Apps.
This library is designed to provide automatic authentication for
https://github.com/google/go-github or your own HTTP client.
See
https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/about-authentication-options-for-github-apps/
# Installation
Get the package:
```bash
go get -u github.com/bradleyfalzon/ghinstallation
```
# GitHub Example
```go
import "github.com/bradleyfalzon/ghinstallation"
func main() {
// Shared transport to reuse TCP connections.
tr := http.DefaultTransport
// Wrap the shared transport for use with the app ID 1 authenticating with installation ID 99.
itr, err := ghinstallation.NewKeyFromFile(tr, 1, 99, "2016-10-19.private-key.pem")
if err != nil {
log.Fatal(err)
}
// Use installation transport with github.com/google/go-github
client := github.NewClient(&http.Client{Transport: itr})
}
```
# GitHub Enterprise Example
For clients using GitHub Enterprise, set the base URL as follows:
```go
import "github.com/bradleyfalzon/ghinstallation"
const GitHubEnterpriseURL = "https://github.example.com/api/v3"
func main() {
// Shared transport to reuse TCP connections.
tr := http.DefaultTransport
// Wrap the shared transport for use with the app ID 1 authenticating with installation ID 99.
itr, err := ghinstallation.NewKeyFromFile(tr, 1, 99, "2016-10-19.private-key.pem")
if err != nil {
log.Fatal(err)
}
itr.BaseURL = GitHubEnterpriseURL
// Use installation transport with github.com/google/go-github
client := github.NewEnterpriseClient(GitHubEnterpriseURL, GitHubEnterpriseURL, &http.Client{Transport: itr})
}
```
## What is app ID and installation ID
`app ID` is the GitHub App ID. \
You can check as following : \
Settings > Developer > settings > GitHub App > About item
`installation ID` is a part of WebHook request. \
You can get the number to check the request. \
Settings > Developer > settings > GitHub Apps > Advanced > Payload in Request
tab
```
WebHook request
...
"installation": {
"id": `installation ID`
}
```
# License
[Apache 2.0](LICENSE)
# Dependencies
- [github.com/dgrijalva/jwt-go](https://github.com/dgrijalva/jwt-go)
================================================
FILE: vendor/github.com/bradleyfalzon/ghinstallation/appsTransport.go
================================================
package ghinstallation
import (
"crypto/rsa"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"time"
jwt "github.com/dgrijalva/jwt-go"
)
// AppsTransport provides a http.RoundTripper by wrapping an existing
// http.RoundTripper and provides GitHub Apps authentication as a
// GitHub App.
//
// Client can also be overwritten, and is useful to change to one which
// provides retry logic if you do experience retryable errors.
//
// See https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/about-authentication-options-for-github-apps/
type AppsTransport struct {
BaseURL string // BaseURL is the scheme and host for GitHub API, defaults to https://api.github.com
Client Client // Client to use to refresh tokens, defaults to http.Client with provided transport
tr http.RoundTripper // tr is the underlying roundtripper being wrapped
key *rsa.PrivateKey // key is the GitHub App's private key
appID int64 // appID is the GitHub App's ID
}
// NewAppsTransportKeyFromFile returns a AppsTransport using a private key from file.
func NewAppsTransportKeyFromFile(tr http.RoundTripper, appID int64, privateKeyFile string) (*AppsTransport, error) {
privateKey, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
return nil, fmt.Errorf("could not read private key: %s", err)
}
return NewAppsTransport(tr, appID, privateKey)
}
// NewAppsTransport returns a AppsTransport using private key. The key is parsed
// and if any errors occur the error is non-nil.
//
// The provided tr http.RoundTripper should be shared between multiple
// installations to ensure reuse of underlying TCP connections.
//
// The returned Transport's RoundTrip method is safe to be used concurrently.
func NewAppsTransport(tr http.RoundTripper, appID int64, privateKey []byte) (*AppsTransport, error) {
key, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
if err != nil {
return nil, fmt.Errorf("could not parse private key: %s", err)
}
return NewAppsTransportFromPrivateKey(tr, appID, key), nil
}
// NewAppsTransportFromPrivateKey returns an AppsTransport using a crypto/rsa.(*PrivateKey).
func NewAppsTransportFromPrivateKey(tr http.RoundTripper, appID int64, key *rsa.PrivateKey) (*AppsTransport) {
return &AppsTransport{
BaseURL: apiBaseURL,
Client: &http.Client{Transport: tr},
tr: tr,
key: key,
appID: appID,
}
}
// RoundTrip implements http.RoundTripper interface.
func (t *AppsTransport) RoundTrip(req *http.Request) (*http.Response, error) {
claims := &jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(time.Minute).Unix(),
Issuer: strconv.FormatInt(t.appID, 10),
}
bearer := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
ss, err := bearer.SignedString(t.key)
if err != nil {
return nil, fmt.Errorf("could not sign jwt: %s", err)
}
req.Header.Set("Authorization", "Bearer "+ss)
req.Header.Add("Accept", acceptHeader)
resp, err := t.tr.RoundTrip(req)
return resp, err
}
================================================
FILE: vendor/github.com/bradleyfalzon/ghinstallation/transport.go
================================================
package ghinstallation
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"sync"
"time"
"github.com/google/go-github/v29/github"
)
const (
// acceptHeader is the GitHub Apps Preview Accept header.
acceptHeader = "application/vnd.github.machine-man-preview+json"
apiBaseURL = "https://api.github.com"
)
// Transport provides a http.RoundTripper by wrapping an existing
// http.RoundTripper and provides GitHub Apps authentication as an
// installation.
//
// Client can also be overwritten, and is useful to change to one which
// provides retry logic if you do experience retryable errors.
//
// See https://developer.github.com/apps/building-integrations/setting-up-and-registering-github-apps/about-authentication-options-for-github-apps/
type Transport struct {
BaseURL string // BaseURL is the scheme and host for GitHub API, defaults to https://api.github.com
Client Client // Client to use to refresh tokens, defaults to http.Client with provided transport
tr http.RoundTripper // tr is the underlying roundtripper being wrapped
appID int64 // appID is the GitHub App's ID
installationID int64 // installationID is the GitHub App Installation ID
InstallationTokenOptions *github.InstallationTokenOptions // parameters restrict a token's access
appsTransport *AppsTransport
mu *sync.Mutex // mu protects token
token *accessToken // token is the installation's access token
}
// accessToken is an installation access token response from GitHub
type accessToken struct {
Token string `json:"token"`
ExpiresAt time.Time `json:"expires_at"`
Permissions github.InstallationPermissions `json:"permissions,omitempty"`
Repositories []github.Repository `json:"repositories,omitempty"`
}
var _ http.RoundTripper = &Transport{}
// NewKeyFromFile returns a Transport using a private key from file.
func NewKeyFromFile(tr http.RoundTripper, appID, installationID int64, privateKeyFile string) (*Transport, error) {
privateKey, err := ioutil.ReadFile(privateKeyFile)
if err != nil {
return nil, fmt.Errorf("could not read private key: %s", err)
}
return New(tr, appID, installationID, privateKey)
}
// Client is a HTTP client which sends a http.Request and returns a http.Response
// or an error.
type Client interface {
Do(*http.Request) (*http.Response, error)
}
// New returns an Transport using private key. The key is parsed
// and if any errors occur the error is non-nil.
//
// The provided tr http.RoundTripper should be shared between multiple
// installations to ensure reuse of underlying TCP connections.
//
// The returned Transport's RoundTrip method is safe to be used concurrently.
func New(tr http.RoundTripper, appID, installationID int64, privateKey []byte) (*Transport, error) {
atr, err := NewAppsTransport(tr, appID, privateKey)
if err != nil {
return nil, err
}
return NewFromAppsTransport(atr, installationID), nil
}
// NewFromAppsTransport returns a Transport using an existing *AppsTransport.
func NewFromAppsTransport(atr *AppsTransport, installationID int64) *Transport {
return &Transport{
BaseURL: atr.BaseURL,
Client: &http.Client{Transport: atr.tr},
tr: atr.tr,
appID: atr.appID,
installationID: installationID,
appsTransport: atr,
mu: &sync.Mutex{},
}
}
// RoundTrip implements http.RoundTripper interface.
func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error) {
token, err := t.Token(req.Context())
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "token "+token)
req.Header.Add("Accept", acceptHeader) // We add to "Accept" header to avoid overwriting existing req headers.
resp, err := t.tr.RoundTrip(req)
return resp, err
}
// Token checks the active token expiration and renews if necessary. Token returns
// a valid access token. If renewal fails an error is returned.
func (t *Transport) Token(ctx context.Context) (string, error) {
t.mu.Lock()
defer t.mu.Unlock()
if t.token == nil || t.token.ExpiresAt.Add(-time.Minute).Before(time.Now()) {
// Token is not set or expired/nearly expired, so refresh
if err := t.refreshToken(ctx); err != nil {
return "", fmt.Errorf("could not refresh installation id %v's token: %s", t.installationID, err)
}
}
return t.token.Token, nil
}
// Permissions returns a transport token's GitHub installation permissions.
func (t *Transport) Permissions() (github.InstallationPermissions, error) {
if t.token == nil {
return github.InstallationPermissions{}, fmt.Errorf("Permissions() = nil, err: nil token")
}
return t.token.Permissions, nil
}
// Repositories returns a transport token's GitHub repositories.
func (t *Transport) Repositories() ([]github.Repository, error) {
if t.token == nil {
return nil, fmt.Errorf("Repositories() = nil, err: nil token")
}
return t.token.Repositories, nil
}
func (t *Transport) refreshToken(ctx context.Context) error {
// Convert InstallationTokenOptions into a ReadWriter to pass as an argument to http.NewRequest.
body, err := GetReadWriter(t.InstallationTokenOptions)
if err != nil {
return fmt.Errorf("could not convert installation token parameters into json: %s", err)
}
req, err := http.NewRequest("POST", fmt.Sprintf("%s/app/installations/%v/access_tokens", t.BaseURL, t.installationID), body)
if err != nil {
return fmt.Errorf("could not create request: %s", err)
}
// Set Content and Accept headers.
if body != nil {
req.Header.Set("Content-Type", "application/json")
}
req.Header.Set("Accept", acceptHeader)
if ctx != nil {
req = req.WithContext(ctx)
}
t.appsTransport.BaseURL = t.BaseURL
t.appsTransport.Client = t.Client
resp, err := t.appsTransport.RoundTrip(req)
if err != nil {
return fmt.Errorf("could not get access_tokens from GitHub API for installation ID %v: %v", t.installationID, err)
}
defer resp.Body.Close()
if resp.StatusCode/100 != 2 {
return fmt.Errorf("request %+v received non 2xx response status %q with body %+v and TLS %+v", resp.Request, resp.Body, resp.Request, resp.TLS)
}
return json.NewDecoder(resp.Body).Decode(&t.token)
}
// GetReadWriter converts a body interface into an io.ReadWriter object.
func GetReadWriter(i interface{}) (io.ReadWriter, error) {
var buf io.ReadWriter
if i != nil {
buf = new(bytes.Buffer)
enc := json.NewEncoder(buf)
err := enc.Encode(i)
if err != nil {
return nil, err
}
}
return buf, nil
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/.gitignore
================================================
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/.travis.yml
================================================
language: go
go:
- 1.7
- 1.x
- tip
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2014 Cenk Altı
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/README.md
================================================
# Exponential Backoff [![GoDoc][godoc image]][godoc] [![Build Status][travis image]][travis] [![Coverage Status][coveralls image]][coveralls]
This is a Go port of the exponential backoff algorithm from [Google's HTTP Client Library for Java][google-http-java-client].
[Exponential backoff][exponential backoff wiki]
is an algorithm that uses feedback to multiplicatively decrease the rate of some process,
in order to gradually find an acceptable rate.
The retries exponentially increase and stop increasing when a certain threshold is met.
## Usage
Import path is `github.com/cenkalti/backoff/v3`. Please note the version part at the end.
godoc.org does not support modules yet,
so you can use https://godoc.org/gopkg.in/cenkalti/backoff.v3 to view the documentation.
## Contributing
* I would like to keep this library as small as possible.
* Please don't send a PR without opening an issue and discussing it first.
* If proposed change is not a common use case, I will probably not accept it.
[godoc]: https://godoc.org/github.com/cenkalti/backoff
[godoc image]: https://godoc.org/github.com/cenkalti/backoff?status.png
[travis]: https://travis-ci.org/cenkalti/backoff
[travis image]: https://travis-ci.org/cenkalti/backoff.png?branch=master
[coveralls]: https://coveralls.io/github/cenkalti/backoff?branch=master
[coveralls image]: https://coveralls.io/repos/github/cenkalti/backoff/badge.svg?branch=master
[google-http-java-client]: https://github.com/google/google-http-java-client/blob/da1aa993e90285ec18579f1553339b00e19b3ab5/google-http-client/src/main/java/com/google/api/client/util/ExponentialBackOff.java
[exponential backoff wiki]: http://en.wikipedia.org/wiki/Exponential_backoff
[advanced example]: https://godoc.org/github.com/cenkalti/backoff#example_
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/backoff.go
================================================
// Package backoff implements backoff algorithms for retrying operations.
//
// Use Retry function for retrying operations that may fail.
// If Retry does not meet your needs,
// copy/paste the function into your project and modify as you wish.
//
// There is also Ticker type similar to time.Ticker.
// You can use it if you need to work with channels.
//
// See Examples section below for usage examples.
package backoff
import "time"
// BackOff is a backoff policy for retrying an operation.
type BackOff interface {
// NextBackOff returns the duration to wait before retrying the operation,
// or backoff. Stop to indicate that no more retries should be made.
//
// Example usage:
//
// duration := backoff.NextBackOff();
// if (duration == backoff.Stop) {
// // Do not retry operation.
// } else {
// // Sleep for duration and retry operation.
// }
//
NextBackOff() time.Duration
// Reset to initial state.
Reset()
}
// Stop indicates that no more retries should be made for use in NextBackOff().
const Stop time.Duration = -1
// ZeroBackOff is a fixed backoff policy whose backoff time is always zero,
// meaning that the operation is retried immediately without waiting, indefinitely.
type ZeroBackOff struct{}
func (b *ZeroBackOff) Reset() {}
func (b *ZeroBackOff) NextBackOff() time.Duration { return 0 }
// StopBackOff is a fixed backoff policy that always returns backoff.Stop for
// NextBackOff(), meaning that the operation should never be retried.
type StopBackOff struct{}
func (b *StopBackOff) Reset() {}
func (b *StopBackOff) NextBackOff() time.Duration { return Stop }
// ConstantBackOff is a backoff policy that always returns the same backoff delay.
// This is in contrast to an exponential backoff policy,
// which returns a delay that grows longer as you call NextBackOff() over and over again.
type ConstantBackOff struct {
Interval time.Duration
}
func (b *ConstantBackOff) Reset() {}
func (b *ConstantBackOff) NextBackOff() time.Duration { return b.Interval }
func NewConstantBackOff(d time.Duration) *ConstantBackOff {
return &ConstantBackOff{Interval: d}
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/context.go
================================================
package backoff
import (
"context"
"time"
)
// BackOffContext is a backoff policy that stops retrying after the context
// is canceled.
type BackOffContext interface { // nolint: golint
BackOff
Context() context.Context
}
type backOffContext struct {
BackOff
ctx context.Context
}
// WithContext returns a BackOffContext with context ctx
//
// ctx must not be nil
func WithContext(b BackOff, ctx context.Context) BackOffContext { // nolint: golint
if ctx == nil {
panic("nil context")
}
if b, ok := b.(*backOffContext); ok {
return &backOffContext{
BackOff: b.BackOff,
ctx: ctx,
}
}
return &backOffContext{
BackOff: b,
ctx: ctx,
}
}
func getContext(b BackOff) context.Context {
if cb, ok := b.(BackOffContext); ok {
return cb.Context()
}
if tb, ok := b.(*backOffTries); ok {
return getContext(tb.delegate)
}
return context.Background()
}
func (b *backOffContext) Context() context.Context {
return b.ctx
}
func (b *backOffContext) NextBackOff() time.Duration {
select {
case <-b.ctx.Done():
return Stop
default:
}
next := b.BackOff.NextBackOff()
if deadline, ok := b.ctx.Deadline(); ok && deadline.Sub(time.Now()) < next { // nolint: gosimple
return Stop
}
return next
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/exponential.go
================================================
package backoff
import (
"math/rand"
"time"
)
/*
ExponentialBackOff is a backoff implementation that increases the backoff
period for each retry attempt using a randomization function that grows exponentially.
NextBackOff() is calculated using the following formula:
randomized interval =
RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])
In other words NextBackOff() will range between the randomization factor
percentage below and above the retry interval.
For example, given the following parameters:
RetryInterval = 2
RandomizationFactor = 0.5
Multiplier = 2
the actual backoff period used in the next retry attempt will range between 1 and 3 seconds,
multiplied by the exponential, that is, between 2 and 6 seconds.
Note: MaxInterval caps the RetryInterval and not the randomized interval.
If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
The elapsed time can be reset by calling Reset().
Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:
Request # RetryInterval (seconds) Randomized Interval (seconds)
1 0.5 [0.25, 0.75]
2 0.75 [0.375, 1.125]
3 1.125 [0.562, 1.687]
4 1.687 [0.8435, 2.53]
5 2.53 [1.265, 3.795]
6 3.795 [1.897, 5.692]
7 5.692 [2.846, 8.538]
8 8.538 [4.269, 12.807]
9 12.807 [6.403, 19.210]
10 19.210 backoff.Stop
Note: Implementation is not thread-safe.
*/
type ExponentialBackOff struct {
InitialInterval time.Duration
RandomizationFactor float64
Multiplier float64
MaxInterval time.Duration
// After MaxElapsedTime the ExponentialBackOff stops.
// It never stops if MaxElapsedTime == 0.
MaxElapsedTime time.Duration
Clock Clock
currentInterval time.Duration
startTime time.Time
}
// Clock is an interface that returns current time for BackOff.
type Clock interface {
Now() time.Time
}
// Default values for ExponentialBackOff.
const (
DefaultInitialInterval = 500 * time.Millisecond
DefaultRandomizationFactor = 0.5
DefaultMultiplier = 1.5
DefaultMaxInterval = 60 * time.Second
DefaultMaxElapsedTime = 15 * time.Minute
)
// NewExponentialBackOff creates an instance of ExponentialBackOff using default values.
func NewExponentialBackOff() *ExponentialBackOff {
b := &ExponentialBackOff{
InitialInterval: DefaultInitialInterval,
RandomizationFactor: DefaultRandomizationFactor,
Multiplier: DefaultMultiplier,
MaxInterval: DefaultMaxInterval,
MaxElapsedTime: DefaultMaxElapsedTime,
Clock: SystemClock,
}
b.Reset()
return b
}
type systemClock struct{}
func (t systemClock) Now() time.Time {
return time.Now()
}
// SystemClock implements Clock interface that uses time.Now().
var SystemClock = systemClock{}
// Reset the interval back to the initial retry interval and restarts the timer.
// Reset must be called before using b.
func (b *ExponentialBackOff) Reset() {
b.currentInterval = b.InitialInterval
b.startTime = b.Clock.Now()
}
// NextBackOff calculates the next backoff interval using the formula:
// Randomized interval = RetryInterval * (1 ± RandomizationFactor)
func (b *ExponentialBackOff) NextBackOff() time.Duration {
// Make sure we have not gone over the maximum elapsed time.
if b.MaxElapsedTime != 0 && b.GetElapsedTime() > b.MaxElapsedTime {
return Stop
}
defer b.incrementCurrentInterval()
return getRandomValueFromInterval(b.RandomizationFactor, rand.Float64(), b.currentInterval)
}
// GetElapsedTime returns the elapsed time since an ExponentialBackOff instance
// is created and is reset when Reset() is called.
//
// The elapsed time is computed using time.Now().UnixNano(). It is
// safe to call even while the backoff policy is used by a running
// ticker.
func (b *ExponentialBackOff) GetElapsedTime() time.Duration {
return b.Clock.Now().Sub(b.startTime)
}
// Increments the current interval by multiplying it with the multiplier.
func (b *ExponentialBackOff) incrementCurrentInterval() {
// Check for overflow, if overflow is detected set the current interval to the max interval.
if float64(b.currentInterval) >= float64(b.MaxInterval)/b.Multiplier {
b.currentInterval = b.MaxInterval
} else {
b.currentInterval = time.Duration(float64(b.currentInterval) * b.Multiplier)
}
}
// Returns a random value from the following interval:
// [randomizationFactor * currentInterval, randomizationFactor * currentInterval].
func getRandomValueFromInterval(randomizationFactor, random float64, currentInterval time.Duration) time.Duration {
var delta = randomizationFactor * float64(currentInterval)
var minInterval = float64(currentInterval) - delta
var maxInterval = float64(currentInterval) + delta
// Get a random value from the range [minInterval, maxInterval].
// The formula used below has a +1 because if the minInterval is 1 and the maxInterval is 3 then
// we want a 33% chance for selecting either 1, 2 or 3.
return time.Duration(minInterval + (random * (maxInterval - minInterval + 1)))
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/retry.go
================================================
package backoff
import "time"
// An Operation is executing by Retry() or RetryNotify().
// The operation will be retried using a backoff policy if it returns an error.
type Operation func() error
// Notify is a notify-on-error function. It receives an operation error and
// backoff delay if the operation failed (with an error).
//
// NOTE that if the backoff policy stated to stop retrying,
// the notify function isn't called.
type Notify func(error, time.Duration)
// Retry the operation o until it does not return error or BackOff stops.
// o is guaranteed to be run at least once.
//
// If o returns a *PermanentError, the operation is not retried, and the
// wrapped error is returned.
//
// Retry sleeps the goroutine for the duration returned by BackOff after a
// failed operation returns.
func Retry(o Operation, b BackOff) error {
return RetryNotify(o, b, nil)
}
// RetryNotify calls notify function with the error and wait duration
// for each failed attempt before sleep.
func RetryNotify(operation Operation, b BackOff, notify Notify) error {
return RetryNotifyWithTimer(operation, b, notify, nil)
}
// RetryNotifyWithTimer calls notify function with the error and wait duration using the given Timer
// for each failed attempt before sleep.
// A default timer that uses system timer is used when nil is passed.
func RetryNotifyWithTimer(operation Operation, b BackOff, notify Notify, t Timer) error {
var err error
var next time.Duration
if t == nil {
t = &defaultTimer{}
}
defer func() {
t.Stop()
}()
ctx := getContext(b)
b.Reset()
for {
if err = operation(); err == nil {
return nil
}
if permanent, ok := err.(*PermanentError); ok {
return permanent.Err
}
if next = b.NextBackOff(); next == Stop {
return err
}
if notify != nil {
notify(err, next)
}
t.Start(next)
select {
case <-ctx.Done():
return ctx.Err()
case <-t.C():
}
}
}
// PermanentError signals that the operation should not be retried.
type PermanentError struct {
Err error
}
func (e *PermanentError) Error() string {
return e.Err.Error()
}
func (e *PermanentError) Unwrap() error {
return e.Err
}
// Permanent wraps the given err in a *PermanentError.
func Permanent(err error) *PermanentError {
return &PermanentError{
Err: err,
}
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/ticker.go
================================================
package backoff
import (
"context"
"sync"
"time"
)
// Ticker holds a channel that delivers `ticks' of a clock at times reported by a BackOff.
//
// Ticks will continue to arrive when the previous operation is still running,
// so operations that take a while to fail could run in quick succession.
type Ticker struct {
C <-chan time.Time
c chan time.Time
b BackOff
ctx context.Context
timer Timer
stop chan struct{}
stopOnce sync.Once
}
// NewTicker returns a new Ticker containing a channel that will send
// the time at times specified by the BackOff argument. Ticker is
// guaranteed to tick at least once. The channel is closed when Stop
// method is called or BackOff stops. It is not safe to manipulate the
// provided backoff policy (notably calling NextBackOff or Reset)
// while the ticker is running.
func NewTicker(b BackOff) *Ticker {
return NewTickerWithTimer(b, &defaultTimer{})
}
// NewTickerWithTimer returns a new Ticker with a custom timer.
// A default timer that uses system timer is used when nil is passed.
func NewTickerWithTimer(b BackOff, timer Timer) *Ticker {
c := make(chan time.Time)
t := &Ticker{
C: c,
c: c,
b: b,
ctx: getContext(b),
timer: timer,
stop: make(chan struct{}),
}
t.b.Reset()
go t.run()
return t
}
// Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() {
t.stopOnce.Do(func() { close(t.stop) })
}
func (t *Ticker) run() {
c := t.c
defer close(c)
// Ticker is guaranteed to tick at least once.
afterC := t.send(time.Now())
for {
if afterC == nil {
return
}
select {
case tick := <-afterC:
afterC = t.send(tick)
case <-t.stop:
t.c = nil // Prevent future ticks from being sent to the channel.
return
case <-t.ctx.Done():
return
}
}
}
func (t *Ticker) send(tick time.Time) <-chan time.Time {
select {
case t.c <- tick:
case <-t.stop:
return nil
}
next := t.b.NextBackOff()
if next == Stop {
t.Stop()
return nil
}
t.timer.Start(next)
return t.timer.C()
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/timer.go
================================================
package backoff
import "time"
type Timer interface {
Start(duration time.Duration)
Stop()
C() <-chan time.Time
}
// defaultTimer implements Timer interface using time.Timer
type defaultTimer struct {
timer *time.Timer
}
// C returns the timers channel which receives the current time when the timer fires.
func (t *defaultTimer) C() <-chan time.Time {
return t.timer.C
}
// Start starts the timer to fire after the given duration
func (t *defaultTimer) Start(duration time.Duration) {
if t.timer == nil {
t.timer = time.NewTimer(duration)
} else {
t.timer.Reset(duration)
}
}
// Stop is called when the timer is not used anymore and resources may be freed.
func (t *defaultTimer) Stop() {
if t.timer != nil {
t.timer.Stop()
}
}
================================================
FILE: vendor/github.com/cenkalti/backoff/v3/tries.go
================================================
package backoff
import "time"
/*
WithMaxRetries creates a wrapper around another BackOff, which will
return Stop if NextBackOff() has been called too many times since
the last time Reset() was called
Note: Implementation is not thread-safe.
*/
func WithMaxRetries(b BackOff, max uint64) BackOff {
return &backOffTries{delegate: b, maxTries: max}
}
type backOffTries struct {
delegate BackOff
maxTries uint64
numTries uint64
}
func (b *backOffTries) NextBackOff() time.Duration {
if b.maxTries > 0 {
if b.maxTries <= b.numTries {
return Stop
}
b.numTries++
}
return b.delegate.NextBackOff()
}
func (b *backOffTries) Reset() {
b.numTries = 0
b.delegate.Reset()
}
================================================
FILE: vendor/github.com/cloudflare/circl/LICENSE
================================================
Copyright (c) 2019 Cloudflare. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Cloudflare nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
========================================================================
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve.go
================================================
package x25519
import (
fp "github.com/cloudflare/circl/math/fp25519"
)
// ladderJoye calculates a fixed-point multiplication with the generator point.
// The algorithm is the right-to-left Joye's ladder as described
// in "How to precompute a ladder" in SAC'2017.
func ladderJoye(k *Key) {
w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved.
fp.SetOne(&w[1]) // x1 = 1
fp.SetOne(&w[2]) // z1 = 1
w[3] = fp.Elt{ // x2 = G-S
0xbd, 0xaa, 0x2f, 0xc8, 0xfe, 0xe1, 0x94, 0x7e,
0xf8, 0xed, 0xb2, 0x14, 0xae, 0x95, 0xf0, 0xbb,
0xe2, 0x48, 0x5d, 0x23, 0xb9, 0xa0, 0xc7, 0xad,
0x34, 0xab, 0x7c, 0xe2, 0xee, 0xcd, 0xae, 0x1e,
}
fp.SetOne(&w[4]) // z2 = 1
const n = 255
const h = 3
swap := uint(1)
for s := 0; s < n-h; s++ {
i := (s + h) / 8
j := (s + h) % 8
bit := uint((k[i] >> uint(j)) & 1)
copy(w[0][:], tableGenerator[s*Size:(s+1)*Size])
diffAdd(&w, swap^bit)
swap = bit
}
for s := 0; s < h; s++ {
double(&w[1], &w[2])
}
toAffine((*[fp.Size]byte)(k), &w[1], &w[2])
}
// ladderMontgomery calculates a generic scalar point multiplication
// The algorithm implemented is the left-to-right Montgomery's ladder.
func ladderMontgomery(k, xP *Key) {
w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved.
w[0] = *(*fp.Elt)(xP) // x1 = xP
fp.SetOne(&w[1]) // x2 = 1
w[3] = *(*fp.Elt)(xP) // x3 = xP
fp.SetOne(&w[4]) // z3 = 1
move := uint(0)
for s := 255 - 1; s >= 0; s-- {
i := s / 8
j := s % 8
bit := uint((k[i] >> uint(j)) & 1)
ladderStep(&w, move^bit)
move = bit
}
toAffine((*[fp.Size]byte)(k), &w[1], &w[2])
}
func toAffine(k *[fp.Size]byte, x, z *fp.Elt) {
fp.Inv(z, z)
fp.Mul(x, x, z)
_ = fp.ToBytes(k[:], x)
}
var lowOrderPoints = [5]fp.Elt{
{ /* (0,_,1) point of order 2 on Curve25519 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{ /* (1,_,1) point of order 4 on Curve25519 */
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{ /* (x,_,1) first point of order 8 on Curve25519 */
0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae,
0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a,
0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd,
0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00,
},
{ /* (x,_,1) second point of order 8 on Curve25519 */
0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24,
0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b,
0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86,
0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57,
},
{ /* (-1,_,1) a point of order 4 on the twist of Curve25519 */
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
},
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.go
================================================
//go:build amd64 && !purego
// +build amd64,!purego
package x25519
import (
fp "github.com/cloudflare/circl/math/fp25519"
"golang.org/x/sys/cpu"
)
var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX
var _ = hasBmi2Adx
func double(x, z *fp.Elt) { doubleAmd64(x, z) }
func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) }
func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) }
func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) }
//go:noescape
func ladderStepAmd64(w *[5]fp.Elt, b uint)
//go:noescape
func diffAddAmd64(w *[5]fp.Elt, b uint)
//go:noescape
func doubleAmd64(x, z *fp.Elt)
//go:noescape
func mulA24Amd64(z, x *fp.Elt)
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.h
================================================
#define ladderStepLeg \
addSub(x2,z2) \
addSub(x3,z3) \
integerMulLeg(b0,x2,z3) \
integerMulLeg(b1,x3,z2) \
reduceFromDoubleLeg(t0,b0) \
reduceFromDoubleLeg(t1,b1) \
addSub(t0,t1) \
cselect(x2,x3,regMove) \
cselect(z2,z3,regMove) \
integerSqrLeg(b0,t0) \
integerSqrLeg(b1,t1) \
reduceFromDoubleLeg(x3,b0) \
reduceFromDoubleLeg(z3,b1) \
integerMulLeg(b0,x1,z3) \
reduceFromDoubleLeg(z3,b0) \
integerSqrLeg(b0,x2) \
integerSqrLeg(b1,z2) \
reduceFromDoubleLeg(x2,b0) \
reduceFromDoubleLeg(z2,b1) \
subtraction(t0,x2,z2) \
multiplyA24Leg(t1,t0) \
additionLeg(t1,t1,z2) \
integerMulLeg(b0,x2,z2) \
integerMulLeg(b1,t0,t1) \
reduceFromDoubleLeg(x2,b0) \
reduceFromDoubleLeg(z2,b1)
#define ladderStepBmi2Adx \
addSub(x2,z2) \
addSub(x3,z3) \
integerMulAdx(b0,x2,z3) \
integerMulAdx(b1,x3,z2) \
reduceFromDoubleAdx(t0,b0) \
reduceFromDoubleAdx(t1,b1) \
addSub(t0,t1) \
cselect(x2,x3,regMove) \
cselect(z2,z3,regMove) \
integerSqrAdx(b0,t0) \
integerSqrAdx(b1,t1) \
reduceFromDoubleAdx(x3,b0) \
reduceFromDoubleAdx(z3,b1) \
integerMulAdx(b0,x1,z3) \
reduceFromDoubleAdx(z3,b0) \
integerSqrAdx(b0,x2) \
integerSqrAdx(b1,z2) \
reduceFromDoubleAdx(x2,b0) \
reduceFromDoubleAdx(z2,b1) \
subtraction(t0,x2,z2) \
multiplyA24Adx(t1,t0) \
additionAdx(t1,t1,z2) \
integerMulAdx(b0,x2,z2) \
integerMulAdx(b1,t0,t1) \
reduceFromDoubleAdx(x2,b0) \
reduceFromDoubleAdx(z2,b1)
#define difAddLeg \
addSub(x1,z1) \
integerMulLeg(b0,z1,ui) \
reduceFromDoubleLeg(z1,b0) \
addSub(x1,z1) \
integerSqrLeg(b0,x1) \
integerSqrLeg(b1,z1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1) \
integerMulLeg(b0,x1,z2) \
integerMulLeg(b1,z1,x2) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1)
#define difAddBmi2Adx \
addSub(x1,z1) \
integerMulAdx(b0,z1,ui) \
reduceFromDoubleAdx(z1,b0) \
addSub(x1,z1) \
integerSqrAdx(b0,x1) \
integerSqrAdx(b1,z1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1) \
integerMulAdx(b0,x1,z2) \
integerMulAdx(b1,z1,x2) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1)
#define doubleLeg \
addSub(x1,z1) \
integerSqrLeg(b0,x1) \
integerSqrLeg(b1,z1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1) \
subtraction(t0,x1,z1) \
multiplyA24Leg(t1,t0) \
additionLeg(t1,t1,z1) \
integerMulLeg(b0,x1,z1) \
integerMulLeg(b1,t0,t1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1)
#define doubleBmi2Adx \
addSub(x1,z1) \
integerSqrAdx(b0,x1) \
integerSqrAdx(b1,z1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1) \
subtraction(t0,x1,z1) \
multiplyA24Adx(t1,t0) \
additionAdx(t1,t1,z1) \
integerMulAdx(b0,x1,z1) \
integerMulAdx(b1,t0,t1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1)
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve_amd64.s
================================================
// +build amd64
#include "textflag.h"
// Depends on circl/math/fp25519 package
#include "../../math/fp25519/fp_amd64.h"
#include "curve_amd64.h"
// CTE_A24 is (A+2)/4 from Curve25519
#define CTE_A24 121666
#define Size 32
// multiplyA24Leg multiplies x times CTE_A24 and stores in z
// Uses: AX, DX, R8-R13, FLAGS
// Instr: x86_64, cmov
#define multiplyA24Leg(z,x) \
MOVL $CTE_A24, AX; MULQ 0+x; MOVQ AX, R8; MOVQ DX, R9; \
MOVL $CTE_A24, AX; MULQ 8+x; MOVQ AX, R12; MOVQ DX, R10; \
MOVL $CTE_A24, AX; MULQ 16+x; MOVQ AX, R13; MOVQ DX, R11; \
MOVL $CTE_A24, AX; MULQ 24+x; \
ADDQ R12, R9; \
ADCQ R13, R10; \
ADCQ AX, R11; \
ADCQ $0, DX; \
MOVL $38, AX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \
IMULQ AX, DX; \
ADDQ DX, R8; \
ADCQ $0, R9; MOVQ R9, 8+z; \
ADCQ $0, R10; MOVQ R10, 16+z; \
ADCQ $0, R11; MOVQ R11, 24+z; \
MOVQ $0, DX; \
CMOVQCS AX, DX; \
ADDQ DX, R8; MOVQ R8, 0+z;
// multiplyA24Adx multiplies x times CTE_A24 and stores in z
// Uses: AX, DX, R8-R12, FLAGS
// Instr: x86_64, cmov, bmi2
#define multiplyA24Adx(z,x) \
MOVQ $CTE_A24, DX; \
MULXQ 0+x, R8, R10; \
MULXQ 8+x, R9, R11; ADDQ R10, R9; \
MULXQ 16+x, R10, AX; ADCQ R11, R10; \
MULXQ 24+x, R11, R12; ADCQ AX, R11; \
;;;;;;;;;;;;;;;;;;;;; ADCQ $0, R12; \
MOVL $38, DX; /* 2*C = 38 = 2^256 MOD 2^255-19*/ \
IMULQ DX, R12; \
ADDQ R12, R8; \
ADCQ $0, R9; MOVQ R9, 8+z; \
ADCQ $0, R10; MOVQ R10, 16+z; \
ADCQ $0, R11; MOVQ R11, 24+z; \
MOVQ $0, R12; \
CMOVQCS DX, R12; \
ADDQ R12, R8; MOVQ R8, 0+z;
#define mulA24Legacy \
multiplyA24Leg(0(DI),0(SI))
#define mulA24Bmi2Adx \
multiplyA24Adx(0(DI),0(SI))
// func mulA24Amd64(z, x *fp255.Elt)
TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx)
// func ladderStepAmd64(w *[5]fp255.Elt, b uint)
// ladderStepAmd64 calculates a point addition and doubling as follows:
// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-).
// work = (x1,x2,z2,x3,z3) are five fp255.Elt of 32 bytes.
// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and
// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
TEXT ·ladderStepAmd64(SB),NOSPLIT,$192-16
// Parameters
#define regWork DI
#define regMove SI
#define x1 0*Size(regWork)
#define x2 1*Size(regWork)
#define z2 2*Size(regWork)
#define x3 3*Size(regWork)
#define z3 4*Size(regWork)
// Local variables
#define t0 0*Size(SP)
#define t1 1*Size(SP)
#define b0 2*Size(SP)
#define b1 4*Size(SP)
MOVQ w+0(FP), regWork
MOVQ b+8(FP), regMove
CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx)
#undef regWork
#undef regMove
#undef x1
#undef x2
#undef z2
#undef x3
#undef z3
#undef t0
#undef t1
#undef b0
#undef b1
// func diffAddAmd64(w *[5]fp255.Elt, b uint)
// diffAddAmd64 calculates a differential point addition using a precomputed point.
// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2)
// w = (mu,x1,z1,x2,z2) are five fp.Elt, and
// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
TEXT ·diffAddAmd64(SB),NOSPLIT,$128-16
// Parameters
#define regWork DI
#define regSwap SI
#define ui 0*Size(regWork)
#define x1 1*Size(regWork)
#define z1 2*Size(regWork)
#define x2 3*Size(regWork)
#define z2 4*Size(regWork)
// Local variables
#define b0 0*Size(SP)
#define b1 2*Size(SP)
MOVQ w+0(FP), regWork
MOVQ b+8(FP), regSwap
cswap(x1,x2,regSwap)
cswap(z1,z2,regSwap)
CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx)
#undef regWork
#undef regSwap
#undef ui
#undef x1
#undef z1
#undef x2
#undef z2
#undef b0
#undef b1
// func doubleAmd64(x, z *fp255.Elt)
// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1).
// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and
// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
TEXT ·doubleAmd64(SB),NOSPLIT,$192-16
// Parameters
#define x1 0(DI)
#define z1 0(SI)
// Local variables
#define t0 0*Size(SP)
#define t1 1*Size(SP)
#define b0 2*Size(SP)
#define b1 4*Size(SP)
MOVQ x+0(FP), DI
MOVQ z+8(FP), SI
CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx)
#undef x1
#undef z1
#undef t0
#undef t1
#undef b0
#undef b1
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve_generic.go
================================================
package x25519
import (
"encoding/binary"
"math/bits"
fp "github.com/cloudflare/circl/math/fp25519"
)
func doubleGeneric(x, z *fp.Elt) {
t0, t1 := &fp.Elt{}, &fp.Elt{}
fp.AddSub(x, z)
fp.Sqr(x, x)
fp.Sqr(z, z)
fp.Sub(t0, x, z)
mulA24Generic(t1, t0)
fp.Add(t1, t1, z)
fp.Mul(x, x, z)
fp.Mul(z, t0, t1)
}
func diffAddGeneric(w *[5]fp.Elt, b uint) {
mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4]
fp.Cswap(x1, x2, b)
fp.Cswap(z1, z2, b)
fp.AddSub(x1, z1)
fp.Mul(z1, z1, mu)
fp.AddSub(x1, z1)
fp.Sqr(x1, x1)
fp.Sqr(z1, z1)
fp.Mul(x1, x1, z2)
fp.Mul(z1, z1, x2)
}
func ladderStepGeneric(w *[5]fp.Elt, b uint) {
x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4]
t0 := &fp.Elt{}
t1 := &fp.Elt{}
fp.AddSub(x2, z2)
fp.AddSub(x3, z3)
fp.Mul(t0, x2, z3)
fp.Mul(t1, x3, z2)
fp.AddSub(t0, t1)
fp.Cmov(x2, x3, b)
fp.Cmov(z2, z3, b)
fp.Sqr(x3, t0)
fp.Sqr(z3, t1)
fp.Mul(z3, x1, z3)
fp.Sqr(x2, x2)
fp.Sqr(z2, z2)
fp.Sub(t0, x2, z2)
mulA24Generic(t1, t0)
fp.Add(t1, t1, z2)
fp.Mul(x2, x2, z2)
fp.Mul(z2, t0, t1)
}
func mulA24Generic(z, x *fp.Elt) {
const A24 = 121666
const n = 8
var xx [4]uint64
for i := range xx {
xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n])
}
h0, l0 := bits.Mul64(xx[0], A24)
h1, l1 := bits.Mul64(xx[1], A24)
h2, l2 := bits.Mul64(xx[2], A24)
h3, l3 := bits.Mul64(xx[3], A24)
var c3 uint64
l1, c0 := bits.Add64(h0, l1, 0)
l2, c1 := bits.Add64(h1, l2, c0)
l3, c2 := bits.Add64(h2, l3, c1)
l4, _ := bits.Add64(h3, 0, c2)
_, l4 = bits.Mul64(l4, 38)
l0, c0 = bits.Add64(l0, l4, 0)
xx[1], c1 = bits.Add64(l1, 0, c0)
xx[2], c2 = bits.Add64(l2, 0, c1)
xx[3], c3 = bits.Add64(l3, 0, c2)
xx[0], _ = bits.Add64(l0, (-c3)&38, 0)
for i := range xx {
binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i])
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/curve_noasm.go
================================================
//go:build !amd64 || purego
// +build !amd64 purego
package x25519
import fp "github.com/cloudflare/circl/math/fp25519"
func double(x, z *fp.Elt) { doubleGeneric(x, z) }
func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) }
func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) }
func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) }
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/doc.go
================================================
/*
Package x25519 provides Diffie-Hellman functions as specified in RFC-7748.
Validation of public keys.
The Diffie-Hellman function, as described in RFC-7748 [1], works for any
public key. However, if a different protocol requires contributory
behaviour [2,3], then the public keys must be validated against low-order
points [3,4]. To do that, the Shared function performs this validation
internally and returns false when the public key is invalid (i.e., it
is a low-order point).
References:
- [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt)
- [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html)
- [3] Bernstein (https://cr.yp.to/ecdh.html#validate)
- [4] Cremers&Jackson (https://eprint.iacr.org/2019/526)
*/
package x25519
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/key.go
================================================
package x25519
import (
"crypto/subtle"
fp "github.com/cloudflare/circl/math/fp25519"
)
// Size is the length in bytes of a X25519 key.
const Size = 32
// Key represents a X25519 key.
type Key [Size]byte
func (k *Key) clamp(in *Key) *Key {
*k = *in
k[0] &= 248
k[31] = (k[31] & 127) | 64
return k
}
// isValidPubKey verifies if the public key is not a low-order point.
func (k *Key) isValidPubKey() bool {
fp.Modp((*fp.Elt)(k))
var isLowOrder int
for _, P := range lowOrderPoints {
isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:])
}
return isLowOrder == 0
}
// KeyGen obtains a public key given a secret key.
func KeyGen(public, secret *Key) {
ladderJoye(public.clamp(secret))
}
// Shared calculates Alice's shared key from Alice's secret key and Bob's
// public key returning true on success. A failure case happens when the public
// key is a low-order point, thus the shared key is all-zeros and the function
// returns false.
func Shared(shared, secret, public *Key) bool {
validPk := *public
validPk[31] &= (1 << (255 % 8)) - 1
ok := validPk.isValidPubKey()
ladderMontgomery(shared.clamp(secret), &validPk)
return ok
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x25519/table.go
================================================
package x25519
import "github.com/cloudflare/circl/math/fp25519"
// tableGenerator contains the set of points:
//
// t[i] = (xi+1)/(xi-1),
//
// where (xi,yi) = 2^iG and G is the generator point
// Size = (256)*(256/8) = 8192 bytes.
var tableGenerator = [256 * fp25519.Size]byte{
/* (2^ 0)P */ 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5f,
/* (2^ 1)P */ 0x96, 0xfe, 0xaa, 0x16, 0xf4, 0x20, 0x82, 0x6b, 0x34, 0x6a, 0x56, 0x4f, 0x2b, 0xeb, 0xeb, 0x82, 0x0f, 0x95, 0xa5, 0x75, 0xb0, 0xa5, 0xa9, 0xd5, 0xf4, 0x88, 0x24, 0x4b, 0xcf, 0xb2, 0x42, 0x51,
/* (2^ 2)P */ 0x0c, 0x68, 0x69, 0x00, 0x75, 0xbc, 0xae, 0x6a, 0x41, 0x9c, 0xf9, 0xa0, 0x20, 0x78, 0xcf, 0x89, 0xf4, 0xd0, 0x56, 0x3b, 0x18, 0xd9, 0x58, 0x2a, 0xa4, 0x11, 0x60, 0xe3, 0x80, 0xca, 0x5a, 0x4b,
/* (2^ 3)P */ 0x5d, 0x74, 0x29, 0x8c, 0x34, 0x32, 0x91, 0x32, 0xd7, 0x2f, 0x64, 0xe1, 0x16, 0xe6, 0xa2, 0xf4, 0x34, 0xbc, 0x67, 0xff, 0x03, 0xbb, 0x45, 0x1e, 0x4a, 0x9b, 0x2a, 0xf4, 0xd0, 0x12, 0x69, 0x30,
/* (2^ 4)P */ 0x54, 0x71, 0xaf, 0xe6, 0x07, 0x65, 0x88, 0xff, 0x2f, 0xc8, 0xee, 0xdf, 0x13, 0x0e, 0xf5, 0x04, 0xce, 0xb5, 0xba, 0x2a, 0xe8, 0x2f, 0x51, 0xaa, 0x22, 0xf2, 0xd5, 0x68, 0x1a, 0x25, 0x4e, 0x17,
/* (2^ 5)P */ 0x98, 0x88, 0x02, 0x82, 0x0d, 0x70, 0x96, 0xcf, 0xc5, 0x02, 0x2c, 0x0a, 0x37, 0xe3, 0x43, 0x17, 0xaa, 0x6e, 0xe8, 0xb4, 0x98, 0xec, 0x9e, 0x37, 0x2e, 0x48, 0xe0, 0x51, 0x8a, 0x88, 0x59, 0x0c,
/* (2^ 6)P */ 0x89, 0xd1, 0xb5, 0x99, 0xd6, 0xf1, 0xcb, 0xfb, 0x84, 0xdc, 0x9f, 0x8e, 0xd5, 0xf0, 0xae, 0xac, 0x14, 0x76, 0x1f, 0x23, 0x06, 0x0d, 0xc2, 0xc1, 0x72, 0xf9, 0x74, 0xa2, 0x8d, 0x21, 0x38, 0x29,
/* (2^ 7)P */ 0x18, 0x7f, 0x1d, 0xff, 0xbe, 0x49, 0xaf, 0xf6, 0xc2, 0xc9, 0x7a, 0x38, 0x22, 0x1c, 0x54, 0xcc, 0x6b, 0xc5, 0x15, 0x40, 0xef, 0xc9, 0xfc, 0x96, 0xa9, 0x13, 0x09, 0x69, 0x7c, 0x62, 0xc1, 0x69,
/* (2^ 8)P */ 0x0e, 0xdb, 0x33, 0x47, 0x2f, 0xfd, 0x86, 0x7a, 0xe9, 0x7d, 0x08, 0x9e, 0xf2, 0xc4, 0xb8, 0xfd, 0x29, 0xa2, 0xa2, 0x8e, 0x1a, 0x4b, 0x5e, 0x09, 0x79, 0x7a, 0xb3, 0x29, 0xc8, 0xa7, 0xd7, 0x1a,
/* (2^ 9)P */ 0xc0, 0xa0, 0x7e, 0xd1, 0xca, 0x89, 0x2d, 0x34, 0x51, 0x20, 0xed, 0xcc, 0xa6, 0xdd, 0xbe, 0x67, 0x74, 0x2f, 0xb4, 0x2b, 0xbf, 0x31, 0xca, 0x19, 0xbb, 0xac, 0x80, 0x49, 0xc8, 0xb4, 0xf7, 0x3d,
/* (2^ 10)P */ 0x83, 0xd8, 0x0a, 0xc8, 0x4d, 0x44, 0xc6, 0xa8, 0x85, 0xab, 0xe3, 0x66, 0x03, 0x44, 0x1e, 0xb9, 0xd8, 0xf6, 0x64, 0x01, 0xa0, 0xcd, 0x15, 0xc2, 0x68, 0xe6, 0x47, 0xf2, 0x6e, 0x7c, 0x86, 0x3d,
/* (2^ 11)P */ 0x8c, 0x65, 0x3e, 0xcc, 0x2b, 0x58, 0xdd, 0xc7, 0x28, 0x55, 0x0e, 0xee, 0x48, 0x47, 0x2c, 0xfd, 0x71, 0x4f, 0x9f, 0xcc, 0x95, 0x9b, 0xfd, 0xa0, 0xdf, 0x5d, 0x67, 0xb0, 0x71, 0xd8, 0x29, 0x75,
/* (2^ 12)P */ 0x78, 0xbd, 0x3c, 0x2d, 0xb4, 0x68, 0xf5, 0xb8, 0x82, 0xda, 0xf3, 0x91, 0x1b, 0x01, 0x33, 0x12, 0x62, 0x3b, 0x7c, 0x4a, 0xcd, 0x6c, 0xce, 0x2d, 0x03, 0x86, 0x49, 0x9e, 0x8e, 0xfc, 0xe7, 0x75,
/* (2^ 13)P */ 0xec, 0xb6, 0xd0, 0xfc, 0xf1, 0x13, 0x4f, 0x2f, 0x45, 0x7a, 0xff, 0x29, 0x1f, 0xca, 0xa8, 0xf1, 0x9b, 0xe2, 0x81, 0x29, 0xa7, 0xc1, 0x49, 0xc2, 0x6a, 0xb5, 0x83, 0x8c, 0xbb, 0x0d, 0xbe, 0x6e,
/* (2^ 14)P */ 0x22, 0xb2, 0x0b, 0x17, 0x8d, 0xfa, 0x14, 0x71, 0x5f, 0x93, 0x93, 0xbf, 0xd5, 0xdc, 0xa2, 0x65, 0x9a, 0x97, 0x9c, 0xb5, 0x68, 0x1f, 0xc4, 0xbd, 0x89, 0x92, 0xce, 0xa2, 0x79, 0xef, 0x0e, 0x2f,
/* (2^ 15)P */ 0xce, 0x37, 0x3c, 0x08, 0x0c, 0xbf, 0xec, 0x42, 0x22, 0x63, 0x49, 0xec, 0x09, 0xbc, 0x30, 0x29, 0x0d, 0xac, 0xfe, 0x9c, 0xc1, 0xb0, 0x94, 0xf2, 0x80, 0xbb, 0xfa, 0xed, 0x4b, 0xaa, 0x80, 0x37,
/* (2^ 16)P */ 0x29, 0xd9, 0xea, 0x7c, 0x3e, 0x7d, 0xc1, 0x56, 0xc5, 0x22, 0x57, 0x2e, 0xeb, 0x4b, 0xcb, 0xe7, 0x5a, 0xe1, 0xbf, 0x2d, 0x73, 0x31, 0xe9, 0x0c, 0xf8, 0x52, 0x10, 0x62, 0xc7, 0x83, 0xb8, 0x41,
/* (2^ 17)P */ 0x50, 0x53, 0xd2, 0xc3, 0xa0, 0x5c, 0xf7, 0xdb, 0x51, 0xe3, 0xb1, 0x6e, 0x08, 0xbe, 0x36, 0x29, 0x12, 0xb2, 0xa9, 0xb4, 0x3c, 0xe0, 0x36, 0xc9, 0xaa, 0x25, 0x22, 0x32, 0x82, 0xbf, 0x45, 0x1d,
/* (2^ 18)P */ 0xc5, 0x4c, 0x02, 0x6a, 0x03, 0xb1, 0x1a, 0xe8, 0x72, 0x9a, 0x4c, 0x30, 0x1c, 0x20, 0x12, 0xe2, 0xfc, 0xb1, 0x32, 0x68, 0xba, 0x3f, 0xd7, 0xc5, 0x81, 0x95, 0x83, 0x4d, 0x5a, 0xdb, 0xff, 0x20,
/* (2^ 19)P */ 0xad, 0x0f, 0x5d, 0xbe, 0x67, 0xd3, 0x83, 0xa2, 0x75, 0x44, 0x16, 0x8b, 0xca, 0x25, 0x2b, 0x6c, 0x2e, 0xf2, 0xaa, 0x7c, 0x46, 0x35, 0x49, 0x9d, 0x49, 0xff, 0x85, 0xee, 0x8e, 0x40, 0x66, 0x51,
/* (2^ 20)P */ 0x61, 0xe3, 0xb4, 0xfa, 0xa2, 0xba, 0x67, 0x3c, 0xef, 0x5c, 0xf3, 0x7e, 0xc6, 0x33, 0xe4, 0xb3, 0x1c, 0x9b, 0x15, 0x41, 0x92, 0x72, 0x59, 0x52, 0x33, 0xab, 0xb0, 0xd5, 0x92, 0x18, 0x62, 0x6a,
/* (2^ 21)P */ 0xcb, 0xcd, 0x55, 0x75, 0x38, 0x4a, 0xb7, 0x20, 0x3f, 0x92, 0x08, 0x12, 0x0e, 0xa1, 0x2a, 0x53, 0xd1, 0x1d, 0x28, 0x62, 0x77, 0x7b, 0xa1, 0xea, 0xbf, 0x44, 0x5c, 0xf0, 0x43, 0x34, 0xab, 0x61,
/* (2^ 22)P */ 0xf8, 0xde, 0x24, 0x23, 0x42, 0x6c, 0x7a, 0x25, 0x7f, 0xcf, 0xe3, 0x17, 0x10, 0x6c, 0x1c, 0x13, 0x57, 0xa2, 0x30, 0xf6, 0x39, 0x87, 0x75, 0x23, 0x80, 0x85, 0xa7, 0x01, 0x7a, 0x40, 0x5a, 0x29,
/* (2^ 23)P */ 0xd9, 0xa8, 0x5d, 0x6d, 0x24, 0x43, 0xc4, 0xf8, 0x5d, 0xfa, 0x52, 0x0c, 0x45, 0x75, 0xd7, 0x19, 0x3d, 0xf8, 0x1b, 0x73, 0x92, 0xfc, 0xfc, 0x2a, 0x00, 0x47, 0x2b, 0x1b, 0xe8, 0xc8, 0x10, 0x7d,
/* (2^ 24)P */ 0x0b, 0xa2, 0xba, 0x70, 0x1f, 0x27, 0xe0, 0xc8, 0x57, 0x39, 0xa6, 0x7c, 0x86, 0x48, 0x37, 0x99, 0xbb, 0xd4, 0x7e, 0xcb, 0xb3, 0xef, 0x12, 0x54, 0x75, 0x29, 0xe6, 0x73, 0x61, 0xd3, 0x96, 0x31,
/* (2^ 25)P */ 0xfc, 0xdf, 0xc7, 0x41, 0xd1, 0xca, 0x5b, 0xde, 0x48, 0xc8, 0x95, 0xb3, 0xd2, 0x8c, 0xcc, 0x47, 0xcb, 0xf3, 0x1a, 0xe1, 0x42, 0xd9, 0x4c, 0xa3, 0xc2, 0xce, 0x4e, 0xd0, 0xf2, 0xdb, 0x56, 0x02,
/* (2^ 26)P */ 0x7f, 0x66, 0x0e, 0x4b, 0xe9, 0xb7, 0x5a, 0x87, 0x10, 0x0d, 0x85, 0xc0, 0x83, 0xdd, 0xd4, 0xca, 0x9f, 0xc7, 0x72, 0x4e, 0x8f, 0x2e, 0xf1, 0x47, 0x9b, 0xb1, 0x85, 0x8c, 0xbb, 0x87, 0x1a, 0x5f,
/* (2^ 27)P */ 0xb8, 0x51, 0x7f, 0x43, 0xb6, 0xd0, 0xe9, 0x7a, 0x65, 0x90, 0x87, 0x18, 0x55, 0xce, 0xc7, 0x12, 0xee, 0x7a, 0xf7, 0x5c, 0xfe, 0x09, 0xde, 0x2a, 0x27, 0x56, 0x2c, 0x7d, 0x2f, 0x5a, 0xa0, 0x23,
/* (2^ 28)P */ 0x9a, 0x16, 0x7c, 0xf1, 0x28, 0xe1, 0x08, 0x59, 0x2d, 0x85, 0xd0, 0x8a, 0xdd, 0x98, 0x74, 0xf7, 0x64, 0x2f, 0x10, 0xab, 0xce, 0xc4, 0xb4, 0x74, 0x45, 0x98, 0x13, 0x10, 0xdd, 0xba, 0x3a, 0x18,
/* (2^ 29)P */ 0xac, 0xaa, 0x92, 0xaa, 0x8d, 0xba, 0x65, 0xb1, 0x05, 0x67, 0x38, 0x99, 0x95, 0xef, 0xc5, 0xd5, 0xd1, 0x40, 0xfc, 0xf8, 0x0c, 0x8f, 0x2f, 0xbe, 0x14, 0x45, 0x20, 0xee, 0x35, 0xe6, 0x01, 0x27,
/* (2^ 30)P */ 0x14, 0x65, 0x15, 0x20, 0x00, 0xa8, 0x9f, 0x62, 0xce, 0xc1, 0xa8, 0x64, 0x87, 0x86, 0x23, 0xf2, 0x0e, 0x06, 0x3f, 0x0b, 0xff, 0x4f, 0x89, 0x5b, 0xfa, 0xa3, 0x08, 0xf7, 0x4c, 0x94, 0xd9, 0x60,
/* (2^ 31)P */ 0x1f, 0x20, 0x7a, 0x1c, 0x1a, 0x00, 0xea, 0xae, 0x63, 0xce, 0xe2, 0x3e, 0x63, 0x6a, 0xf1, 0xeb, 0xe1, 0x07, 0x7a, 0x4c, 0x59, 0x09, 0x77, 0x6f, 0xcb, 0x08, 0x02, 0x0d, 0x15, 0x58, 0xb9, 0x79,
/* (2^ 32)P */ 0xe7, 0x10, 0xd4, 0x01, 0x53, 0x5e, 0xb5, 0x24, 0x4d, 0xc8, 0xfd, 0xf3, 0xdf, 0x4e, 0xa3, 0xe3, 0xd8, 0x32, 0x40, 0x90, 0xe4, 0x68, 0x87, 0xd8, 0xec, 0xae, 0x3a, 0x7b, 0x42, 0x84, 0x13, 0x13,
/* (2^ 33)P */ 0x14, 0x4f, 0x23, 0x86, 0x12, 0xe5, 0x05, 0x84, 0x29, 0xc5, 0xb4, 0xad, 0x39, 0x47, 0xdc, 0x14, 0xfd, 0x4f, 0x63, 0x50, 0xb2, 0xb5, 0xa2, 0xb8, 0x93, 0xff, 0xa7, 0xd8, 0x4a, 0xa9, 0xe2, 0x2f,
/* (2^ 34)P */ 0xdd, 0xfa, 0x43, 0xe8, 0xef, 0x57, 0x5c, 0xec, 0x18, 0x99, 0xbb, 0xf0, 0x40, 0xce, 0x43, 0x28, 0x05, 0x63, 0x3d, 0xcf, 0xd6, 0x61, 0xb5, 0xa4, 0x7e, 0x77, 0xfb, 0xe8, 0xbd, 0x29, 0x36, 0x74,
/* (2^ 35)P */ 0x8f, 0x73, 0xaf, 0xbb, 0x46, 0xdd, 0x3e, 0x34, 0x51, 0xa6, 0x01, 0xb1, 0x28, 0x18, 0x98, 0xed, 0x7a, 0x79, 0x2c, 0x88, 0x0b, 0x76, 0x01, 0xa4, 0x30, 0x87, 0xc8, 0x8d, 0xe2, 0x23, 0xc2, 0x1f,
/* (2^ 36)P */ 0x0e, 0xba, 0x0f, 0xfc, 0x91, 0x4e, 0x60, 0x48, 0xa4, 0x6f, 0x2c, 0x05, 0x8f, 0xf7, 0x37, 0xb6, 0x9c, 0x23, 0xe9, 0x09, 0x3d, 0xac, 0xcc, 0x91, 0x7c, 0x68, 0x7a, 0x43, 0xd4, 0xee, 0xf7, 0x23,
/* (2^ 37)P */ 0x00, 0xd8, 0x9b, 0x8d, 0x11, 0xb1, 0x73, 0x51, 0xa7, 0xd4, 0x89, 0x31, 0xb6, 0x41, 0xd6, 0x29, 0x86, 0xc5, 0xbb, 0x88, 0x79, 0x17, 0xbf, 0xfd, 0xf5, 0x1d, 0xd8, 0xca, 0x4f, 0x89, 0x59, 0x29,
/* (2^ 38)P */ 0x99, 0xc8, 0xbb, 0xb4, 0xf3, 0x8e, 0xbc, 0xae, 0xb9, 0x92, 0x69, 0xb2, 0x5a, 0x99, 0x48, 0x41, 0xfb, 0x2c, 0xf9, 0x34, 0x01, 0x0b, 0xe2, 0x24, 0xe8, 0xde, 0x05, 0x4a, 0x89, 0x58, 0xd1, 0x40,
/* (2^ 39)P */ 0xf6, 0x76, 0xaf, 0x85, 0x11, 0x0b, 0xb0, 0x46, 0x79, 0x7a, 0x18, 0x73, 0x78, 0xc7, 0xba, 0x26, 0x5f, 0xff, 0x8f, 0xab, 0x95, 0xbf, 0xc0, 0x3d, 0xd7, 0x24, 0x55, 0x94, 0xd8, 0x8b, 0x60, 0x2a,
/* (2^ 40)P */ 0x02, 0x63, 0x44, 0xbd, 0x88, 0x95, 0x44, 0x26, 0x9c, 0x43, 0x88, 0x03, 0x1c, 0xc2, 0x4b, 0x7c, 0xb2, 0x11, 0xbd, 0x83, 0xf3, 0xa4, 0x98, 0x8e, 0xb9, 0x76, 0xd8, 0xc9, 0x7b, 0x8d, 0x21, 0x26,
/* (2^ 41)P */ 0x8a, 0x17, 0x7c, 0x99, 0x42, 0x15, 0x08, 0xe3, 0x6f, 0x60, 0xb6, 0x6f, 0xa8, 0x29, 0x2d, 0x3c, 0x74, 0x93, 0x27, 0xfa, 0x36, 0x77, 0x21, 0x5c, 0xfa, 0xb1, 0xfe, 0x4a, 0x73, 0x05, 0xde, 0x7d,
/* (2^ 42)P */ 0xab, 0x2b, 0xd4, 0x06, 0x39, 0x0e, 0xf1, 0x3b, 0x9c, 0x64, 0x80, 0x19, 0x3e, 0x80, 0xf7, 0xe4, 0x7a, 0xbf, 0x95, 0x95, 0xf8, 0x3b, 0x05, 0xe6, 0x30, 0x55, 0x24, 0xda, 0x38, 0xaf, 0x4f, 0x39,
/* (2^ 43)P */ 0xf4, 0x28, 0x69, 0x89, 0x58, 0xfb, 0x8e, 0x7a, 0x3c, 0x11, 0x6a, 0xcc, 0xe9, 0x78, 0xc7, 0xfb, 0x6f, 0x59, 0xaf, 0x30, 0xe3, 0x0c, 0x67, 0x72, 0xf7, 0x6c, 0x3d, 0x1d, 0xa8, 0x22, 0xf2, 0x48,
/* (2^ 44)P */ 0xa7, 0xca, 0x72, 0x0d, 0x41, 0xce, 0x1f, 0xf0, 0x95, 0x55, 0x3b, 0x21, 0xc7, 0xec, 0x20, 0x5a, 0x83, 0x14, 0xfa, 0xc1, 0x65, 0x11, 0xc2, 0x7b, 0x41, 0xa7, 0xa8, 0x1d, 0xe3, 0x9a, 0xf8, 0x07,
/* (2^ 45)P */ 0xf9, 0x0f, 0x83, 0xc6, 0xb4, 0xc2, 0xd2, 0x05, 0x93, 0x62, 0x31, 0xc6, 0x0f, 0x33, 0x3e, 0xd4, 0x04, 0xa9, 0xd3, 0x96, 0x0a, 0x59, 0xa5, 0xa5, 0xb6, 0x33, 0x53, 0xa6, 0x91, 0xdb, 0x5e, 0x70,
/* (2^ 46)P */ 0xf7, 0xa5, 0xb9, 0x0b, 0x5e, 0xe1, 0x8e, 0x04, 0x5d, 0xaf, 0x0a, 0x9e, 0xca, 0xcf, 0x40, 0x32, 0x0b, 0xa4, 0xc4, 0xed, 0xce, 0x71, 0x4b, 0x8f, 0x6d, 0x4a, 0x54, 0xde, 0xa3, 0x0d, 0x1c, 0x62,
/* (2^ 47)P */ 0x91, 0x40, 0x8c, 0xa0, 0x36, 0x28, 0x87, 0x92, 0x45, 0x14, 0xc9, 0x10, 0xb0, 0x75, 0x83, 0xce, 0x94, 0x63, 0x27, 0x4f, 0x52, 0xeb, 0x72, 0x8a, 0x35, 0x36, 0xc8, 0x7e, 0xfa, 0xfc, 0x67, 0x26,
/* (2^ 48)P */ 0x2a, 0x75, 0xe8, 0x45, 0x33, 0x17, 0x4c, 0x7f, 0xa5, 0x79, 0x70, 0xee, 0xfe, 0x47, 0x1b, 0x06, 0x34, 0xff, 0x86, 0x9f, 0xfa, 0x9a, 0xdd, 0x25, 0x9c, 0xc8, 0x5d, 0x42, 0xf5, 0xce, 0x80, 0x37,
/* (2^ 49)P */ 0xe9, 0xb4, 0x3b, 0x51, 0x5a, 0x03, 0x46, 0x1a, 0xda, 0x5a, 0x57, 0xac, 0x79, 0xf3, 0x1e, 0x3e, 0x50, 0x4b, 0xa2, 0x5f, 0x1c, 0x5f, 0x8c, 0xc7, 0x22, 0x9f, 0xfd, 0x34, 0x76, 0x96, 0x1a, 0x32,
/* (2^ 50)P */ 0xfa, 0x27, 0x6e, 0x82, 0xb8, 0x07, 0x67, 0x94, 0xd0, 0x6f, 0x50, 0x4c, 0xd6, 0x84, 0xca, 0x3d, 0x36, 0x14, 0xe9, 0x75, 0x80, 0x21, 0x89, 0xc1, 0x84, 0x84, 0x3b, 0x9b, 0x16, 0x84, 0x92, 0x6d,
/* (2^ 51)P */ 0xdf, 0x2d, 0x3f, 0x38, 0x40, 0xe8, 0x67, 0x3a, 0x75, 0x9b, 0x4f, 0x0c, 0xa3, 0xc9, 0xee, 0x33, 0x47, 0xef, 0x83, 0xa7, 0x6f, 0xc8, 0xc7, 0x3e, 0xc4, 0xfb, 0xc9, 0xba, 0x9f, 0x44, 0xec, 0x26,
/* (2^ 52)P */ 0x7d, 0x9e, 0x9b, 0xa0, 0xcb, 0x38, 0x0f, 0x5c, 0x8c, 0x47, 0xa3, 0x62, 0xc7, 0x8c, 0x16, 0x81, 0x1c, 0x12, 0xfc, 0x06, 0xd3, 0xb0, 0x23, 0x3e, 0xdd, 0xdc, 0xef, 0xa5, 0xa0, 0x8a, 0x23, 0x5a,
/* (2^ 53)P */ 0xff, 0x43, 0xea, 0xc4, 0x21, 0x61, 0xa2, 0x1b, 0xb5, 0x32, 0x88, 0x7c, 0x7f, 0xc7, 0xf8, 0x36, 0x9a, 0xf9, 0xdc, 0x0a, 0x0b, 0xea, 0xfb, 0x88, 0xf9, 0xeb, 0x5b, 0xc2, 0x8e, 0x93, 0xa9, 0x5c,
/* (2^ 54)P */ 0xa0, 0xcd, 0xfc, 0x51, 0x5e, 0x6a, 0x43, 0xd5, 0x3b, 0x89, 0xcd, 0xc2, 0x97, 0x47, 0xbc, 0x1d, 0x08, 0x4a, 0x22, 0xd3, 0x65, 0x6a, 0x34, 0x19, 0x66, 0xf4, 0x9a, 0x9b, 0xe4, 0x34, 0x50, 0x0f,
/* (2^ 55)P */ 0x6e, 0xb9, 0xe0, 0xa1, 0x67, 0x39, 0x3c, 0xf2, 0x88, 0x4d, 0x7a, 0x86, 0xfa, 0x08, 0x8b, 0xe5, 0x79, 0x16, 0x34, 0xa7, 0xc6, 0xab, 0x2f, 0xfb, 0x46, 0x69, 0x02, 0xb6, 0x1e, 0x38, 0x75, 0x2a,
/* (2^ 56)P */ 0xac, 0x20, 0x94, 0xc1, 0xe4, 0x3b, 0x0a, 0xc8, 0xdc, 0xb6, 0xf2, 0x81, 0xc6, 0xf6, 0xb1, 0x66, 0x88, 0x33, 0xe9, 0x61, 0x67, 0x03, 0xf7, 0x7c, 0xc4, 0xa4, 0x60, 0xa6, 0xd8, 0xbb, 0xab, 0x25,
/* (2^ 57)P */ 0x98, 0x51, 0xfd, 0x14, 0xba, 0x12, 0xea, 0x91, 0xa9, 0xff, 0x3c, 0x4a, 0xfc, 0x50, 0x49, 0x68, 0x28, 0xad, 0xf5, 0x30, 0x21, 0x84, 0x26, 0xf8, 0x41, 0xa4, 0x01, 0x53, 0xf7, 0x88, 0xa9, 0x3e,
/* (2^ 58)P */ 0x6f, 0x8c, 0x5f, 0x69, 0x9a, 0x10, 0x78, 0xc9, 0xf3, 0xc3, 0x30, 0x05, 0x4a, 0xeb, 0x46, 0x17, 0x95, 0x99, 0x45, 0xb4, 0x77, 0x6d, 0x4d, 0x44, 0xc7, 0x5c, 0x4e, 0x05, 0x8c, 0x2b, 0x95, 0x75,
/* (2^ 59)P */ 0xaa, 0xd6, 0xf4, 0x15, 0x79, 0x3f, 0x70, 0xa3, 0xd8, 0x47, 0x26, 0x2f, 0x20, 0x46, 0xc3, 0x66, 0x4b, 0x64, 0x1d, 0x81, 0xdf, 0x69, 0x14, 0xd0, 0x1f, 0xd7, 0xa5, 0x81, 0x7d, 0xa4, 0xfe, 0x77,
/* (2^ 60)P */ 0x81, 0xa3, 0x7c, 0xf5, 0x9e, 0x52, 0xe9, 0xc5, 0x1a, 0x88, 0x2f, 0xce, 0xb9, 0xb4, 0xee, 0x6e, 0xd6, 0x9b, 0x00, 0xe8, 0x28, 0x1a, 0xe9, 0xb6, 0xec, 0x3f, 0xfc, 0x9a, 0x3e, 0xbe, 0x80, 0x4b,
/* (2^ 61)P */ 0xc5, 0xd2, 0xae, 0x26, 0xc5, 0x73, 0x37, 0x7e, 0x9d, 0xa4, 0xc9, 0x53, 0xb4, 0xfc, 0x4a, 0x1b, 0x4d, 0xb2, 0xff, 0xba, 0xd7, 0xbd, 0x20, 0xa9, 0x0e, 0x40, 0x2d, 0x12, 0x9f, 0x69, 0x54, 0x7c,
/* (2^ 62)P */ 0xc8, 0x4b, 0xa9, 0x4f, 0xe1, 0xc8, 0x46, 0xef, 0x5e, 0xed, 0x52, 0x29, 0xce, 0x74, 0xb0, 0xe0, 0xd5, 0x85, 0xd8, 0xdb, 0xe1, 0x50, 0xa4, 0xbe, 0x2c, 0x71, 0x0f, 0x32, 0x49, 0x86, 0xb6, 0x61,
/* (2^ 63)P */ 0xd1, 0xbd, 0xcc, 0x09, 0x73, 0x5f, 0x48, 0x8a, 0x2d, 0x1a, 0x4d, 0x7d, 0x0d, 0x32, 0x06, 0xbd, 0xf4, 0xbe, 0x2d, 0x32, 0x73, 0x29, 0x23, 0x25, 0x70, 0xf7, 0x17, 0x8c, 0x75, 0xc4, 0x5d, 0x44,
/* (2^ 64)P */ 0x3c, 0x93, 0xc8, 0x7c, 0x17, 0x34, 0x04, 0xdb, 0x9f, 0x05, 0xea, 0x75, 0x21, 0xe8, 0x6f, 0xed, 0x34, 0xdb, 0x53, 0xc0, 0xfd, 0xbe, 0xfe, 0x1e, 0x99, 0xaf, 0x5d, 0xc6, 0x67, 0xe8, 0xdb, 0x4a,
/* (2^ 65)P */ 0xdf, 0x09, 0x06, 0xa9, 0xa2, 0x71, 0xcd, 0x3a, 0x50, 0x40, 0xd0, 0x6d, 0x85, 0x91, 0xe9, 0xe5, 0x3c, 0xc2, 0x57, 0x81, 0x68, 0x9b, 0xc6, 0x1e, 0x4d, 0xfe, 0x5c, 0x88, 0xf6, 0x27, 0x74, 0x69,
/* (2^ 66)P */ 0x51, 0xa8, 0xe1, 0x65, 0x9b, 0x7b, 0xbe, 0xd7, 0xdd, 0x36, 0xc5, 0x22, 0xd5, 0x28, 0x3d, 0xa0, 0x45, 0xb6, 0xd2, 0x8f, 0x65, 0x9d, 0x39, 0x28, 0xe1, 0x41, 0x26, 0x7c, 0xe1, 0xb7, 0xe5, 0x49,
/* (2^ 67)P */ 0xa4, 0x57, 0x04, 0x70, 0x98, 0x3a, 0x8c, 0x6f, 0x78, 0x67, 0xbb, 0x5e, 0xa2, 0xf0, 0x78, 0x50, 0x0f, 0x96, 0x82, 0xc3, 0xcb, 0x3c, 0x3c, 0xd1, 0xb1, 0x84, 0xdf, 0xa7, 0x58, 0x32, 0x00, 0x2e,
/* (2^ 68)P */ 0x1c, 0x6a, 0x29, 0xe6, 0x9b, 0xf3, 0xd1, 0x8a, 0xb2, 0xbf, 0x5f, 0x2a, 0x65, 0xaa, 0xee, 0xc1, 0xcb, 0xf3, 0x26, 0xfd, 0x73, 0x06, 0xee, 0x33, 0xcc, 0x2c, 0x9d, 0xa6, 0x73, 0x61, 0x25, 0x59,
/* (2^ 69)P */ 0x41, 0xfc, 0x18, 0x4e, 0xaa, 0x07, 0xea, 0x41, 0x1e, 0xa5, 0x87, 0x7c, 0x52, 0x19, 0xfc, 0xd9, 0x6f, 0xca, 0x31, 0x58, 0x80, 0xcb, 0xaa, 0xbd, 0x4f, 0x69, 0x16, 0xc9, 0x2d, 0x65, 0x5b, 0x44,
/* (2^ 70)P */ 0x15, 0x23, 0x17, 0xf2, 0xa7, 0xa3, 0x92, 0xce, 0x64, 0x99, 0x1b, 0xe1, 0x2d, 0x28, 0xdc, 0x1e, 0x4a, 0x31, 0x4c, 0xe0, 0xaf, 0x3a, 0x82, 0xa1, 0x86, 0xf5, 0x7c, 0x43, 0x94, 0x2d, 0x0a, 0x79,
/* (2^ 71)P */ 0x09, 0xe0, 0xf6, 0x93, 0xfb, 0x47, 0xc4, 0x71, 0x76, 0x52, 0x84, 0x22, 0x67, 0xa5, 0x22, 0x89, 0x69, 0x51, 0x4f, 0x20, 0x3b, 0x90, 0x70, 0xbf, 0xfe, 0x19, 0xa3, 0x1b, 0x89, 0x89, 0x7a, 0x2f,
/* (2^ 72)P */ 0x0c, 0x14, 0xe2, 0x77, 0xb5, 0x8e, 0xa0, 0x02, 0xf4, 0xdc, 0x7b, 0x42, 0xd4, 0x4e, 0x9a, 0xed, 0xd1, 0x3c, 0x32, 0xe4, 0x44, 0xec, 0x53, 0x52, 0x5b, 0x35, 0xe9, 0x14, 0x3c, 0x36, 0x88, 0x3e,
/* (2^ 73)P */ 0x8c, 0x0b, 0x11, 0x77, 0x42, 0xc1, 0x66, 0xaa, 0x90, 0x33, 0xa2, 0x10, 0x16, 0x39, 0xe0, 0x1a, 0xa2, 0xc2, 0x3f, 0xc9, 0x12, 0xbd, 0x30, 0x20, 0xab, 0xc7, 0x55, 0x95, 0x57, 0x41, 0xe1, 0x3e,
/* (2^ 74)P */ 0x41, 0x7d, 0x6e, 0x6d, 0x3a, 0xde, 0x14, 0x92, 0xfe, 0x7e, 0xf1, 0x07, 0x86, 0xd8, 0xcd, 0x3c, 0x17, 0x12, 0xe1, 0xf8, 0x88, 0x12, 0x4f, 0x67, 0xd0, 0x93, 0x9f, 0x32, 0x0f, 0x25, 0x82, 0x56,
/* (2^ 75)P */ 0x6e, 0x39, 0x2e, 0x6d, 0x13, 0x0b, 0xf0, 0x6c, 0xbf, 0xde, 0x14, 0x10, 0x6f, 0xf8, 0x4c, 0x6e, 0x83, 0x4e, 0xcc, 0xbf, 0xb5, 0xb1, 0x30, 0x59, 0xb6, 0x16, 0xba, 0x8a, 0xb4, 0x69, 0x70, 0x04,
/* (2^ 76)P */ 0x93, 0x07, 0xb2, 0x69, 0xab, 0xe4, 0x4c, 0x0d, 0x9e, 0xfb, 0xd0, 0x97, 0x1a, 0xb9, 0x4d, 0xb2, 0x1d, 0xd0, 0x00, 0x4e, 0xf5, 0x50, 0xfa, 0xcd, 0xb5, 0xdd, 0x8b, 0x36, 0x85, 0x10, 0x1b, 0x22,
/* (2^ 77)P */ 0xd2, 0xd8, 0xe3, 0xb1, 0x68, 0x94, 0xe5, 0xe7, 0x93, 0x2f, 0x12, 0xbd, 0x63, 0x65, 0xc5, 0x53, 0x09, 0x3f, 0x66, 0xe0, 0x03, 0xa9, 0xe8, 0xee, 0x42, 0x3d, 0xbe, 0xcb, 0x62, 0xa6, 0xef, 0x61,
/* (2^ 78)P */ 0x2a, 0xab, 0x6e, 0xde, 0xdd, 0xdd, 0xf8, 0x2c, 0x31, 0xf2, 0x35, 0x14, 0xd5, 0x0a, 0xf8, 0x9b, 0x73, 0x49, 0xf0, 0xc9, 0xce, 0xda, 0xea, 0x5d, 0x27, 0x9b, 0xd2, 0x41, 0x5d, 0x5b, 0x27, 0x29,
/* (2^ 79)P */ 0x4f, 0xf1, 0xeb, 0x95, 0x08, 0x0f, 0xde, 0xcf, 0xa7, 0x05, 0x49, 0x05, 0x6b, 0xb9, 0xaa, 0xb9, 0xfd, 0x20, 0xc4, 0xa1, 0xd9, 0x0d, 0xe8, 0xca, 0xc7, 0xbb, 0x73, 0x16, 0x2f, 0xbf, 0x63, 0x0a,
/* (2^ 80)P */ 0x8c, 0xbc, 0x8f, 0x95, 0x11, 0x6e, 0x2f, 0x09, 0xad, 0x2f, 0x82, 0x04, 0xe8, 0x81, 0x2a, 0x67, 0x17, 0x25, 0xd5, 0x60, 0x15, 0x35, 0xc8, 0xca, 0xf8, 0x92, 0xf1, 0xc8, 0x22, 0x77, 0x3f, 0x6f,
/* (2^ 81)P */ 0xb7, 0x94, 0xe8, 0xc2, 0xcc, 0x90, 0xba, 0xf8, 0x0d, 0x9f, 0xff, 0x38, 0xa4, 0x57, 0x75, 0x2c, 0x59, 0x23, 0xe5, 0x5a, 0x85, 0x1d, 0x4d, 0x89, 0x69, 0x3d, 0x74, 0x7b, 0x15, 0x22, 0xe1, 0x68,
/* (2^ 82)P */ 0xf3, 0x19, 0xb9, 0xcf, 0x70, 0x55, 0x7e, 0xd8, 0xb9, 0x8d, 0x79, 0x95, 0xcd, 0xde, 0x2c, 0x3f, 0xce, 0xa2, 0xc0, 0x10, 0x47, 0x15, 0x21, 0x21, 0xb2, 0xc5, 0x6d, 0x24, 0x15, 0xa1, 0x66, 0x3c,
/* (2^ 83)P */ 0x72, 0xcb, 0x4e, 0x29, 0x62, 0xc5, 0xed, 0xcb, 0x16, 0x0b, 0x28, 0x6a, 0xc3, 0x43, 0x71, 0xba, 0x67, 0x8b, 0x07, 0xd4, 0xef, 0xc2, 0x10, 0x96, 0x1e, 0x4b, 0x6a, 0x94, 0x5d, 0x73, 0x44, 0x61,
/* (2^ 84)P */ 0x50, 0x33, 0x5b, 0xd7, 0x1e, 0x11, 0x6f, 0x53, 0x1b, 0xd8, 0x41, 0x20, 0x8c, 0xdb, 0x11, 0x02, 0x3c, 0x41, 0x10, 0x0e, 0x00, 0xb1, 0x3c, 0xf9, 0x76, 0x88, 0x9e, 0x03, 0x3c, 0xfd, 0x9d, 0x14,
/* (2^ 85)P */ 0x5b, 0x15, 0x63, 0x6b, 0xe4, 0xdd, 0x79, 0xd4, 0x76, 0x79, 0x83, 0x3c, 0xe9, 0x15, 0x6e, 0xb6, 0x38, 0xe0, 0x13, 0x1f, 0x3b, 0xe4, 0xfd, 0xda, 0x35, 0x0b, 0x4b, 0x2e, 0x1a, 0xda, 0xaf, 0x5f,
/* (2^ 86)P */ 0x81, 0x75, 0x19, 0x17, 0xdf, 0xbb, 0x00, 0x36, 0xc2, 0xd2, 0x3c, 0xbe, 0x0b, 0x05, 0x72, 0x39, 0x86, 0xbe, 0xd5, 0xbd, 0x6d, 0x90, 0x38, 0x59, 0x0f, 0x86, 0x9b, 0x3f, 0xe4, 0xe5, 0xfc, 0x34,
/* (2^ 87)P */ 0x02, 0x4d, 0xd1, 0x42, 0xcd, 0xa4, 0xa8, 0x75, 0x65, 0xdf, 0x41, 0x34, 0xc5, 0xab, 0x8d, 0x82, 0xd3, 0x31, 0xe1, 0xd2, 0xed, 0xab, 0xdc, 0x33, 0x5f, 0xd2, 0x14, 0xb8, 0x6f, 0xd7, 0xba, 0x3e,
/* (2^ 88)P */ 0x0f, 0xe1, 0x70, 0x6f, 0x56, 0x6f, 0x90, 0xd4, 0x5a, 0x0f, 0x69, 0x51, 0xaa, 0xf7, 0x12, 0x5d, 0xf2, 0xfc, 0xce, 0x76, 0x6e, 0xb1, 0xad, 0x45, 0x99, 0x29, 0x23, 0xad, 0xae, 0x68, 0xf7, 0x01,
/* (2^ 89)P */ 0xbd, 0xfe, 0x48, 0x62, 0x7b, 0xc7, 0x6c, 0x2b, 0xfd, 0xaf, 0x3a, 0xec, 0x28, 0x06, 0xd3, 0x3c, 0x6a, 0x48, 0xef, 0xd4, 0x80, 0x0b, 0x1c, 0xce, 0x23, 0x6c, 0xf6, 0xa6, 0x2e, 0xff, 0x3b, 0x4c,
/* (2^ 90)P */ 0x5f, 0xeb, 0xea, 0x4a, 0x09, 0xc4, 0x2e, 0x3f, 0xa7, 0x2c, 0x37, 0x6e, 0x28, 0x9b, 0xb1, 0x61, 0x1d, 0x70, 0x2a, 0xde, 0x66, 0xa9, 0xef, 0x5e, 0xef, 0xe3, 0x55, 0xde, 0x65, 0x05, 0xb2, 0x23,
/* (2^ 91)P */ 0x57, 0x85, 0xd5, 0x79, 0x52, 0xca, 0x01, 0xe3, 0x4f, 0x87, 0xc2, 0x27, 0xce, 0xd4, 0xb2, 0x07, 0x67, 0x1d, 0xcf, 0x9d, 0x8a, 0xcd, 0x32, 0xa5, 0x56, 0xff, 0x2b, 0x3f, 0xe2, 0xfe, 0x52, 0x2a,
/* (2^ 92)P */ 0x3d, 0x66, 0xd8, 0x7c, 0xb3, 0xef, 0x24, 0x86, 0x94, 0x75, 0xbd, 0xff, 0x20, 0xac, 0xc7, 0xbb, 0x45, 0x74, 0xd3, 0x82, 0x9c, 0x5e, 0xb8, 0x57, 0x66, 0xec, 0xa6, 0x86, 0xcb, 0x52, 0x30, 0x7b,
/* (2^ 93)P */ 0x1e, 0xe9, 0x25, 0x25, 0xad, 0xf0, 0x82, 0x34, 0xa0, 0xdc, 0x8e, 0xd2, 0x43, 0x80, 0xb6, 0x2c, 0x3a, 0x00, 0x1b, 0x2e, 0x05, 0x6d, 0x4f, 0xaf, 0x0a, 0x1b, 0x78, 0x29, 0x25, 0x8c, 0x5f, 0x18,
/* (2^ 94)P */ 0xd6, 0xe0, 0x0c, 0xd8, 0x5b, 0xde, 0x41, 0xaa, 0xd6, 0xe9, 0x53, 0x68, 0x41, 0xb2, 0x07, 0x94, 0x3a, 0x4c, 0x7f, 0x35, 0x6e, 0xc3, 0x3e, 0x56, 0xce, 0x7b, 0x29, 0x0e, 0xdd, 0xb8, 0xc4, 0x4c,
/* (2^ 95)P */ 0x0e, 0x73, 0xb8, 0xff, 0x52, 0x1a, 0xfc, 0xa2, 0x37, 0x8e, 0x05, 0x67, 0x6e, 0xf1, 0x11, 0x18, 0xe1, 0x4e, 0xdf, 0xcd, 0x66, 0xa3, 0xf9, 0x10, 0x99, 0xf0, 0xb9, 0xa0, 0xc4, 0xa0, 0xf4, 0x72,
/* (2^ 96)P */ 0xa7, 0x4e, 0x3f, 0x66, 0x6f, 0xc0, 0x16, 0x8c, 0xba, 0x0f, 0x97, 0x4e, 0xf7, 0x3a, 0x3b, 0x69, 0x45, 0xc3, 0x9e, 0xd6, 0xf1, 0xe7, 0x02, 0x21, 0x89, 0x80, 0x8a, 0x96, 0xbc, 0x3c, 0xa5, 0x0b,
/* (2^ 97)P */ 0x37, 0x55, 0xa1, 0xfe, 0xc7, 0x9d, 0x3d, 0xca, 0x93, 0x64, 0x53, 0x51, 0xbb, 0x24, 0x68, 0x4c, 0xb1, 0x06, 0x40, 0x84, 0x14, 0x63, 0x88, 0xb9, 0x60, 0xcc, 0x54, 0xb4, 0x2a, 0xa7, 0xd2, 0x40,
/* (2^ 98)P */ 0x75, 0x09, 0x57, 0x12, 0xb7, 0xa1, 0x36, 0x59, 0x57, 0xa6, 0xbd, 0xde, 0x48, 0xd6, 0xb9, 0x91, 0xea, 0x30, 0x43, 0xb6, 0x4b, 0x09, 0x44, 0x33, 0xd0, 0x51, 0xee, 0x12, 0x0d, 0xa1, 0x6b, 0x00,
/* (2^ 99)P */ 0x58, 0x5d, 0xde, 0xf5, 0x68, 0x84, 0x22, 0x19, 0xb0, 0x05, 0xcc, 0x38, 0x4c, 0x2f, 0xb1, 0x0e, 0x90, 0x19, 0x60, 0xd5, 0x9d, 0x9f, 0x03, 0xa1, 0x0b, 0x0e, 0xff, 0x4f, 0xce, 0xd4, 0x02, 0x45,
/* (2^100)P */ 0x89, 0xc1, 0x37, 0x68, 0x10, 0x54, 0x20, 0xeb, 0x3c, 0xb9, 0xd3, 0x6d, 0x4c, 0x54, 0xf6, 0xd0, 0x4f, 0xd7, 0x16, 0xc4, 0x64, 0x70, 0x72, 0x40, 0xf0, 0x2e, 0x50, 0x4b, 0x11, 0xc6, 0x15, 0x6e,
/* (2^101)P */ 0x6b, 0xa7, 0xb1, 0xcf, 0x98, 0xa3, 0xf2, 0x4d, 0xb1, 0xf6, 0xf2, 0x19, 0x74, 0x6c, 0x25, 0x11, 0x43, 0x60, 0x6e, 0x06, 0x62, 0x79, 0x49, 0x4a, 0x44, 0x5b, 0x35, 0x41, 0xab, 0x3a, 0x5b, 0x70,
/* (2^102)P */ 0xd8, 0xb1, 0x97, 0xd7, 0x36, 0xf5, 0x5e, 0x36, 0xdb, 0xf0, 0xdd, 0x22, 0xd6, 0x6b, 0x07, 0x00, 0x88, 0x5a, 0x57, 0xe0, 0xb0, 0x33, 0xbf, 0x3b, 0x4d, 0xca, 0xe4, 0xc8, 0x05, 0xaa, 0x77, 0x37,
/* (2^103)P */ 0x5f, 0xdb, 0x78, 0x55, 0xc8, 0x45, 0x27, 0x39, 0xe2, 0x5a, 0xae, 0xdb, 0x49, 0x41, 0xda, 0x6f, 0x67, 0x98, 0xdc, 0x8a, 0x0b, 0xb0, 0xf0, 0xb1, 0xa3, 0x1d, 0x6f, 0xd3, 0x37, 0x34, 0x96, 0x09,
/* (2^104)P */ 0x53, 0x38, 0xdc, 0xa5, 0x90, 0x4e, 0x82, 0x7e, 0xbd, 0x5c, 0x13, 0x1f, 0x64, 0xf6, 0xb5, 0xcc, 0xcc, 0x8f, 0xce, 0x87, 0x6c, 0xd8, 0x36, 0x67, 0x9f, 0x24, 0x04, 0x66, 0xe2, 0x3c, 0x5f, 0x62,
/* (2^105)P */ 0x3f, 0xf6, 0x02, 0x95, 0x05, 0xc8, 0x8a, 0xaf, 0x69, 0x14, 0x35, 0x2e, 0x0a, 0xe7, 0x05, 0x0c, 0x05, 0x63, 0x4b, 0x76, 0x9c, 0x2e, 0x29, 0x35, 0xc3, 0x3a, 0xe2, 0xc7, 0x60, 0x43, 0x39, 0x1a,
/* (2^106)P */ 0x64, 0x32, 0x18, 0x51, 0x32, 0xd5, 0xc6, 0xd5, 0x4f, 0xb7, 0xc2, 0x43, 0xbd, 0x5a, 0x06, 0x62, 0x9b, 0x3f, 0x97, 0x3b, 0xd0, 0xf5, 0xfb, 0xb5, 0x5e, 0x6e, 0x20, 0x61, 0x36, 0xda, 0xa3, 0x13,
/* (2^107)P */ 0xe5, 0x94, 0x5d, 0x72, 0x37, 0x58, 0xbd, 0xc6, 0xc5, 0x16, 0x50, 0x20, 0x12, 0x09, 0xe3, 0x18, 0x68, 0x3c, 0x03, 0x70, 0x15, 0xce, 0x88, 0x20, 0x87, 0x79, 0x83, 0x5c, 0x49, 0x1f, 0xba, 0x7f,
/* (2^108)P */ 0x9d, 0x07, 0xf9, 0xf2, 0x23, 0x74, 0x8c, 0x5a, 0xc5, 0x3f, 0x02, 0x34, 0x7b, 0x15, 0x35, 0x17, 0x51, 0xb3, 0xfa, 0xd2, 0x9a, 0xb4, 0xf9, 0xe4, 0x3c, 0xe3, 0x78, 0xc8, 0x72, 0xff, 0x91, 0x66,
/* (2^109)P */ 0x3e, 0xff, 0x5e, 0xdc, 0xde, 0x2a, 0x2c, 0x12, 0xf4, 0x6c, 0x95, 0xd8, 0xf1, 0x4b, 0xdd, 0xf8, 0xda, 0x5b, 0x9e, 0x9e, 0x5d, 0x20, 0x86, 0xeb, 0x43, 0xc7, 0x75, 0xd9, 0xb9, 0x92, 0x9b, 0x04,
/* (2^110)P */ 0x5a, 0xc0, 0xf6, 0xb0, 0x30, 0x97, 0x37, 0xa5, 0x53, 0xa5, 0xf3, 0xc6, 0xac, 0xff, 0xa0, 0x72, 0x6d, 0xcd, 0x0d, 0xb2, 0x34, 0x2c, 0x03, 0xb0, 0x4a, 0x16, 0xd5, 0x88, 0xbc, 0x9d, 0x0e, 0x47,
/* (2^111)P */ 0x47, 0xc0, 0x37, 0xa2, 0x0c, 0xf1, 0x9c, 0xb1, 0xa2, 0x81, 0x6c, 0x1f, 0x71, 0x66, 0x54, 0xb6, 0x43, 0x0b, 0xd8, 0x6d, 0xd1, 0x1b, 0x32, 0xb3, 0x8e, 0xbe, 0x5f, 0x0c, 0x60, 0x4f, 0xc1, 0x48,
/* (2^112)P */ 0x03, 0xc8, 0xa6, 0x4a, 0x26, 0x1c, 0x45, 0x66, 0xa6, 0x7d, 0xfa, 0xa4, 0x04, 0x39, 0x6e, 0xb6, 0x95, 0x83, 0x12, 0xb3, 0xb0, 0x19, 0x5f, 0xd4, 0x10, 0xbc, 0xc9, 0xc3, 0x27, 0x26, 0x60, 0x31,
/* (2^113)P */ 0x0d, 0xe1, 0xe4, 0x32, 0x48, 0xdc, 0x20, 0x31, 0xf7, 0x17, 0xc7, 0x56, 0x67, 0xc4, 0x20, 0xeb, 0x94, 0x02, 0x28, 0x67, 0x3f, 0x2e, 0xf5, 0x00, 0x09, 0xc5, 0x30, 0x47, 0xc1, 0x4f, 0x6d, 0x56,
/* (2^114)P */ 0x06, 0x72, 0x83, 0xfd, 0x40, 0x5d, 0x3a, 0x7e, 0x7a, 0x54, 0x59, 0x71, 0xdc, 0x26, 0xe9, 0xc1, 0x95, 0x60, 0x8d, 0xa6, 0xfb, 0x30, 0x67, 0x21, 0xa7, 0xce, 0x69, 0x3f, 0x84, 0xc3, 0xe8, 0x22,
/* (2^115)P */ 0x2b, 0x4b, 0x0e, 0x93, 0xe8, 0x74, 0xd0, 0x33, 0x16, 0x58, 0xd1, 0x84, 0x0e, 0x35, 0xe4, 0xb6, 0x65, 0x23, 0xba, 0xd6, 0x6a, 0xc2, 0x34, 0x55, 0xf3, 0xf3, 0xf1, 0x89, 0x2f, 0xc1, 0x73, 0x77,
/* (2^116)P */ 0xaa, 0x62, 0x79, 0xa5, 0x4d, 0x40, 0xba, 0x8c, 0x56, 0xce, 0x99, 0x19, 0xa8, 0x97, 0x98, 0x5b, 0xfc, 0x92, 0x16, 0x12, 0x2f, 0x86, 0x8e, 0x50, 0x91, 0xc2, 0x93, 0xa0, 0x7f, 0x90, 0x81, 0x3a,
/* (2^117)P */ 0x10, 0xa5, 0x25, 0x47, 0xff, 0xd0, 0xde, 0x0d, 0x03, 0xc5, 0x3f, 0x67, 0x10, 0xcc, 0xd8, 0x10, 0x89, 0x4e, 0x1f, 0x9f, 0x1c, 0x15, 0x9d, 0x5b, 0x4c, 0xa4, 0x09, 0xcb, 0xd5, 0xc1, 0xa5, 0x32,
/* (2^118)P */ 0xfb, 0x41, 0x05, 0xb9, 0x42, 0xa4, 0x0a, 0x1e, 0xdb, 0x85, 0xb4, 0xc1, 0x7c, 0xeb, 0x85, 0x5f, 0xe5, 0xf2, 0x9d, 0x8a, 0xce, 0x95, 0xe5, 0xbe, 0x36, 0x22, 0x42, 0x22, 0xc7, 0x96, 0xe4, 0x25,
/* (2^119)P */ 0xb9, 0xe5, 0x0f, 0xcd, 0x46, 0x3c, 0xdf, 0x5e, 0x88, 0x33, 0xa4, 0xd2, 0x7e, 0x5a, 0xe7, 0x34, 0x52, 0xe3, 0x61, 0xd7, 0x11, 0xde, 0x88, 0xe4, 0x5c, 0x54, 0x85, 0xa0, 0x01, 0x8a, 0x87, 0x0e,
/* (2^120)P */ 0x04, 0xbb, 0x21, 0xe0, 0x77, 0x3c, 0x49, 0xba, 0x9a, 0x89, 0xdf, 0xc7, 0x43, 0x18, 0x4d, 0x2b, 0x67, 0x0d, 0xe8, 0x7a, 0x48, 0x7a, 0xa3, 0x9e, 0x94, 0x17, 0xe4, 0x11, 0x80, 0x95, 0xa9, 0x67,
/* (2^121)P */ 0x65, 0xb0, 0x97, 0x66, 0x1a, 0x05, 0x58, 0x4b, 0xd4, 0xa6, 0x6b, 0x8d, 0x7d, 0x3f, 0xe3, 0x47, 0xc1, 0x46, 0xca, 0x83, 0xd4, 0xa8, 0x4d, 0xbb, 0x0d, 0xdb, 0xc2, 0x81, 0xa1, 0xca, 0xbe, 0x68,
/* (2^122)P */ 0xa5, 0x9a, 0x98, 0x0b, 0xe9, 0x80, 0x89, 0x8d, 0x9b, 0xc9, 0x93, 0x2c, 0x4a, 0xb1, 0x5e, 0xf9, 0xa2, 0x73, 0x6e, 0x79, 0xc4, 0xc7, 0xc6, 0x51, 0x69, 0xb5, 0xef, 0xb5, 0x63, 0x83, 0x22, 0x6e,
/* (2^123)P */ 0xc8, 0x24, 0xd6, 0x2d, 0xb0, 0xc0, 0xbb, 0xc6, 0xee, 0x70, 0x81, 0xec, 0x7d, 0xb4, 0x7e, 0x77, 0xa9, 0xaf, 0xcf, 0x04, 0xa0, 0x15, 0xde, 0x3c, 0x9b, 0xbf, 0x60, 0x71, 0x08, 0xbc, 0xc6, 0x1d,
/* (2^124)P */ 0x02, 0x40, 0xc3, 0xee, 0x43, 0xe0, 0x07, 0x2e, 0x7f, 0xdc, 0x68, 0x7a, 0x67, 0xfc, 0xe9, 0x18, 0x9a, 0x5b, 0xd1, 0x8b, 0x18, 0x03, 0xda, 0xd8, 0x53, 0x82, 0x56, 0x00, 0xbb, 0xc3, 0xfb, 0x48,
/* (2^125)P */ 0xe1, 0x4c, 0x65, 0xfb, 0x4c, 0x7d, 0x54, 0x57, 0xad, 0xe2, 0x58, 0xa0, 0x82, 0x5b, 0x56, 0xd3, 0x78, 0x44, 0x15, 0xbf, 0x0b, 0xaf, 0x3e, 0xf6, 0x18, 0xbb, 0xdf, 0x14, 0xf1, 0x1e, 0x53, 0x47,
/* (2^126)P */ 0x87, 0xc5, 0x78, 0x42, 0x0a, 0x63, 0xec, 0xe1, 0xf3, 0x83, 0x8e, 0xca, 0x46, 0xd5, 0x07, 0x55, 0x2b, 0x0c, 0xdc, 0x3a, 0xc6, 0x35, 0xe1, 0x85, 0x4e, 0x84, 0x82, 0x56, 0xa8, 0xef, 0xa7, 0x0a,
/* (2^127)P */ 0x15, 0xf6, 0xe1, 0xb3, 0xa8, 0x1b, 0x69, 0x72, 0xfa, 0x3f, 0xbe, 0x1f, 0x70, 0xe9, 0xb4, 0x32, 0x68, 0x78, 0xbb, 0x39, 0x2e, 0xd9, 0xb6, 0x97, 0xe8, 0x39, 0x2e, 0xa0, 0xde, 0x53, 0xfe, 0x2c,
/* (2^128)P */ 0xb0, 0x52, 0xcd, 0x85, 0xcd, 0x92, 0x73, 0x68, 0x31, 0x98, 0xe2, 0x10, 0xc9, 0x66, 0xff, 0x27, 0x06, 0x2d, 0x83, 0xa9, 0x56, 0x45, 0x13, 0x97, 0xa0, 0xf8, 0x84, 0x0a, 0x36, 0xb0, 0x9b, 0x26,
/* (2^129)P */ 0x5c, 0xf8, 0x43, 0x76, 0x45, 0x55, 0x6e, 0x70, 0x1b, 0x7d, 0x59, 0x9b, 0x8c, 0xa4, 0x34, 0x37, 0x72, 0xa4, 0xef, 0xc6, 0xe8, 0x91, 0xee, 0x7a, 0xe0, 0xd9, 0xa9, 0x98, 0xc1, 0xab, 0xd6, 0x5c,
/* (2^130)P */ 0x1a, 0xe4, 0x3c, 0xcb, 0x06, 0xde, 0x04, 0x0e, 0x38, 0xe1, 0x02, 0x34, 0x89, 0xeb, 0xc6, 0xd8, 0x72, 0x37, 0x6e, 0x68, 0xbb, 0x59, 0x46, 0x90, 0xc8, 0xa8, 0x6b, 0x74, 0x71, 0xc3, 0x15, 0x72,
/* (2^131)P */ 0xd9, 0xa2, 0xe4, 0xea, 0x7e, 0xa9, 0x12, 0xfd, 0xc5, 0xf2, 0x94, 0x63, 0x51, 0xb7, 0x14, 0x95, 0x94, 0xf2, 0x08, 0x92, 0x80, 0xd5, 0x6f, 0x26, 0xb9, 0x26, 0x9a, 0x61, 0x85, 0x70, 0x84, 0x5c,
/* (2^132)P */ 0xea, 0x94, 0xd6, 0xfe, 0x10, 0x54, 0x98, 0x52, 0x54, 0xd2, 0x2e, 0x4a, 0x93, 0x5b, 0x90, 0x3c, 0x67, 0xe4, 0x3b, 0x2d, 0x69, 0x47, 0xbb, 0x10, 0xe1, 0xe9, 0xe5, 0x69, 0x2d, 0x3d, 0x3b, 0x06,
/* (2^133)P */ 0xeb, 0x7d, 0xa5, 0xdd, 0xee, 0x26, 0x27, 0x47, 0x91, 0x18, 0xf4, 0x10, 0xae, 0xc4, 0xb6, 0xef, 0x14, 0x76, 0x30, 0x7b, 0x91, 0x41, 0x16, 0x2b, 0x7c, 0x5b, 0xf4, 0xc4, 0x4f, 0x55, 0x7c, 0x11,
/* (2^134)P */ 0x12, 0x88, 0x9d, 0x8f, 0x11, 0xf3, 0x7c, 0xc0, 0x39, 0x79, 0x01, 0x50, 0x20, 0xd8, 0xdb, 0x01, 0x27, 0x28, 0x1b, 0x17, 0xf4, 0x03, 0xe8, 0xd7, 0xea, 0x25, 0xd2, 0x87, 0x74, 0xe8, 0x15, 0x10,
/* (2^135)P */ 0x4d, 0xcc, 0x3a, 0xd2, 0xfe, 0xe3, 0x8d, 0xc5, 0x2d, 0xbe, 0xa7, 0x94, 0xc2, 0x91, 0xdb, 0x50, 0x57, 0xf4, 0x9c, 0x1c, 0x3d, 0xd4, 0x94, 0x0b, 0x4a, 0x52, 0x37, 0x6e, 0xfa, 0x40, 0x16, 0x6b,
/* (2^136)P */ 0x09, 0x0d, 0xda, 0x5f, 0x6c, 0x34, 0x2f, 0x69, 0x51, 0x31, 0x4d, 0xfa, 0x59, 0x1c, 0x0b, 0x20, 0x96, 0xa2, 0x77, 0x07, 0x76, 0x6f, 0xc4, 0xb8, 0xcf, 0xfb, 0xfd, 0x3f, 0x5f, 0x39, 0x38, 0x4b,
/* (2^137)P */ 0x71, 0xd6, 0x54, 0xbe, 0x00, 0x5e, 0xd2, 0x18, 0xa6, 0xab, 0xc8, 0xbe, 0x82, 0x05, 0xd5, 0x60, 0x82, 0xb9, 0x78, 0x3b, 0x26, 0x8f, 0xad, 0x87, 0x32, 0x04, 0xda, 0x9c, 0x4e, 0xf6, 0xfd, 0x50,
/* (2^138)P */ 0xf0, 0xdc, 0x78, 0xc5, 0xaa, 0x67, 0xf5, 0x90, 0x3b, 0x13, 0xa3, 0xf2, 0x0e, 0x9b, 0x1e, 0xef, 0x71, 0xde, 0xd9, 0x42, 0x92, 0xba, 0xeb, 0x0e, 0xc7, 0x01, 0x31, 0xf0, 0x9b, 0x3c, 0x47, 0x15,
/* (2^139)P */ 0x95, 0x80, 0xb7, 0x56, 0xae, 0xe8, 0x77, 0x7c, 0x8e, 0x07, 0x6f, 0x6e, 0x66, 0xe7, 0x78, 0xb6, 0x1f, 0xba, 0x48, 0x53, 0x61, 0xb9, 0xa0, 0x2d, 0x0b, 0x3f, 0x73, 0xff, 0xc1, 0x31, 0xf9, 0x7c,
/* (2^140)P */ 0x6c, 0x36, 0x0a, 0x0a, 0xf5, 0x57, 0xb3, 0x26, 0x32, 0xd7, 0x87, 0x2b, 0xf4, 0x8c, 0x70, 0xe9, 0xc0, 0xb2, 0x1c, 0xf9, 0xa5, 0xee, 0x3a, 0xc1, 0x4c, 0xbb, 0x43, 0x11, 0x99, 0x0c, 0xd9, 0x35,
/* (2^141)P */ 0xdc, 0xd9, 0xa0, 0xa9, 0x04, 0xc4, 0xc1, 0x47, 0x51, 0xd2, 0x72, 0x19, 0x45, 0x58, 0x9e, 0x65, 0x31, 0x8c, 0xb3, 0x73, 0xc4, 0xa8, 0x75, 0x38, 0x24, 0x1f, 0x56, 0x79, 0xd3, 0x9e, 0xbd, 0x1f,
/* (2^142)P */ 0x8d, 0xc2, 0x1e, 0xd4, 0x6f, 0xbc, 0xfa, 0x11, 0xca, 0x2d, 0x2a, 0xcd, 0xe3, 0xdf, 0xf8, 0x7e, 0x95, 0x45, 0x40, 0x8c, 0x5d, 0x3b, 0xe7, 0x72, 0x27, 0x2f, 0xb7, 0x54, 0x49, 0xfa, 0x35, 0x61,
/* (2^143)P */ 0x9c, 0xb6, 0x24, 0xde, 0xa2, 0x32, 0xfc, 0xcc, 0x88, 0x5d, 0x09, 0x1f, 0x8c, 0x69, 0x55, 0x3f, 0x29, 0xf9, 0xc3, 0x5a, 0xed, 0x50, 0x33, 0xbe, 0xeb, 0x7e, 0x47, 0xca, 0x06, 0xf8, 0x9b, 0x5e,
/* (2^144)P */ 0x68, 0x9f, 0x30, 0x3c, 0xb6, 0x8f, 0xce, 0xe9, 0xf4, 0xf9, 0xe1, 0x65, 0x35, 0xf6, 0x76, 0x53, 0xf1, 0x93, 0x63, 0x5a, 0xb3, 0xcf, 0xaf, 0xd1, 0x06, 0x35, 0x62, 0xe5, 0xed, 0xa1, 0x32, 0x66,
/* (2^145)P */ 0x4c, 0xed, 0x2d, 0x0c, 0x39, 0x6c, 0x7d, 0x0b, 0x1f, 0xcb, 0x04, 0xdf, 0x81, 0x32, 0xcb, 0x56, 0xc7, 0xc3, 0xec, 0x49, 0x12, 0x5a, 0x30, 0x66, 0x2a, 0xa7, 0x8c, 0xa3, 0x60, 0x8b, 0x58, 0x5d,
/* (2^146)P */ 0x2d, 0xf4, 0xe5, 0xe8, 0x78, 0xbf, 0xec, 0xa6, 0xec, 0x3e, 0x8a, 0x3c, 0x4b, 0xb4, 0xee, 0x86, 0x04, 0x16, 0xd2, 0xfb, 0x48, 0x9c, 0x21, 0xec, 0x31, 0x67, 0xc3, 0x17, 0xf5, 0x1a, 0xaf, 0x1a,
/* (2^147)P */ 0xe7, 0xbd, 0x69, 0x67, 0x83, 0xa2, 0x06, 0xc3, 0xdb, 0x2a, 0x1e, 0x2b, 0x62, 0x80, 0x82, 0x20, 0xa6, 0x94, 0xff, 0xfb, 0x1f, 0xf5, 0x27, 0x80, 0x6b, 0xf2, 0x24, 0x11, 0xce, 0xa1, 0xcf, 0x76,
/* (2^148)P */ 0xb6, 0xab, 0x22, 0x24, 0x56, 0x00, 0xeb, 0x18, 0xc3, 0x29, 0x8c, 0x8f, 0xd5, 0xc4, 0x77, 0xf3, 0x1a, 0x56, 0x31, 0xf5, 0x07, 0xc2, 0xbb, 0x4d, 0x27, 0x8a, 0x12, 0x82, 0xf0, 0xb7, 0x53, 0x02,
/* (2^149)P */ 0xe0, 0x17, 0x2c, 0xb6, 0x1c, 0x09, 0x1f, 0x3d, 0xa9, 0x28, 0x46, 0xd6, 0xab, 0xe1, 0x60, 0x48, 0x53, 0x42, 0x9d, 0x30, 0x36, 0x74, 0xd1, 0x52, 0x76, 0xe5, 0xfa, 0x3e, 0xe1, 0x97, 0x6f, 0x35,
/* (2^150)P */ 0x5b, 0x53, 0x50, 0xa1, 0x1a, 0xe1, 0x51, 0xd3, 0xcc, 0x78, 0xd8, 0x1d, 0xbb, 0x45, 0x6b, 0x3e, 0x98, 0x2c, 0xd9, 0xbe, 0x28, 0x61, 0x77, 0x0c, 0xb8, 0x85, 0x28, 0x03, 0x93, 0xae, 0x34, 0x1d,
/* (2^151)P */ 0xc3, 0xa4, 0x5b, 0xa8, 0x8c, 0x48, 0xa0, 0x4b, 0xce, 0xe6, 0x9c, 0x3c, 0xc3, 0x48, 0x53, 0x98, 0x70, 0xa7, 0xbd, 0x97, 0x6f, 0x4c, 0x12, 0x66, 0x4a, 0x12, 0x54, 0x06, 0x29, 0xa0, 0x81, 0x0f,
/* (2^152)P */ 0xfd, 0x86, 0x9b, 0x56, 0xa6, 0x9c, 0xd0, 0x9e, 0x2d, 0x9a, 0xaf, 0x18, 0xfd, 0x09, 0x10, 0x81, 0x0a, 0xc2, 0xd8, 0x93, 0x3f, 0xd0, 0x08, 0xff, 0x6b, 0xf2, 0xae, 0x9f, 0x19, 0x48, 0xa1, 0x52,
/* (2^153)P */ 0x73, 0x1b, 0x8d, 0x2d, 0xdc, 0xf9, 0x03, 0x3e, 0x70, 0x1a, 0x96, 0x73, 0x18, 0x80, 0x05, 0x42, 0x70, 0x59, 0xa3, 0x41, 0xf0, 0x87, 0xd9, 0xc0, 0x49, 0xd5, 0xc0, 0xa1, 0x15, 0x1f, 0xaa, 0x07,
/* (2^154)P */ 0x24, 0x72, 0xd2, 0x8c, 0xe0, 0x6c, 0xd4, 0xdf, 0x39, 0x42, 0x4e, 0x93, 0x4f, 0x02, 0x0a, 0x6d, 0x59, 0x7b, 0x89, 0x99, 0x63, 0x7a, 0x8a, 0x80, 0xa2, 0x95, 0x3d, 0xe1, 0xe9, 0x56, 0x45, 0x0a,
/* (2^155)P */ 0x45, 0x30, 0xc1, 0xe9, 0x1f, 0x99, 0x1a, 0xd2, 0xb8, 0x51, 0x77, 0xfe, 0x48, 0x85, 0x0e, 0x9b, 0x35, 0x00, 0xf3, 0x4b, 0xcb, 0x43, 0xa6, 0x5d, 0x21, 0xf7, 0x40, 0x39, 0xd6, 0x28, 0xdb, 0x77,
/* (2^156)P */ 0x11, 0x90, 0xdc, 0x4a, 0x61, 0xeb, 0x5e, 0xfc, 0xeb, 0x11, 0xc4, 0xe8, 0x9a, 0x41, 0x29, 0x52, 0x74, 0xcf, 0x1d, 0x7d, 0x78, 0xe7, 0xc3, 0x9e, 0xb5, 0x4c, 0x6e, 0x21, 0x3e, 0x05, 0x0d, 0x34,
/* (2^157)P */ 0xb4, 0xf2, 0x8d, 0xb4, 0x39, 0xaf, 0xc7, 0xca, 0x94, 0x0a, 0xa1, 0x71, 0x28, 0xec, 0xfa, 0xc0, 0xed, 0x75, 0xa5, 0x5c, 0x24, 0x69, 0x0a, 0x14, 0x4c, 0x3a, 0x27, 0x34, 0x71, 0xc3, 0xf1, 0x0c,
/* (2^158)P */ 0xa5, 0xb8, 0x24, 0xc2, 0x6a, 0x30, 0xee, 0xc8, 0xb0, 0x30, 0x49, 0xcb, 0x7c, 0xee, 0xea, 0x57, 0x4f, 0xe7, 0xcb, 0xaa, 0xbd, 0x06, 0xe8, 0xa1, 0x7d, 0x65, 0xeb, 0x2e, 0x74, 0x62, 0x9a, 0x7d,
/* (2^159)P */ 0x30, 0x48, 0x6c, 0x54, 0xef, 0xb6, 0xb6, 0x9e, 0x2e, 0x6e, 0xb3, 0xdd, 0x1f, 0xca, 0x5c, 0x88, 0x05, 0x71, 0x0d, 0xef, 0x83, 0xf3, 0xb9, 0xe6, 0x12, 0x04, 0x2e, 0x9d, 0xef, 0x4f, 0x65, 0x58,
/* (2^160)P */ 0x26, 0x8e, 0x0e, 0xbe, 0xff, 0xc4, 0x05, 0xa9, 0x6e, 0x81, 0x31, 0x9b, 0xdf, 0xe5, 0x2d, 0x94, 0xe1, 0x88, 0x2e, 0x80, 0x3f, 0x72, 0x7d, 0x49, 0x8d, 0x40, 0x2f, 0x60, 0xea, 0x4d, 0x68, 0x30,
/* (2^161)P */ 0x34, 0xcb, 0xe6, 0xa3, 0x78, 0xa2, 0xe5, 0x21, 0xc4, 0x1d, 0x15, 0x5b, 0x6f, 0x6e, 0xfb, 0xae, 0x15, 0xca, 0x77, 0x9d, 0x04, 0x8e, 0x0b, 0xb3, 0x81, 0x89, 0xb9, 0x53, 0xcf, 0xc9, 0xc3, 0x28,
/* (2^162)P */ 0x2a, 0xdd, 0x6c, 0x55, 0x21, 0xb7, 0x7f, 0x28, 0x74, 0x22, 0x02, 0x97, 0xa8, 0x7c, 0x31, 0x0d, 0x58, 0x32, 0x54, 0x3a, 0x42, 0xc7, 0x68, 0x74, 0x2f, 0x64, 0xb5, 0x4e, 0x46, 0x11, 0x7f, 0x4a,
/* (2^163)P */ 0xa6, 0x3a, 0x19, 0x4d, 0x77, 0xa4, 0x37, 0xa2, 0xa1, 0x29, 0x21, 0xa9, 0x6e, 0x98, 0x65, 0xd8, 0x88, 0x1a, 0x7c, 0xf8, 0xec, 0x15, 0xc5, 0x24, 0xeb, 0xf5, 0x39, 0x5f, 0x57, 0x03, 0x40, 0x60,
/* (2^164)P */ 0x27, 0x9b, 0x0a, 0x57, 0x89, 0xf1, 0xb9, 0x47, 0x78, 0x4b, 0x5e, 0x46, 0xde, 0xce, 0x98, 0x2b, 0x20, 0x5c, 0xb8, 0xdb, 0x51, 0xf5, 0x6d, 0x02, 0x01, 0x19, 0xe2, 0x47, 0x10, 0xd9, 0xfc, 0x74,
/* (2^165)P */ 0xa3, 0xbf, 0xc1, 0x23, 0x0a, 0xa9, 0xe2, 0x13, 0xf6, 0x19, 0x85, 0x47, 0x4e, 0x07, 0xb0, 0x0c, 0x44, 0xcf, 0xf6, 0x3a, 0xbe, 0xcb, 0xf1, 0x5f, 0xbe, 0x2d, 0x81, 0xbe, 0x38, 0x54, 0xfe, 0x67,
/* (2^166)P */ 0xb0, 0x05, 0x0f, 0xa4, 0x4f, 0xf6, 0x3c, 0xd1, 0x87, 0x37, 0x28, 0x32, 0x2f, 0xfb, 0x4d, 0x05, 0xea, 0x2a, 0x0d, 0x7f, 0x5b, 0x91, 0x73, 0x41, 0x4e, 0x0d, 0x61, 0x1f, 0x4f, 0x14, 0x2f, 0x48,
/* (2^167)P */ 0x34, 0x82, 0x7f, 0xb4, 0x01, 0x02, 0x21, 0xf6, 0x90, 0xb9, 0x70, 0x9e, 0x92, 0xe1, 0x0a, 0x5d, 0x7c, 0x56, 0x49, 0xb0, 0x55, 0xf4, 0xd7, 0xdc, 0x01, 0x6f, 0x91, 0xf0, 0xf1, 0xd0, 0x93, 0x7e,
/* (2^168)P */ 0xfa, 0xb4, 0x7d, 0x8a, 0xf1, 0xcb, 0x79, 0xdd, 0x2f, 0xc6, 0x74, 0x6f, 0xbf, 0x91, 0x83, 0xbe, 0xbd, 0x91, 0x82, 0x4b, 0xd1, 0x45, 0x71, 0x02, 0x05, 0x17, 0xbf, 0x2c, 0xea, 0x73, 0x5a, 0x58,
/* (2^169)P */ 0xb2, 0x0d, 0x8a, 0x92, 0x3e, 0xa0, 0x5c, 0x48, 0xe7, 0x57, 0x28, 0x74, 0xa5, 0x01, 0xfc, 0x10, 0xa7, 0x51, 0xd5, 0xd6, 0xdb, 0x2e, 0x48, 0x2f, 0x8a, 0xdb, 0x8f, 0x04, 0xb5, 0x33, 0x04, 0x0f,
/* (2^170)P */ 0x47, 0x62, 0xdc, 0xd7, 0x8d, 0x2e, 0xda, 0x60, 0x9a, 0x81, 0xd4, 0x8c, 0xd3, 0xc9, 0xb4, 0x88, 0x97, 0x66, 0xf6, 0x01, 0xc0, 0x3a, 0x03, 0x13, 0x75, 0x7d, 0x36, 0x3b, 0xfe, 0x24, 0x3b, 0x27,
/* (2^171)P */ 0xd4, 0xb9, 0xb3, 0x31, 0x6a, 0xf6, 0xe8, 0xc6, 0xd5, 0x49, 0xdf, 0x94, 0xa4, 0x14, 0x15, 0x28, 0xa7, 0x3d, 0xb2, 0xc8, 0xdf, 0x6f, 0x72, 0xd1, 0x48, 0xe5, 0xde, 0x03, 0xd1, 0xe7, 0x3a, 0x4b,
/* (2^172)P */ 0x7e, 0x9d, 0x4b, 0xce, 0x19, 0x6e, 0x25, 0xc6, 0x1c, 0xc6, 0xe3, 0x86, 0xf1, 0x5c, 0x5c, 0xff, 0x45, 0xc1, 0x8e, 0x4b, 0xa3, 0x3c, 0xc6, 0xac, 0x74, 0x65, 0xe6, 0xfe, 0x88, 0x18, 0x62, 0x74,
/* (2^173)P */ 0x1e, 0x0a, 0x29, 0x45, 0x96, 0x40, 0x6f, 0x95, 0x2e, 0x96, 0x3a, 0x26, 0xe3, 0xf8, 0x0b, 0xef, 0x7b, 0x64, 0xc2, 0x5e, 0xeb, 0x50, 0x6a, 0xed, 0x02, 0x75, 0xca, 0x9d, 0x3a, 0x28, 0x94, 0x06,
/* (2^174)P */ 0xd1, 0xdc, 0xa2, 0x43, 0x36, 0x96, 0x9b, 0x76, 0x53, 0x53, 0xfc, 0x09, 0xea, 0xc8, 0xb7, 0x42, 0xab, 0x7e, 0x39, 0x13, 0xee, 0x2a, 0x00, 0x4f, 0x3a, 0xd6, 0xb7, 0x19, 0x2c, 0x5e, 0x00, 0x63,
/* (2^175)P */ 0xea, 0x3b, 0x02, 0x63, 0xda, 0x36, 0x67, 0xca, 0xb7, 0x99, 0x2a, 0xb1, 0x6d, 0x7f, 0x6c, 0x96, 0xe1, 0xc5, 0x37, 0xc5, 0x90, 0x93, 0xe0, 0xac, 0xee, 0x89, 0xaa, 0xa1, 0x63, 0x60, 0x69, 0x0b,
/* (2^176)P */ 0xe5, 0x56, 0x8c, 0x28, 0x97, 0x3e, 0xb0, 0xeb, 0xe8, 0x8b, 0x8c, 0x93, 0x9f, 0x9f, 0x2a, 0x43, 0x71, 0x7f, 0x71, 0x5b, 0x3d, 0xa9, 0xa5, 0xa6, 0x97, 0x9d, 0x8f, 0xe1, 0xc3, 0xb4, 0x5f, 0x1a,
/* (2^177)P */ 0xce, 0xcd, 0x60, 0x1c, 0xad, 0xe7, 0x94, 0x1c, 0xa0, 0xc4, 0x02, 0xfc, 0x43, 0x2a, 0x20, 0xee, 0x20, 0x6a, 0xc4, 0x67, 0xd8, 0xe4, 0xaf, 0x8d, 0x58, 0x7b, 0xc2, 0x8a, 0x3c, 0x26, 0x10, 0x0a,
/* (2^178)P */ 0x4a, 0x2a, 0x43, 0xe4, 0xdf, 0xa9, 0xde, 0xd0, 0xc5, 0x77, 0x92, 0xbe, 0x7b, 0xf8, 0x6a, 0x85, 0x1a, 0xc7, 0x12, 0xc2, 0xac, 0x72, 0x84, 0xce, 0x91, 0x1e, 0xbb, 0x9b, 0x6d, 0x1b, 0x15, 0x6f,
/* (2^179)P */ 0x6a, 0xd5, 0xee, 0x7c, 0x52, 0x6c, 0x77, 0x26, 0xec, 0xfa, 0xf8, 0xfb, 0xb7, 0x1c, 0x21, 0x7d, 0xcc, 0x09, 0x46, 0xfd, 0xa6, 0x66, 0xae, 0x37, 0x42, 0x0c, 0x77, 0xd2, 0x02, 0xb7, 0x81, 0x1f,
/* (2^180)P */ 0x92, 0x83, 0xc5, 0xea, 0x57, 0xb0, 0xb0, 0x2f, 0x9d, 0x4e, 0x74, 0x29, 0xfe, 0x89, 0xdd, 0xe1, 0xf8, 0xb4, 0xbe, 0x17, 0xeb, 0xf8, 0x64, 0xc9, 0x1e, 0xd4, 0xa2, 0xc9, 0x73, 0x10, 0x57, 0x29,
/* (2^181)P */ 0x54, 0xe2, 0xc0, 0x81, 0x89, 0xa1, 0x48, 0xa9, 0x30, 0x28, 0xb2, 0x65, 0x9b, 0x36, 0xf6, 0x2d, 0xc6, 0xd3, 0xcf, 0x5f, 0xd7, 0xb2, 0x3e, 0xa3, 0x1f, 0xa0, 0x99, 0x41, 0xec, 0xd6, 0x8c, 0x07,
/* (2^182)P */ 0x2f, 0x0d, 0x90, 0xad, 0x41, 0x4a, 0x58, 0x4a, 0x52, 0x4c, 0xc7, 0xe2, 0x78, 0x2b, 0x14, 0x32, 0x78, 0xc9, 0x31, 0x84, 0x33, 0xe8, 0xc4, 0x68, 0xc2, 0x9f, 0x68, 0x08, 0x90, 0xea, 0x69, 0x7f,
/* (2^183)P */ 0x65, 0x82, 0xa3, 0x46, 0x1e, 0xc8, 0xf2, 0x52, 0xfd, 0x32, 0xa8, 0x04, 0x2d, 0x07, 0x78, 0xfd, 0x94, 0x9e, 0x35, 0x25, 0xfa, 0xd5, 0xd7, 0x8c, 0xd2, 0x29, 0xcc, 0x54, 0x74, 0x1b, 0xe7, 0x4d,
/* (2^184)P */ 0xc9, 0x6a, 0xda, 0x1e, 0xad, 0x60, 0xeb, 0x42, 0x3a, 0x9c, 0xc0, 0xdb, 0xdf, 0x37, 0xad, 0x0a, 0x91, 0xc1, 0x3c, 0xe3, 0x71, 0x4b, 0x00, 0x81, 0x3c, 0x80, 0x22, 0x51, 0x34, 0xbe, 0xe6, 0x44,
/* (2^185)P */ 0xdb, 0x20, 0x19, 0xba, 0x88, 0x83, 0xfe, 0x03, 0x08, 0xb0, 0x0d, 0x15, 0x32, 0x7c, 0xd5, 0xf5, 0x29, 0x0c, 0xf6, 0x1a, 0x28, 0xc4, 0xc8, 0x49, 0xee, 0x1a, 0x70, 0xde, 0x18, 0xb5, 0xed, 0x21,
/* (2^186)P */ 0x99, 0xdc, 0x06, 0x8f, 0x41, 0x3e, 0xb6, 0x7f, 0xb8, 0xd7, 0x66, 0xc1, 0x99, 0x0d, 0x46, 0xa4, 0x83, 0x0a, 0x52, 0xce, 0x48, 0x52, 0xdd, 0x24, 0x58, 0x83, 0x92, 0x2b, 0x71, 0xad, 0xc3, 0x5e,
/* (2^187)P */ 0x0f, 0x93, 0x17, 0xbd, 0x5f, 0x2a, 0x02, 0x15, 0xe3, 0x70, 0x25, 0xd8, 0x77, 0x4a, 0xf6, 0xa4, 0x12, 0x37, 0x78, 0x15, 0x69, 0x8d, 0xbc, 0x12, 0xbb, 0x0a, 0x62, 0xfc, 0xc0, 0x94, 0x81, 0x49,
/* (2^188)P */ 0x82, 0x6c, 0x68, 0x55, 0xd2, 0xd9, 0xa2, 0x38, 0xf0, 0x21, 0x3e, 0x19, 0xd9, 0x6b, 0x5c, 0x78, 0x84, 0x54, 0x4a, 0xb2, 0x1a, 0xc8, 0xd5, 0xe4, 0x89, 0x09, 0xe2, 0xb2, 0x60, 0x78, 0x30, 0x56,
/* (2^189)P */ 0xc4, 0x74, 0x4d, 0x8b, 0xf7, 0x55, 0x9d, 0x42, 0x31, 0x01, 0x35, 0x43, 0x46, 0x83, 0xf1, 0x22, 0xff, 0x1f, 0xc7, 0x98, 0x45, 0xc2, 0x60, 0x1e, 0xef, 0x83, 0x99, 0x97, 0x14, 0xf0, 0xf2, 0x59,
/* (2^190)P */ 0x44, 0x4a, 0x49, 0xeb, 0x56, 0x7d, 0xa4, 0x46, 0x8e, 0xa1, 0x36, 0xd6, 0x54, 0xa8, 0x22, 0x3e, 0x3b, 0x1c, 0x49, 0x74, 0x52, 0xe1, 0x46, 0xb3, 0xe7, 0xcd, 0x90, 0x53, 0x4e, 0xfd, 0xea, 0x2c,
/* (2^191)P */ 0x75, 0x66, 0x0d, 0xbe, 0x38, 0x85, 0x8a, 0xba, 0x23, 0x8e, 0x81, 0x50, 0xbb, 0x74, 0x90, 0x4b, 0xc3, 0x04, 0xd3, 0x85, 0x90, 0xb8, 0xda, 0xcb, 0xc4, 0x92, 0x61, 0xe5, 0xe0, 0x4f, 0xa2, 0x61,
/* (2^192)P */ 0xcb, 0x5b, 0x52, 0xdb, 0xe6, 0x15, 0x76, 0xcb, 0xca, 0xe4, 0x67, 0xa5, 0x35, 0x8c, 0x7d, 0xdd, 0x69, 0xdd, 0xfc, 0xca, 0x3a, 0x15, 0xb4, 0xe6, 0x66, 0x97, 0x3c, 0x7f, 0x09, 0x8e, 0x66, 0x2d,
/* (2^193)P */ 0xf0, 0x5e, 0xe5, 0x5c, 0x26, 0x7e, 0x7e, 0xa5, 0x67, 0xb9, 0xd4, 0x7c, 0x52, 0x4e, 0x9f, 0x5d, 0xe5, 0xd1, 0x2f, 0x49, 0x06, 0x36, 0xc8, 0xfb, 0xae, 0xf7, 0xc3, 0xb7, 0xbe, 0x52, 0x0d, 0x09,
/* (2^194)P */ 0x7c, 0x4d, 0x7b, 0x1e, 0x5a, 0x51, 0xb9, 0x09, 0xc0, 0x44, 0xda, 0x99, 0x25, 0x6a, 0x26, 0x1f, 0x04, 0x55, 0xc5, 0xe2, 0x48, 0x95, 0xc4, 0xa1, 0xcc, 0x15, 0x6f, 0x12, 0x87, 0x42, 0xf0, 0x7e,
/* (2^195)P */ 0x15, 0xef, 0x30, 0xbd, 0x9d, 0x65, 0xd1, 0xfe, 0x7b, 0x27, 0xe0, 0xc4, 0xee, 0xb9, 0x4a, 0x8b, 0x91, 0x32, 0xdf, 0xa5, 0x36, 0x62, 0x4d, 0x88, 0x88, 0xf7, 0x5c, 0xbf, 0xa6, 0x6e, 0xd9, 0x1f,
/* (2^196)P */ 0x9a, 0x0d, 0x19, 0x1f, 0x98, 0x61, 0xa1, 0x42, 0xc1, 0x52, 0x60, 0x7e, 0x50, 0x49, 0xd8, 0x61, 0xd5, 0x2c, 0x5a, 0x28, 0xbf, 0x13, 0xe1, 0x9f, 0xd8, 0x85, 0xad, 0xdb, 0x76, 0xd6, 0x22, 0x7c,
/* (2^197)P */ 0x7d, 0xd2, 0xfb, 0x2b, 0xed, 0x70, 0xe7, 0x82, 0xa5, 0xf5, 0x96, 0xe9, 0xec, 0xb2, 0x05, 0x4c, 0x50, 0x01, 0x90, 0xb0, 0xc2, 0xa9, 0x40, 0xcd, 0x64, 0xbf, 0xd9, 0x13, 0x92, 0x31, 0x95, 0x58,
/* (2^198)P */ 0x08, 0x2e, 0xea, 0x3f, 0x70, 0x5d, 0xcc, 0xe7, 0x8c, 0x18, 0xe2, 0x58, 0x12, 0x49, 0x0c, 0xb5, 0xf0, 0x5b, 0x20, 0x48, 0xaa, 0x0b, 0xe3, 0xcc, 0x62, 0x2d, 0xa3, 0xcf, 0x9c, 0x65, 0x7c, 0x53,
/* (2^199)P */ 0x88, 0xc0, 0xcf, 0x98, 0x3a, 0x62, 0xb6, 0x37, 0xa4, 0xac, 0xd6, 0xa4, 0x1f, 0xed, 0x9b, 0xfe, 0xb0, 0xd1, 0xa8, 0x56, 0x8e, 0x9b, 0xd2, 0x04, 0x75, 0x95, 0x51, 0x0b, 0xc4, 0x71, 0x5f, 0x72,
/* (2^200)P */ 0xe6, 0x9c, 0x33, 0xd0, 0x9c, 0xf8, 0xc7, 0x28, 0x8b, 0xc1, 0xdd, 0x69, 0x44, 0xb1, 0x67, 0x83, 0x2c, 0x65, 0xa1, 0xa6, 0x83, 0xda, 0x3a, 0x88, 0x17, 0x6c, 0x4d, 0x03, 0x74, 0x19, 0x5f, 0x58,
/* (2^201)P */ 0x88, 0x91, 0xb1, 0xf1, 0x66, 0xb2, 0xcf, 0x89, 0x17, 0x52, 0xc3, 0xe7, 0x63, 0x48, 0x3b, 0xe6, 0x6a, 0x52, 0xc0, 0xb4, 0xa6, 0x9d, 0x8c, 0xd8, 0x35, 0x46, 0x95, 0xf0, 0x9d, 0x5c, 0x03, 0x3e,
/* (2^202)P */ 0x9d, 0xde, 0x45, 0xfb, 0x12, 0x54, 0x9d, 0xdd, 0x0d, 0xf4, 0xcf, 0xe4, 0x32, 0x45, 0x68, 0xdd, 0x1c, 0x67, 0x1d, 0x15, 0x9b, 0x99, 0x5c, 0x4b, 0x90, 0xf6, 0xe7, 0x11, 0xc8, 0x2c, 0x8c, 0x2d,
/* (2^203)P */ 0x40, 0x5d, 0x05, 0x90, 0x1d, 0xbe, 0x54, 0x7f, 0x40, 0xaf, 0x4a, 0x46, 0xdf, 0xc5, 0x64, 0xa4, 0xbe, 0x17, 0xe9, 0xf0, 0x24, 0x96, 0x97, 0x33, 0x30, 0x6b, 0x35, 0x27, 0xc5, 0x8d, 0x01, 0x2c,
/* (2^204)P */ 0xd4, 0xb3, 0x30, 0xe3, 0x24, 0x50, 0x41, 0xa5, 0xd3, 0x52, 0x16, 0x69, 0x96, 0x3d, 0xff, 0x73, 0xf1, 0x59, 0x9b, 0xef, 0xc4, 0x42, 0xec, 0x94, 0x5a, 0x8e, 0xd0, 0x18, 0x16, 0x20, 0x47, 0x07,
/* (2^205)P */ 0x53, 0x1c, 0x41, 0xca, 0x8a, 0xa4, 0x6c, 0x4d, 0x19, 0x61, 0xa6, 0xcf, 0x2f, 0x5f, 0x41, 0x66, 0xff, 0x27, 0xe2, 0x51, 0x00, 0xd4, 0x4d, 0x9c, 0xeb, 0xf7, 0x02, 0x9a, 0xc0, 0x0b, 0x81, 0x59,
/* (2^206)P */ 0x1d, 0x10, 0xdc, 0xb3, 0x71, 0xb1, 0x7e, 0x2a, 0x8e, 0xf6, 0xfe, 0x9f, 0xb9, 0x5a, 0x1c, 0x44, 0xea, 0x59, 0xb3, 0x93, 0x9b, 0x5c, 0x02, 0x32, 0x2f, 0x11, 0x9d, 0x1e, 0xa7, 0xe0, 0x8c, 0x5e,
/* (2^207)P */ 0xfd, 0x03, 0x95, 0x42, 0x92, 0xcb, 0xcc, 0xbf, 0x55, 0x5d, 0x09, 0x2f, 0x75, 0xba, 0x71, 0xd2, 0x1e, 0x09, 0x2d, 0x97, 0x5e, 0xad, 0x5e, 0x34, 0xba, 0x03, 0x31, 0xa8, 0x11, 0xdf, 0xc8, 0x18,
/* (2^208)P */ 0x4c, 0x0f, 0xed, 0x9a, 0x9a, 0x94, 0xcd, 0x90, 0x7e, 0xe3, 0x60, 0x66, 0xcb, 0xf4, 0xd1, 0xc5, 0x0b, 0x2e, 0xc5, 0x56, 0x2d, 0xc5, 0xca, 0xb8, 0x0d, 0x8e, 0x80, 0xc5, 0x00, 0xe4, 0x42, 0x6e,
/* (2^209)P */ 0x23, 0xfd, 0xae, 0xee, 0x66, 0x69, 0xb4, 0xa3, 0xca, 0xcd, 0x9e, 0xe3, 0x0b, 0x1f, 0x4f, 0x0c, 0x1d, 0xa5, 0x83, 0xd6, 0xc9, 0xc8, 0x9d, 0x18, 0x1b, 0x35, 0x09, 0x4c, 0x05, 0x7f, 0xf2, 0x51,
/* (2^210)P */ 0x82, 0x06, 0x32, 0x2a, 0xcd, 0x7c, 0x48, 0x4c, 0x96, 0x1c, 0xdf, 0xb3, 0x5b, 0xa9, 0x7e, 0x58, 0xe8, 0xb8, 0x5c, 0x55, 0x9e, 0xf7, 0xcc, 0xc8, 0x3d, 0xd7, 0x06, 0xa2, 0x29, 0xc8, 0x7d, 0x54,
/* (2^211)P */ 0x06, 0x9b, 0xc3, 0x80, 0xcd, 0xa6, 0x22, 0xb8, 0xc6, 0xd4, 0x00, 0x20, 0x73, 0x54, 0x6d, 0xe9, 0x4d, 0x3b, 0x46, 0x91, 0x6f, 0x5b, 0x53, 0x28, 0x1d, 0x6e, 0x48, 0xe2, 0x60, 0x46, 0x8f, 0x22,
/* (2^212)P */ 0xbf, 0x3a, 0x8d, 0xde, 0x38, 0x95, 0x79, 0x98, 0x6e, 0xca, 0xeb, 0x45, 0x00, 0x33, 0xd8, 0x8c, 0x38, 0xe7, 0x21, 0x82, 0x00, 0x2a, 0x95, 0x79, 0xbb, 0xd2, 0x5c, 0x53, 0xa7, 0xe1, 0x22, 0x43,
/* (2^213)P */ 0x1c, 0x80, 0xd1, 0x19, 0x18, 0xc1, 0x14, 0xb1, 0xc7, 0x5e, 0x3f, 0x4f, 0xd8, 0xe4, 0x16, 0x20, 0x4c, 0x0f, 0x26, 0x09, 0xf4, 0x2d, 0x0e, 0xdd, 0x66, 0x72, 0x5f, 0xae, 0xc0, 0x62, 0xc3, 0x5e,
/* (2^214)P */ 0xee, 0xb4, 0xb2, 0xb8, 0x18, 0x2b, 0x46, 0xc0, 0xfb, 0x1a, 0x4d, 0x27, 0x50, 0xd9, 0xc8, 0x7c, 0xd2, 0x02, 0x6b, 0x43, 0x05, 0x71, 0x5f, 0xf2, 0xd3, 0xcc, 0xf9, 0xbf, 0xdc, 0xf8, 0xbb, 0x43,
/* (2^215)P */ 0xdf, 0xe9, 0x39, 0xa0, 0x67, 0x17, 0xad, 0xb6, 0x83, 0x35, 0x9d, 0xf6, 0xa8, 0x4d, 0x71, 0xb0, 0xf5, 0x31, 0x29, 0xb4, 0x18, 0xfa, 0x55, 0x5e, 0x61, 0x09, 0xc6, 0x33, 0x8f, 0x55, 0xd5, 0x4e,
/* (2^216)P */ 0xdd, 0xa5, 0x47, 0xc6, 0x01, 0x79, 0xe3, 0x1f, 0x57, 0xd3, 0x81, 0x80, 0x1f, 0xdf, 0x3d, 0x59, 0xa6, 0xd7, 0x3f, 0x81, 0xfd, 0xa4, 0x49, 0x02, 0x61, 0xaf, 0x9c, 0x4e, 0x27, 0xca, 0xac, 0x69,
/* (2^217)P */ 0xc9, 0x21, 0x07, 0x33, 0xea, 0xa3, 0x7b, 0x04, 0xa0, 0x1e, 0x7e, 0x0e, 0xc2, 0x3f, 0x42, 0x83, 0x60, 0x4a, 0x31, 0x01, 0xaf, 0xc0, 0xf4, 0x1d, 0x27, 0x95, 0x28, 0x89, 0xab, 0x2d, 0xa6, 0x09,
/* (2^218)P */ 0x00, 0xcb, 0xc6, 0x9c, 0xa4, 0x25, 0xb3, 0xa5, 0xb6, 0x6c, 0xb5, 0x54, 0xc6, 0x5d, 0x4b, 0xe9, 0xa0, 0x94, 0xc9, 0xad, 0x79, 0x87, 0xe2, 0x3b, 0xad, 0x4a, 0x3a, 0xba, 0xf8, 0xe8, 0x96, 0x42,
/* (2^219)P */ 0xab, 0x1e, 0x45, 0x1e, 0x76, 0x89, 0x86, 0x32, 0x4a, 0x59, 0x59, 0xff, 0x8b, 0x59, 0x4d, 0x2e, 0x4a, 0x08, 0xa7, 0xd7, 0x53, 0x68, 0xb9, 0x49, 0xa8, 0x20, 0x14, 0x60, 0x19, 0xa3, 0x80, 0x49,
/* (2^220)P */ 0x42, 0x2c, 0x55, 0x2f, 0xe1, 0xb9, 0x65, 0x95, 0x96, 0xfe, 0x00, 0x71, 0xdb, 0x18, 0x53, 0x8a, 0xd7, 0xd0, 0xad, 0x43, 0x4d, 0x0b, 0xc9, 0x05, 0xda, 0x4e, 0x5d, 0x6a, 0xd6, 0x4c, 0x8b, 0x53,
/* (2^221)P */ 0x9f, 0x03, 0x9f, 0xe8, 0xc3, 0x4f, 0xe9, 0xf4, 0x45, 0x80, 0x61, 0x6f, 0xf2, 0x9a, 0x2c, 0x59, 0x50, 0x95, 0x4b, 0xfd, 0xb5, 0x6e, 0xa3, 0x08, 0x19, 0x14, 0xed, 0xc2, 0xf6, 0xfa, 0xff, 0x25,
/* (2^222)P */ 0x54, 0xd3, 0x79, 0xcc, 0x59, 0x44, 0x43, 0x34, 0x6b, 0x47, 0xd5, 0xb1, 0xb4, 0xbf, 0xec, 0xee, 0x99, 0x5d, 0x61, 0x61, 0xa0, 0x34, 0xeb, 0xdd, 0x73, 0xb7, 0x64, 0xeb, 0xcc, 0xce, 0x29, 0x51,
/* (2^223)P */ 0x20, 0x35, 0x99, 0x94, 0x58, 0x21, 0x43, 0xee, 0x3b, 0x0b, 0x4c, 0xf1, 0x7c, 0x9c, 0x2f, 0x77, 0xd5, 0xda, 0xbe, 0x06, 0xe3, 0xfc, 0xe2, 0xd2, 0x97, 0x6a, 0xf0, 0x46, 0xb5, 0x42, 0x5f, 0x71,
/* (2^224)P */ 0x1a, 0x5f, 0x5b, 0xda, 0xce, 0xcd, 0x4e, 0x43, 0xa9, 0x41, 0x97, 0xa4, 0x15, 0x71, 0xa1, 0x0d, 0x2e, 0xad, 0xed, 0x73, 0x7c, 0xd7, 0x0b, 0x68, 0x41, 0x90, 0xdd, 0x4e, 0x35, 0x02, 0x7c, 0x48,
/* (2^225)P */ 0xc4, 0xd9, 0x0e, 0xa7, 0xf3, 0xef, 0xef, 0xb8, 0x02, 0xe3, 0x57, 0xe8, 0xa3, 0x2a, 0xa3, 0x56, 0xa0, 0xa5, 0xa2, 0x48, 0xbd, 0x68, 0x3a, 0xdf, 0x44, 0xc4, 0x76, 0x31, 0xb7, 0x50, 0xf6, 0x07,
/* (2^226)P */ 0xb1, 0xcc, 0xe0, 0x26, 0x16, 0x9b, 0x8b, 0xe3, 0x36, 0xfb, 0x09, 0x8b, 0xc1, 0x53, 0xe0, 0x79, 0x64, 0x49, 0xf9, 0xc9, 0x19, 0x03, 0xd9, 0x56, 0xc4, 0xf5, 0x9f, 0xac, 0xe7, 0x41, 0xa9, 0x1c,
/* (2^227)P */ 0xbb, 0xa0, 0x2f, 0x16, 0x29, 0xdf, 0xc4, 0x49, 0x05, 0x33, 0xb3, 0x82, 0x32, 0xcf, 0x88, 0x84, 0x7d, 0x43, 0xbb, 0xca, 0x14, 0xda, 0xdf, 0x95, 0x86, 0xad, 0xd5, 0x64, 0x82, 0xf7, 0x91, 0x33,
/* (2^228)P */ 0x5d, 0x09, 0xb5, 0xe2, 0x6a, 0xe0, 0x9a, 0x72, 0x46, 0xa9, 0x59, 0x32, 0xd7, 0x58, 0x8a, 0xd5, 0xed, 0x21, 0x39, 0xd1, 0x62, 0x42, 0x83, 0xe9, 0x92, 0xb5, 0x4b, 0xa5, 0xfa, 0xda, 0xfe, 0x27,
/* (2^229)P */ 0xbb, 0x48, 0xad, 0x29, 0xb8, 0xc5, 0x9d, 0xa9, 0x60, 0xe2, 0x9e, 0x49, 0x42, 0x57, 0x02, 0x5f, 0xfd, 0x13, 0x75, 0x5d, 0xcd, 0x8e, 0x2c, 0x80, 0x38, 0xd9, 0x6d, 0x3f, 0xef, 0xb3, 0xce, 0x78,
/* (2^230)P */ 0x94, 0x5d, 0x13, 0x8a, 0x4f, 0xf4, 0x42, 0xc3, 0xa3, 0xdd, 0x8c, 0x82, 0x44, 0xdb, 0x9e, 0x7b, 0xe7, 0xcf, 0x37, 0x05, 0x1a, 0xd1, 0x36, 0x94, 0xc8, 0xb4, 0x1a, 0xec, 0x64, 0xb1, 0x64, 0x50,
/* (2^231)P */ 0xfc, 0xb2, 0x7e, 0xd3, 0xcf, 0xec, 0x20, 0x70, 0xfc, 0x25, 0x0d, 0xd9, 0x3e, 0xea, 0x31, 0x1f, 0x34, 0xbb, 0xa1, 0xdf, 0x7b, 0x0d, 0x93, 0x1b, 0x44, 0x30, 0x11, 0x48, 0x7a, 0x46, 0x44, 0x53,
/* (2^232)P */ 0xfb, 0x6d, 0x5e, 0xf2, 0x70, 0x31, 0x07, 0x70, 0xc8, 0x4c, 0x11, 0x50, 0x1a, 0xdc, 0x85, 0xe3, 0x00, 0x4f, 0xfc, 0xc8, 0x8a, 0x69, 0x48, 0x23, 0xd8, 0x40, 0xdd, 0x84, 0x52, 0xa5, 0x77, 0x2a,
/* (2^233)P */ 0xe4, 0x6c, 0x8c, 0xc9, 0xe0, 0xaf, 0x06, 0xfe, 0xe4, 0xd6, 0xdf, 0xdd, 0x96, 0xdf, 0x35, 0xc2, 0xd3, 0x1e, 0xbf, 0x33, 0x1e, 0xd0, 0x28, 0x14, 0xaf, 0xbd, 0x00, 0x93, 0xec, 0x68, 0x57, 0x78,
/* (2^234)P */ 0x3b, 0xb6, 0xde, 0x91, 0x7a, 0xe5, 0x02, 0x97, 0x80, 0x8b, 0xce, 0xe5, 0xbf, 0xb8, 0xbd, 0x61, 0xac, 0x58, 0x1d, 0x3d, 0x6f, 0x42, 0x5b, 0x64, 0xbc, 0x57, 0xa5, 0x27, 0x22, 0xa8, 0x04, 0x48,
/* (2^235)P */ 0x01, 0x26, 0x4d, 0xb4, 0x8a, 0x04, 0x57, 0x8e, 0x35, 0x69, 0x3a, 0x4b, 0x1a, 0x50, 0xd6, 0x68, 0x93, 0xc2, 0xe1, 0xf9, 0xc3, 0x9e, 0x9c, 0xc3, 0xe2, 0x63, 0xde, 0xd4, 0x57, 0xf2, 0x72, 0x41,
/* (2^236)P */ 0x01, 0x64, 0x0c, 0x33, 0x50, 0xb4, 0x68, 0xd3, 0x91, 0x23, 0x8f, 0x41, 0x17, 0x30, 0x0d, 0x04, 0x0d, 0xd9, 0xb7, 0x90, 0x60, 0xbb, 0x34, 0x2c, 0x1f, 0xd5, 0xdf, 0x8f, 0x22, 0x49, 0xf6, 0x16,
/* (2^237)P */ 0xf5, 0x8e, 0x92, 0x2b, 0x8e, 0x81, 0xa6, 0xbe, 0x72, 0x1e, 0xc1, 0xcd, 0x91, 0xcf, 0x8c, 0xe2, 0xcd, 0x36, 0x7a, 0xe7, 0x68, 0xaa, 0x4a, 0x59, 0x0f, 0xfd, 0x7f, 0x6c, 0x80, 0x34, 0x30, 0x31,
/* (2^238)P */ 0x65, 0xbd, 0x49, 0x22, 0xac, 0x27, 0x9d, 0x8a, 0x12, 0x95, 0x8e, 0x01, 0x64, 0xb4, 0xa3, 0x19, 0xc7, 0x7e, 0xb3, 0x52, 0xf3, 0xcf, 0x6c, 0xc2, 0x21, 0x7b, 0x79, 0x1d, 0x34, 0x68, 0x6f, 0x05,
/* (2^239)P */ 0x27, 0x23, 0xfd, 0x7e, 0x75, 0xd6, 0x79, 0x5e, 0x15, 0xfe, 0x3a, 0x55, 0xb6, 0xbc, 0xbd, 0xfa, 0x60, 0x5a, 0xaf, 0x6e, 0x2c, 0x22, 0xe7, 0xd3, 0x3b, 0x74, 0xae, 0x4d, 0x6d, 0xc7, 0x46, 0x70,
/* (2^240)P */ 0x55, 0x4a, 0x8d, 0xb1, 0x72, 0xe8, 0x0b, 0x66, 0x96, 0x14, 0x4e, 0x57, 0x18, 0x25, 0x99, 0x19, 0xbb, 0xdc, 0x2b, 0x30, 0x3a, 0x05, 0x03, 0xc1, 0x8e, 0x8e, 0x21, 0x0b, 0x80, 0xe9, 0xd8, 0x3e,
/* (2^241)P */ 0x3e, 0xe0, 0x75, 0xfa, 0x39, 0x92, 0x0b, 0x7b, 0x83, 0xc0, 0x33, 0x46, 0x68, 0xfb, 0xe9, 0xef, 0x93, 0x77, 0x1a, 0x39, 0xbe, 0x5f, 0xa3, 0x98, 0x34, 0xfe, 0xd0, 0xe2, 0x0f, 0x51, 0x65, 0x60,
/* (2^242)P */ 0x0c, 0xad, 0xab, 0x48, 0x85, 0x66, 0xcb, 0x55, 0x27, 0xe5, 0x87, 0xda, 0x48, 0x45, 0x58, 0xb4, 0xdd, 0xc1, 0x07, 0x01, 0xea, 0xec, 0x43, 0x2c, 0x35, 0xde, 0x72, 0x93, 0x80, 0x28, 0x60, 0x52,
/* (2^243)P */ 0x1f, 0x3b, 0x21, 0xf9, 0x6a, 0xc5, 0x15, 0x34, 0xdb, 0x98, 0x7e, 0x01, 0x4d, 0x1a, 0xee, 0x5b, 0x9b, 0x70, 0xcf, 0xb5, 0x05, 0xb1, 0xf6, 0x13, 0xb6, 0x9a, 0xb2, 0x82, 0x34, 0x0e, 0xf2, 0x5f,
/* (2^244)P */ 0x90, 0x6c, 0x2e, 0xcc, 0x75, 0x9c, 0xa2, 0x0a, 0x06, 0xe2, 0x70, 0x3a, 0xca, 0x73, 0x7d, 0xfc, 0x15, 0xc5, 0xb5, 0xc4, 0x8f, 0xc3, 0x9f, 0x89, 0x07, 0xc2, 0xff, 0x24, 0xb1, 0x86, 0x03, 0x25,
/* (2^245)P */ 0x56, 0x2b, 0x3d, 0xae, 0xd5, 0x28, 0xea, 0x54, 0xce, 0x60, 0xde, 0xd6, 0x9d, 0x14, 0x13, 0x99, 0xc1, 0xd6, 0x06, 0x8f, 0xc5, 0x4f, 0x69, 0x16, 0xc7, 0x8f, 0x01, 0xeb, 0x75, 0x39, 0xb2, 0x46,
/* (2^246)P */ 0xe2, 0xb4, 0xb7, 0xb4, 0x0f, 0x6a, 0x0a, 0x47, 0xde, 0x53, 0x72, 0x8f, 0x5a, 0x47, 0x92, 0x5d, 0xdb, 0x3a, 0xbd, 0x2f, 0xb5, 0xe5, 0xee, 0xab, 0x68, 0x69, 0x80, 0xa0, 0x01, 0x08, 0xa2, 0x7f,
/* (2^247)P */ 0xd2, 0x14, 0x77, 0x9f, 0xf1, 0xfa, 0xf3, 0x76, 0xc3, 0x60, 0x46, 0x2f, 0xc1, 0x40, 0xe8, 0xb3, 0x4e, 0x74, 0x12, 0xf2, 0x8d, 0xcd, 0xb4, 0x0f, 0xd2, 0x2d, 0x3a, 0x1d, 0x25, 0x5a, 0x06, 0x4b,
/* (2^248)P */ 0x4a, 0xcd, 0x77, 0x3d, 0x38, 0xde, 0xeb, 0x5c, 0xb1, 0x9c, 0x2c, 0x88, 0xdf, 0x39, 0xdf, 0x6a, 0x59, 0xf7, 0x9a, 0xb0, 0x2e, 0x24, 0xdd, 0xa2, 0x22, 0x64, 0x5f, 0x0e, 0xe5, 0xc0, 0x47, 0x31,
/* (2^249)P */ 0xdb, 0x50, 0x13, 0x1d, 0x10, 0xa5, 0x4c, 0x16, 0x62, 0xc9, 0x3f, 0xc3, 0x79, 0x34, 0xd1, 0xf8, 0x08, 0xda, 0xe5, 0x13, 0x4d, 0xce, 0x40, 0xe6, 0xba, 0xf8, 0x61, 0x50, 0xc4, 0xe0, 0xde, 0x4b,
/* (2^250)P */ 0xc9, 0xb1, 0xed, 0xa4, 0xc1, 0x6d, 0xc4, 0xd7, 0x8a, 0xd9, 0x7f, 0x43, 0xb6, 0xd7, 0x14, 0x55, 0x0b, 0xc0, 0xa1, 0xb2, 0x6b, 0x2f, 0x94, 0x58, 0x0e, 0x71, 0x70, 0x1d, 0xab, 0xb2, 0xff, 0x2d,
/* (2^251)P */ 0x68, 0x6d, 0x8b, 0xc1, 0x2f, 0xcf, 0xdf, 0xcc, 0x67, 0x61, 0x80, 0xb7, 0xa8, 0xcb, 0xeb, 0xa8, 0xe3, 0x37, 0x29, 0x5e, 0xf9, 0x97, 0x06, 0x98, 0x8c, 0x6e, 0x12, 0xd0, 0x1c, 0xba, 0xfb, 0x02,
/* (2^252)P */ 0x65, 0x45, 0xff, 0xad, 0x60, 0xc3, 0x98, 0xcb, 0x19, 0x15, 0xdb, 0x4b, 0xd2, 0x01, 0x71, 0x44, 0xd5, 0x15, 0xfb, 0x75, 0x74, 0xc8, 0xc4, 0x98, 0x7d, 0xa2, 0x22, 0x6e, 0x6d, 0xc7, 0xf8, 0x05,
/* (2^253)P */ 0x94, 0xf4, 0xb9, 0xfe, 0xdf, 0xe5, 0x69, 0xab, 0x75, 0x6b, 0x40, 0x18, 0x9d, 0xc7, 0x09, 0xae, 0x1d, 0x2d, 0xa4, 0x94, 0xfb, 0x45, 0x9b, 0x19, 0x84, 0xfa, 0x2a, 0xae, 0xeb, 0x0a, 0x71, 0x79,
/* (2^254)P */ 0xdf, 0xd2, 0x34, 0xf3, 0xa7, 0xed, 0xad, 0xa6, 0xb4, 0x57, 0x2a, 0xaf, 0x51, 0x9c, 0xde, 0x7b, 0xa8, 0xea, 0xdc, 0x86, 0x4f, 0xc6, 0x8f, 0xa9, 0x7b, 0xd0, 0x0e, 0xc2, 0x35, 0x03, 0xbe, 0x6b,
/* (2^255)P */ 0x44, 0x43, 0x98, 0x53, 0xbe, 0xdc, 0x7f, 0x66, 0xa8, 0x49, 0x59, 0x00, 0x1c, 0xbc, 0x72, 0x07, 0x8e, 0xd6, 0xbe, 0x4e, 0x9f, 0xa4, 0x07, 0xba, 0xbf, 0x30, 0xdf, 0xba, 0x85, 0xb0, 0xa7, 0x1f,
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve.go
================================================
package x448
import (
fp "github.com/cloudflare/circl/math/fp448"
)
// ladderJoye calculates a fixed-point multiplication with the generator point.
// The algorithm is the right-to-left Joye's ladder as described
// in "How to precompute a ladder" in SAC'2017.
func ladderJoye(k *Key) {
w := [5]fp.Elt{} // [mu,x1,z1,x2,z2] order must be preserved.
w[1] = fp.Elt{ // x1 = S
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
fp.SetOne(&w[2]) // z1 = 1
w[3] = fp.Elt{ // x2 = G-S
0x20, 0x27, 0x9d, 0xc9, 0x7d, 0x19, 0xb1, 0xac,
0xf8, 0xba, 0x69, 0x1c, 0xff, 0x33, 0xac, 0x23,
0x51, 0x1b, 0xce, 0x3a, 0x64, 0x65, 0xbd, 0xf1,
0x23, 0xf8, 0xc1, 0x84, 0x9d, 0x45, 0x54, 0x29,
0x67, 0xb9, 0x81, 0x1c, 0x03, 0xd1, 0xcd, 0xda,
0x7b, 0xeb, 0xff, 0x1a, 0x88, 0x03, 0xcf, 0x3a,
0x42, 0x44, 0x32, 0x01, 0x25, 0xb7, 0xfa, 0xf0,
}
fp.SetOne(&w[4]) // z2 = 1
const n = 448
const h = 2
swap := uint(1)
for s := 0; s < n-h; s++ {
i := (s + h) / 8
j := (s + h) % 8
bit := uint((k[i] >> uint(j)) & 1)
copy(w[0][:], tableGenerator[s*Size:(s+1)*Size])
diffAdd(&w, swap^bit)
swap = bit
}
for s := 0; s < h; s++ {
double(&w[1], &w[2])
}
toAffine((*[fp.Size]byte)(k), &w[1], &w[2])
}
// ladderMontgomery calculates a generic scalar point multiplication
// The algorithm implemented is the left-to-right Montgomery's ladder.
func ladderMontgomery(k, xP *Key) {
w := [5]fp.Elt{} // [x1, x2, z2, x3, z3] order must be preserved.
w[0] = *(*fp.Elt)(xP) // x1 = xP
fp.SetOne(&w[1]) // x2 = 1
w[3] = *(*fp.Elt)(xP) // x3 = xP
fp.SetOne(&w[4]) // z3 = 1
move := uint(0)
for s := 448 - 1; s >= 0; s-- {
i := s / 8
j := s % 8
bit := uint((k[i] >> uint(j)) & 1)
ladderStep(&w, move^bit)
move = bit
}
toAffine((*[fp.Size]byte)(k), &w[1], &w[2])
}
func toAffine(k *[fp.Size]byte, x, z *fp.Elt) {
fp.Inv(z, z)
fp.Mul(x, x, z)
_ = fp.ToBytes(k[:], x)
}
var lowOrderPoints = [3]fp.Elt{
{ /* (0,_,1) point of order 2 on Curve448 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{ /* (1,_,1) a point of order 4 on the twist of Curve448 */
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
{ /* (-1,_,1) point of order 4 on Curve448 */
0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
},
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.go
================================================
//go:build amd64 && !purego
// +build amd64,!purego
package x448
import (
fp "github.com/cloudflare/circl/math/fp448"
"golang.org/x/sys/cpu"
)
var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX
var _ = hasBmi2Adx
func double(x, z *fp.Elt) { doubleAmd64(x, z) }
func diffAdd(w *[5]fp.Elt, b uint) { diffAddAmd64(w, b) }
func ladderStep(w *[5]fp.Elt, b uint) { ladderStepAmd64(w, b) }
func mulA24(z, x *fp.Elt) { mulA24Amd64(z, x) }
//go:noescape
func doubleAmd64(x, z *fp.Elt)
//go:noescape
func diffAddAmd64(w *[5]fp.Elt, b uint)
//go:noescape
func ladderStepAmd64(w *[5]fp.Elt, b uint)
//go:noescape
func mulA24Amd64(z, x *fp.Elt)
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.h
================================================
#define ladderStepLeg \
addSub(x2,z2) \
addSub(x3,z3) \
integerMulLeg(b0,x2,z3) \
integerMulLeg(b1,x3,z2) \
reduceFromDoubleLeg(t0,b0) \
reduceFromDoubleLeg(t1,b1) \
addSub(t0,t1) \
cselect(x2,x3,regMove) \
cselect(z2,z3,regMove) \
integerSqrLeg(b0,t0) \
integerSqrLeg(b1,t1) \
reduceFromDoubleLeg(x3,b0) \
reduceFromDoubleLeg(z3,b1) \
integerMulLeg(b0,x1,z3) \
reduceFromDoubleLeg(z3,b0) \
integerSqrLeg(b0,x2) \
integerSqrLeg(b1,z2) \
reduceFromDoubleLeg(x2,b0) \
reduceFromDoubleLeg(z2,b1) \
subtraction(t0,x2,z2) \
multiplyA24Leg(t1,t0) \
additionLeg(t1,t1,z2) \
integerMulLeg(b0,x2,z2) \
integerMulLeg(b1,t0,t1) \
reduceFromDoubleLeg(x2,b0) \
reduceFromDoubleLeg(z2,b1)
#define ladderStepBmi2Adx \
addSub(x2,z2) \
addSub(x3,z3) \
integerMulAdx(b0,x2,z3) \
integerMulAdx(b1,x3,z2) \
reduceFromDoubleAdx(t0,b0) \
reduceFromDoubleAdx(t1,b1) \
addSub(t0,t1) \
cselect(x2,x3,regMove) \
cselect(z2,z3,regMove) \
integerSqrAdx(b0,t0) \
integerSqrAdx(b1,t1) \
reduceFromDoubleAdx(x3,b0) \
reduceFromDoubleAdx(z3,b1) \
integerMulAdx(b0,x1,z3) \
reduceFromDoubleAdx(z3,b0) \
integerSqrAdx(b0,x2) \
integerSqrAdx(b1,z2) \
reduceFromDoubleAdx(x2,b0) \
reduceFromDoubleAdx(z2,b1) \
subtraction(t0,x2,z2) \
multiplyA24Adx(t1,t0) \
additionAdx(t1,t1,z2) \
integerMulAdx(b0,x2,z2) \
integerMulAdx(b1,t0,t1) \
reduceFromDoubleAdx(x2,b0) \
reduceFromDoubleAdx(z2,b1)
#define difAddLeg \
addSub(x1,z1) \
integerMulLeg(b0,z1,ui) \
reduceFromDoubleLeg(z1,b0) \
addSub(x1,z1) \
integerSqrLeg(b0,x1) \
integerSqrLeg(b1,z1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1) \
integerMulLeg(b0,x1,z2) \
integerMulLeg(b1,z1,x2) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1)
#define difAddBmi2Adx \
addSub(x1,z1) \
integerMulAdx(b0,z1,ui) \
reduceFromDoubleAdx(z1,b0) \
addSub(x1,z1) \
integerSqrAdx(b0,x1) \
integerSqrAdx(b1,z1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1) \
integerMulAdx(b0,x1,z2) \
integerMulAdx(b1,z1,x2) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1)
#define doubleLeg \
addSub(x1,z1) \
integerSqrLeg(b0,x1) \
integerSqrLeg(b1,z1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1) \
subtraction(t0,x1,z1) \
multiplyA24Leg(t1,t0) \
additionLeg(t1,t1,z1) \
integerMulLeg(b0,x1,z1) \
integerMulLeg(b1,t0,t1) \
reduceFromDoubleLeg(x1,b0) \
reduceFromDoubleLeg(z1,b1)
#define doubleBmi2Adx \
addSub(x1,z1) \
integerSqrAdx(b0,x1) \
integerSqrAdx(b1,z1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1) \
subtraction(t0,x1,z1) \
multiplyA24Adx(t1,t0) \
additionAdx(t1,t1,z1) \
integerMulAdx(b0,x1,z1) \
integerMulAdx(b1,t0,t1) \
reduceFromDoubleAdx(x1,b0) \
reduceFromDoubleAdx(z1,b1)
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve_amd64.s
================================================
// +build amd64
#include "textflag.h"
// Depends on circl/math/fp448 package
#include "../../math/fp448/fp_amd64.h"
#include "curve_amd64.h"
// CTE_A24 is (A+2)/4 from Curve448
#define CTE_A24 39082
#define Size 56
// multiplyA24Leg multiplies x times CTE_A24 and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64, cmov, adx
#define multiplyA24Leg(z,x) \
MOVQ $CTE_A24, R15; \
MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \
MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \
MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \
MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \
MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \
MOVQ DX, AX; \
SHLQ $32, AX; \
ADDQ DX, R8; MOVQ $0, DX; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ AX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
ADCQ $0, DX; \
MOVQ DX, AX; \
SHLQ $32, AX; \
ADDQ DX, R8; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ AX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
MOVQ R8, 0+z; \
MOVQ R9, 8+z; \
MOVQ R10, 16+z; \
MOVQ R11, 24+z; \
MOVQ R12, 32+z; \
MOVQ R13, 40+z; \
MOVQ R14, 48+z;
// multiplyA24Adx multiplies x times CTE_A24 and stores in z
// Uses: AX, DX, R8-R14, FLAGS
// Instr: x86_64, bmi2
#define multiplyA24Adx(z,x) \
MOVQ $CTE_A24, DX; \
MULXQ 0+x, R8, R9; \
MULXQ 8+x, AX, R10; ADDQ AX, R9; \
MULXQ 16+x, AX, R11; ADCQ AX, R10; \
MULXQ 24+x, AX, R12; ADCQ AX, R11; \
MULXQ 32+x, AX, R13; ADCQ AX, R12; \
MULXQ 40+x, AX, R14; ADCQ AX, R13; \
MULXQ 48+x, AX, DX; ADCQ AX, R14; \
;;;;;;;;;;;;;;;;;;;; ADCQ $0, DX; \
MOVQ DX, AX; \
SHLQ $32, AX; \
ADDQ DX, R8; MOVQ $0, DX; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ AX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
ADCQ $0, DX; \
MOVQ DX, AX; \
SHLQ $32, AX; \
ADDQ DX, R8; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ AX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
MOVQ R8, 0+z; \
MOVQ R9, 8+z; \
MOVQ R10, 16+z; \
MOVQ R11, 24+z; \
MOVQ R12, 32+z; \
MOVQ R13, 40+z; \
MOVQ R14, 48+z;
#define mulA24Legacy \
multiplyA24Leg(0(DI),0(SI))
#define mulA24Bmi2Adx \
multiplyA24Adx(0(DI),0(SI))
// func mulA24Amd64(z, x *fp448.Elt)
TEXT ·mulA24Amd64(SB),NOSPLIT,$0-16
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
CHECK_BMI2ADX(LMA24, mulA24Legacy, mulA24Bmi2Adx)
// func ladderStepAmd64(w *[5]fp448.Elt, b uint)
// ladderStepAmd64 calculates a point addition and doubling as follows:
// (x2,z2) = 2*(x2,z2) and (x3,z3) = (x2,z2)+(x3,z3) using as a difference (x1,-).
// w = {x1,x2,z2,x3,z4} are five fp255.Elt of 56 bytes.
// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and
// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
TEXT ·ladderStepAmd64(SB),NOSPLIT,$336-16
// Parameters
#define regWork DI
#define regMove SI
#define x1 0*Size(regWork)
#define x2 1*Size(regWork)
#define z2 2*Size(regWork)
#define x3 3*Size(regWork)
#define z3 4*Size(regWork)
// Local variables
#define t0 0*Size(SP)
#define t1 1*Size(SP)
#define b0 2*Size(SP)
#define b1 4*Size(SP)
MOVQ w+0(FP), regWork
MOVQ b+8(FP), regMove
CHECK_BMI2ADX(LLADSTEP, ladderStepLeg, ladderStepBmi2Adx)
#undef regWork
#undef regMove
#undef x1
#undef x2
#undef z2
#undef x3
#undef z3
#undef t0
#undef t1
#undef b0
#undef b1
// func diffAddAmd64(work *[5]fp.Elt, swap uint)
// diffAddAmd64 calculates a differential point addition using a precomputed point.
// (x1,z1) = (x1,z1)+(mu) using a difference point (x2,z2)
// work = {mu,x1,z1,x2,z2} are five fp448.Elt of 56 bytes, and
// stack = (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
// This is Equation 7 at https://eprint.iacr.org/2017/264.
TEXT ·diffAddAmd64(SB),NOSPLIT,$224-16
// Parameters
#define regWork DI
#define regSwap SI
#define ui 0*Size(regWork)
#define x1 1*Size(regWork)
#define z1 2*Size(regWork)
#define x2 3*Size(regWork)
#define z2 4*Size(regWork)
// Local variables
#define b0 0*Size(SP)
#define b1 2*Size(SP)
MOVQ w+0(FP), regWork
MOVQ b+8(FP), regSwap
cswap(x1,x2,regSwap)
cswap(z1,z2,regSwap)
CHECK_BMI2ADX(LDIFADD, difAddLeg, difAddBmi2Adx)
#undef regWork
#undef regSwap
#undef ui
#undef x1
#undef z1
#undef x2
#undef z2
#undef b0
#undef b1
// func doubleAmd64(x, z *fp448.Elt)
// doubleAmd64 calculates a point doubling (x1,z1) = 2*(x1,z1).
// stack = (t0,t1) are two fp.Elt of fp.Size bytes, and
// (b0,b1) are two-double precision fp.Elt of 2*fp.Size bytes.
TEXT ·doubleAmd64(SB),NOSPLIT,$336-16
// Parameters
#define x1 0(DI)
#define z1 0(SI)
// Local variables
#define t0 0*Size(SP)
#define t1 1*Size(SP)
#define b0 2*Size(SP)
#define b1 4*Size(SP)
MOVQ x+0(FP), DI
MOVQ z+8(FP), SI
CHECK_BMI2ADX(LDOUB,doubleLeg,doubleBmi2Adx)
#undef x1
#undef z1
#undef t0
#undef t1
#undef b0
#undef b1
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve_generic.go
================================================
package x448
import (
"encoding/binary"
"math/bits"
"github.com/cloudflare/circl/math/fp448"
)
func doubleGeneric(x, z *fp448.Elt) {
t0, t1 := &fp448.Elt{}, &fp448.Elt{}
fp448.AddSub(x, z)
fp448.Sqr(x, x)
fp448.Sqr(z, z)
fp448.Sub(t0, x, z)
mulA24Generic(t1, t0)
fp448.Add(t1, t1, z)
fp448.Mul(x, x, z)
fp448.Mul(z, t0, t1)
}
func diffAddGeneric(w *[5]fp448.Elt, b uint) {
mu, x1, z1, x2, z2 := &w[0], &w[1], &w[2], &w[3], &w[4]
fp448.Cswap(x1, x2, b)
fp448.Cswap(z1, z2, b)
fp448.AddSub(x1, z1)
fp448.Mul(z1, z1, mu)
fp448.AddSub(x1, z1)
fp448.Sqr(x1, x1)
fp448.Sqr(z1, z1)
fp448.Mul(x1, x1, z2)
fp448.Mul(z1, z1, x2)
}
func ladderStepGeneric(w *[5]fp448.Elt, b uint) {
x1, x2, z2, x3, z3 := &w[0], &w[1], &w[2], &w[3], &w[4]
t0 := &fp448.Elt{}
t1 := &fp448.Elt{}
fp448.AddSub(x2, z2)
fp448.AddSub(x3, z3)
fp448.Mul(t0, x2, z3)
fp448.Mul(t1, x3, z2)
fp448.AddSub(t0, t1)
fp448.Cmov(x2, x3, b)
fp448.Cmov(z2, z3, b)
fp448.Sqr(x3, t0)
fp448.Sqr(z3, t1)
fp448.Mul(z3, x1, z3)
fp448.Sqr(x2, x2)
fp448.Sqr(z2, z2)
fp448.Sub(t0, x2, z2)
mulA24Generic(t1, t0)
fp448.Add(t1, t1, z2)
fp448.Mul(x2, x2, z2)
fp448.Mul(z2, t0, t1)
}
func mulA24Generic(z, x *fp448.Elt) {
const A24 = 39082
const n = 8
var xx [7]uint64
for i := range xx {
xx[i] = binary.LittleEndian.Uint64(x[i*n : (i+1)*n])
}
h0, l0 := bits.Mul64(xx[0], A24)
h1, l1 := bits.Mul64(xx[1], A24)
h2, l2 := bits.Mul64(xx[2], A24)
h3, l3 := bits.Mul64(xx[3], A24)
h4, l4 := bits.Mul64(xx[4], A24)
h5, l5 := bits.Mul64(xx[5], A24)
h6, l6 := bits.Mul64(xx[6], A24)
l1, c0 := bits.Add64(h0, l1, 0)
l2, c1 := bits.Add64(h1, l2, c0)
l3, c2 := bits.Add64(h2, l3, c1)
l4, c3 := bits.Add64(h3, l4, c2)
l5, c4 := bits.Add64(h4, l5, c3)
l6, c5 := bits.Add64(h5, l6, c4)
l7, _ := bits.Add64(h6, 0, c5)
l0, c0 = bits.Add64(l0, l7, 0)
l1, c1 = bits.Add64(l1, 0, c0)
l2, c2 = bits.Add64(l2, 0, c1)
l3, c3 = bits.Add64(l3, l7<<32, c2)
l4, c4 = bits.Add64(l4, 0, c3)
l5, c5 = bits.Add64(l5, 0, c4)
l6, l7 = bits.Add64(l6, 0, c5)
xx[0], c0 = bits.Add64(l0, l7, 0)
xx[1], c1 = bits.Add64(l1, 0, c0)
xx[2], c2 = bits.Add64(l2, 0, c1)
xx[3], c3 = bits.Add64(l3, l7<<32, c2)
xx[4], c4 = bits.Add64(l4, 0, c3)
xx[5], c5 = bits.Add64(l5, 0, c4)
xx[6], _ = bits.Add64(l6, 0, c5)
for i := range xx {
binary.LittleEndian.PutUint64(z[i*n:(i+1)*n], xx[i])
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/curve_noasm.go
================================================
//go:build !amd64 || purego
// +build !amd64 purego
package x448
import fp "github.com/cloudflare/circl/math/fp448"
func double(x, z *fp.Elt) { doubleGeneric(x, z) }
func diffAdd(w *[5]fp.Elt, b uint) { diffAddGeneric(w, b) }
func ladderStep(w *[5]fp.Elt, b uint) { ladderStepGeneric(w, b) }
func mulA24(z, x *fp.Elt) { mulA24Generic(z, x) }
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/doc.go
================================================
/*
Package x448 provides Diffie-Hellman functions as specified in RFC-7748.
Validation of public keys.
The Diffie-Hellman function, as described in RFC-7748 [1], works for any
public key. However, if a different protocol requires contributory
behaviour [2,3], then the public keys must be validated against low-order
points [3,4]. To do that, the Shared function performs this validation
internally and returns false when the public key is invalid (i.e., it
is a low-order point).
References:
- [1] RFC7748 by Langley, Hamburg, Turner (https://rfc-editor.org/rfc/rfc7748.txt)
- [2] Curve25519 by Bernstein (https://cr.yp.to/ecdh.html)
- [3] Bernstein (https://cr.yp.to/ecdh.html#validate)
- [4] Cremers&Jackson (https://eprint.iacr.org/2019/526)
*/
package x448
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/key.go
================================================
package x448
import (
"crypto/subtle"
fp "github.com/cloudflare/circl/math/fp448"
)
// Size is the length in bytes of a X448 key.
const Size = 56
// Key represents a X448 key.
type Key [Size]byte
func (k *Key) clamp(in *Key) *Key {
*k = *in
k[0] &= 252
k[55] |= 128
return k
}
// isValidPubKey verifies if the public key is not a low-order point.
func (k *Key) isValidPubKey() bool {
fp.Modp((*fp.Elt)(k))
var isLowOrder int
for _, P := range lowOrderPoints {
isLowOrder |= subtle.ConstantTimeCompare(P[:], k[:])
}
return isLowOrder == 0
}
// KeyGen obtains a public key given a secret key.
func KeyGen(public, secret *Key) {
ladderJoye(public.clamp(secret))
}
// Shared calculates Alice's shared key from Alice's secret key and Bob's
// public key returning true on success. A failure case happens when the public
// key is a low-order point, thus the shared key is all-zeros and the function
// returns false.
func Shared(shared, secret, public *Key) bool {
validPk := *public
ok := validPk.isValidPubKey()
ladderMontgomery(shared.clamp(secret), &validPk)
return ok
}
================================================
FILE: vendor/github.com/cloudflare/circl/dh/x448/table.go
================================================
package x448
import fp "github.com/cloudflare/circl/math/fp448"
// tableGenerator contains the set of points:
//
// t[i] = (xi+1)/(xi-1),
//
// where (xi,yi) = 2^iG and G is the generator point
// Size = (448)*(448/8) = 25088 bytes.
var tableGenerator = [448 * fp.Size]byte{
/* (2^ 0)P */ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
/* (2^ 1)P */ 0x37, 0xfa, 0xaa, 0x0d, 0x86, 0xa6, 0x24, 0xe9, 0x6c, 0x95, 0x08, 0x34, 0xba, 0x1a, 0x81, 0x3a, 0xae, 0x01, 0xa5, 0xa7, 0x05, 0x85, 0x96, 0x00, 0x06, 0x5a, 0xd7, 0xff, 0xee, 0x8e, 0x8f, 0x94, 0xd2, 0xdc, 0xd7, 0xfc, 0xe7, 0xe5, 0x99, 0x1d, 0x05, 0x46, 0x43, 0xe8, 0xbc, 0x12, 0xb7, 0xeb, 0x30, 0x5e, 0x7a, 0x85, 0x68, 0xed, 0x9d, 0x28,
/* (2^ 2)P */ 0xf1, 0x7d, 0x08, 0x2b, 0x32, 0x4a, 0x62, 0x80, 0x36, 0xe7, 0xa4, 0x76, 0x5a, 0x2a, 0x1e, 0xf7, 0x9e, 0x3c, 0x40, 0x46, 0x9a, 0x1b, 0x61, 0xc1, 0xbf, 0x1a, 0x1b, 0xae, 0x91, 0x80, 0xa3, 0x76, 0x6c, 0xd4, 0x8f, 0xa4, 0xee, 0x26, 0x39, 0x23, 0xa4, 0x80, 0xf4, 0x66, 0x92, 0xe4, 0xe1, 0x18, 0x76, 0xc5, 0xe2, 0x19, 0x87, 0xd5, 0xc3, 0xe8,
/* (2^ 3)P */ 0xfb, 0xc9, 0xf0, 0x07, 0xf2, 0x93, 0xd8, 0x50, 0x36, 0xed, 0xfb, 0xbd, 0xb2, 0xd3, 0xfc, 0xdf, 0xd5, 0x2a, 0x6e, 0x26, 0x09, 0xce, 0xd4, 0x07, 0x64, 0x9f, 0x40, 0x74, 0xad, 0x98, 0x2f, 0x1c, 0xb6, 0xdc, 0x2d, 0x42, 0xff, 0xbf, 0x97, 0xd8, 0xdb, 0xef, 0x99, 0xca, 0x73, 0x99, 0x1a, 0x04, 0x3b, 0x56, 0x2c, 0x1f, 0x87, 0x9d, 0x9f, 0x03,
/* (2^ 4)P */ 0x4c, 0x35, 0x97, 0xf7, 0x81, 0x2c, 0x84, 0xa6, 0xe0, 0xcb, 0xce, 0x37, 0x4c, 0x21, 0x1c, 0x67, 0xfa, 0xab, 0x18, 0x4d, 0xef, 0xd0, 0xf0, 0x44, 0xa9, 0xfb, 0xc0, 0x8e, 0xda, 0x57, 0xa1, 0xd8, 0xeb, 0x87, 0xf4, 0x17, 0xea, 0x66, 0x0f, 0x16, 0xea, 0xcd, 0x5f, 0x3e, 0x88, 0xea, 0x09, 0x68, 0x40, 0xdf, 0x43, 0xcc, 0x54, 0x61, 0x58, 0xaa,
/* (2^ 5)P */ 0x8d, 0xe7, 0x59, 0xd7, 0x5e, 0x63, 0x37, 0xa7, 0x3f, 0xd1, 0x49, 0x85, 0x01, 0xdd, 0x5e, 0xb3, 0xe6, 0x29, 0xcb, 0x25, 0x93, 0xdd, 0x08, 0x96, 0x83, 0x52, 0x76, 0x85, 0xf5, 0x5d, 0x02, 0xbf, 0xe9, 0x6d, 0x15, 0x27, 0xc1, 0x09, 0xd1, 0x14, 0x4d, 0x6e, 0xe8, 0xaf, 0x59, 0x58, 0x34, 0x9d, 0x2a, 0x99, 0x85, 0x26, 0xbe, 0x4b, 0x1e, 0xb9,
/* (2^ 6)P */ 0x8d, 0xce, 0x94, 0xe2, 0x18, 0x56, 0x0d, 0x82, 0x8e, 0xdf, 0x85, 0x01, 0x8f, 0x93, 0x3c, 0xc6, 0xbd, 0x61, 0xfb, 0xf4, 0x22, 0xc5, 0x16, 0x87, 0xd1, 0xb1, 0x9e, 0x09, 0xc5, 0x83, 0x2e, 0x4a, 0x07, 0x88, 0xee, 0xe0, 0x29, 0x8d, 0x2e, 0x1f, 0x88, 0xad, 0xfd, 0x18, 0x93, 0xb7, 0xed, 0x42, 0x86, 0x78, 0xf0, 0xb8, 0x70, 0xbe, 0x01, 0x67,
/* (2^ 7)P */ 0xdf, 0x62, 0x2d, 0x94, 0xc7, 0x35, 0x23, 0xda, 0x27, 0xbb, 0x2b, 0xdb, 0x30, 0x80, 0x68, 0x16, 0xa3, 0xae, 0xd7, 0xd2, 0xa7, 0x7c, 0xbf, 0x6a, 0x1d, 0x83, 0xde, 0x96, 0x0a, 0x43, 0xb6, 0x30, 0x37, 0xd6, 0xee, 0x63, 0x59, 0x9a, 0xbf, 0xa3, 0x30, 0x6c, 0xaf, 0x0c, 0xee, 0x3d, 0xcb, 0x35, 0x4b, 0x55, 0x5f, 0x84, 0x85, 0xcb, 0x4f, 0x1e,
/* (2^ 8)P */ 0x9d, 0x04, 0x68, 0x89, 0xa4, 0xa9, 0x0d, 0x87, 0xc1, 0x70, 0xf1, 0xeb, 0xfb, 0x47, 0x0a, 0xf0, 0xde, 0x67, 0xb7, 0x94, 0xcd, 0x36, 0x43, 0xa5, 0x49, 0x43, 0x67, 0xc3, 0xee, 0x3c, 0x6b, 0xec, 0xd0, 0x1a, 0xf4, 0xad, 0xef, 0x06, 0x4a, 0xe8, 0x46, 0x24, 0xd7, 0x93, 0xbf, 0xf0, 0xe3, 0x81, 0x61, 0xec, 0xea, 0x64, 0xfe, 0x67, 0xeb, 0xc7,
/* (2^ 9)P */ 0x95, 0x45, 0x79, 0xcf, 0x2c, 0xfd, 0x9b, 0xfe, 0x84, 0x46, 0x4b, 0x8f, 0xa1, 0xcf, 0xc3, 0x04, 0x94, 0x78, 0xdb, 0xc9, 0xa6, 0x01, 0x75, 0xa4, 0xb4, 0x93, 0x72, 0x43, 0xa7, 0x7d, 0xda, 0x31, 0x38, 0x54, 0xab, 0x4e, 0x3f, 0x89, 0xa6, 0xab, 0x57, 0xc0, 0x16, 0x65, 0xdb, 0x92, 0x96, 0xe4, 0xc8, 0xae, 0xe7, 0x4c, 0x7a, 0xeb, 0xbb, 0x5a,
/* (2^ 10)P */ 0xbe, 0xfe, 0x86, 0xc3, 0x97, 0xe0, 0x6a, 0x18, 0x20, 0x21, 0xca, 0x22, 0x55, 0xa1, 0xeb, 0xf5, 0x74, 0xe5, 0xc9, 0x59, 0xa7, 0x92, 0x65, 0x15, 0x08, 0x71, 0xd1, 0x09, 0x7e, 0x83, 0xfc, 0xbc, 0x5a, 0x93, 0x38, 0x0d, 0x43, 0x42, 0xfd, 0x76, 0x30, 0xe8, 0x63, 0x60, 0x09, 0x8d, 0x6c, 0xd3, 0xf8, 0x56, 0x3d, 0x68, 0x47, 0xab, 0xa0, 0x1d,
/* (2^ 11)P */ 0x38, 0x50, 0x1c, 0xb1, 0xac, 0x88, 0x8f, 0x38, 0xe3, 0x69, 0xe6, 0xfc, 0x4f, 0x8f, 0xe1, 0x9b, 0xb1, 0x1a, 0x09, 0x39, 0x19, 0xdf, 0xcd, 0x98, 0x7b, 0x64, 0x42, 0xf6, 0x11, 0xea, 0xc7, 0xe8, 0x92, 0x65, 0x00, 0x2c, 0x75, 0xb5, 0x94, 0x1e, 0x5b, 0xa6, 0x66, 0x81, 0x77, 0xf3, 0x39, 0x94, 0xac, 0xbd, 0xe4, 0x2a, 0x66, 0x84, 0x9c, 0x60,
/* (2^ 12)P */ 0xb5, 0xb6, 0xd9, 0x03, 0x67, 0xa4, 0xa8, 0x0a, 0x4a, 0x2b, 0x9d, 0xfa, 0x13, 0xe1, 0x99, 0x25, 0x4a, 0x5c, 0x67, 0xb9, 0xb2, 0xb7, 0xdd, 0x1e, 0xaf, 0xeb, 0x63, 0x41, 0xb6, 0xb9, 0xa0, 0x87, 0x0a, 0xe0, 0x06, 0x07, 0xaa, 0x97, 0xf8, 0xf9, 0x38, 0x4f, 0xdf, 0x0c, 0x40, 0x7c, 0xc3, 0x98, 0xa9, 0x74, 0xf1, 0x5d, 0xda, 0xd1, 0xc0, 0x0a,
/* (2^ 13)P */ 0xf2, 0x0a, 0xab, 0xab, 0x94, 0x50, 0xf0, 0xa3, 0x6f, 0xc6, 0x66, 0xba, 0xa6, 0xdc, 0x44, 0xdd, 0xd6, 0x08, 0xf4, 0xd3, 0xed, 0xb1, 0x40, 0x93, 0xee, 0xf6, 0xb8, 0x8e, 0xb4, 0x7c, 0xb9, 0x82, 0xc9, 0x9d, 0x45, 0x3b, 0x8e, 0x10, 0xcb, 0x70, 0x1e, 0xba, 0x3c, 0x62, 0x50, 0xda, 0xa9, 0x93, 0xb5, 0xd7, 0xd0, 0x6f, 0x29, 0x52, 0x95, 0xae,
/* (2^ 14)P */ 0x14, 0x68, 0x69, 0x23, 0xa8, 0x44, 0x87, 0x9e, 0x22, 0x91, 0xe8, 0x92, 0xdf, 0xf7, 0xae, 0xba, 0x1c, 0x96, 0xe1, 0xc3, 0x94, 0xed, 0x6c, 0x95, 0xae, 0x96, 0xa7, 0x15, 0x9f, 0xf1, 0x17, 0x11, 0x92, 0x42, 0xd5, 0xcd, 0x18, 0xe7, 0xa9, 0xb5, 0x2f, 0xcd, 0xde, 0x6c, 0xc9, 0x7d, 0xfc, 0x7e, 0xbd, 0x7f, 0x10, 0x3d, 0x01, 0x00, 0x8d, 0x95,
/* (2^ 15)P */ 0x3b, 0x76, 0x72, 0xae, 0xaf, 0x84, 0xf2, 0xf7, 0xd1, 0x6d, 0x13, 0x9c, 0x47, 0xe1, 0xb7, 0xa3, 0x19, 0x16, 0xee, 0x75, 0x45, 0xf6, 0x1a, 0x7b, 0x78, 0x49, 0x79, 0x05, 0x86, 0xf0, 0x7f, 0x9f, 0xfc, 0xc4, 0xbd, 0x86, 0xf3, 0x41, 0xa7, 0xfe, 0x01, 0xd5, 0x67, 0x16, 0x10, 0x5b, 0xa5, 0x16, 0xf3, 0x7f, 0x60, 0xce, 0xd2, 0x0c, 0x8e, 0x4b,
/* (2^ 16)P */ 0x4a, 0x07, 0x99, 0x4a, 0x0f, 0x74, 0x91, 0x14, 0x68, 0xb9, 0x48, 0xb7, 0x44, 0x77, 0x9b, 0x4a, 0xe0, 0x68, 0x0e, 0x43, 0x4d, 0x98, 0x98, 0xbf, 0xa8, 0x3a, 0xb7, 0x6d, 0x2a, 0x9a, 0x77, 0x5f, 0x62, 0xf5, 0x6b, 0x4a, 0xb7, 0x7d, 0xe5, 0x09, 0x6b, 0xc0, 0x8b, 0x9c, 0x88, 0x37, 0x33, 0xf2, 0x41, 0xac, 0x22, 0x1f, 0xcf, 0x3b, 0x82, 0x34,
/* (2^ 17)P */ 0x00, 0xc3, 0x78, 0x42, 0x32, 0x2e, 0xdc, 0xda, 0xb1, 0x96, 0x21, 0xa4, 0xe4, 0xbb, 0xe9, 0x9d, 0xbb, 0x0f, 0x93, 0xed, 0x26, 0x3d, 0xb5, 0xdb, 0x94, 0x31, 0x37, 0x07, 0xa2, 0xb2, 0xd5, 0x99, 0x0d, 0x93, 0xe1, 0xce, 0x3f, 0x0b, 0x96, 0x82, 0x47, 0xfe, 0x60, 0x6f, 0x8f, 0x61, 0x88, 0xd7, 0x05, 0x95, 0x0b, 0x46, 0x06, 0xb7, 0x32, 0x06,
/* (2^ 18)P */ 0x44, 0xf5, 0x34, 0xdf, 0x2f, 0x9c, 0x5d, 0x9f, 0x53, 0x5c, 0x42, 0x8f, 0xc9, 0xdc, 0xd8, 0x40, 0xa2, 0xe7, 0x6a, 0x4a, 0x05, 0xf7, 0x86, 0x77, 0x2b, 0xae, 0x37, 0xed, 0x48, 0xfb, 0xf7, 0x62, 0x7c, 0x17, 0x59, 0x92, 0x41, 0x61, 0x93, 0x38, 0x30, 0xd1, 0xef, 0x54, 0x54, 0x03, 0x17, 0x57, 0x91, 0x15, 0x11, 0x33, 0xb5, 0xfa, 0xfb, 0x17,
/* (2^ 19)P */ 0x29, 0xbb, 0xd4, 0xb4, 0x9c, 0xf1, 0x72, 0x94, 0xce, 0x6a, 0x29, 0xa8, 0x89, 0x18, 0x19, 0xf7, 0xb7, 0xcc, 0xee, 0x9a, 0x02, 0xe3, 0xc0, 0xb1, 0xe0, 0xee, 0x83, 0x78, 0xb4, 0x9e, 0x07, 0x87, 0xdf, 0xb0, 0x82, 0x26, 0x4e, 0xa4, 0x0c, 0x33, 0xaf, 0x40, 0x59, 0xb6, 0xdd, 0x52, 0x45, 0xf0, 0xb4, 0xf6, 0xe8, 0x4e, 0x4e, 0x79, 0x1a, 0x5d,
/* (2^ 20)P */ 0x27, 0x33, 0x4d, 0x4c, 0x6b, 0x4f, 0x75, 0xb1, 0xbc, 0x1f, 0xab, 0x5b, 0x2b, 0xf0, 0x1c, 0x57, 0x86, 0xdd, 0xfd, 0x60, 0xb0, 0x8c, 0xe7, 0x9a, 0xe5, 0x5c, 0xeb, 0x11, 0x3a, 0xda, 0x22, 0x25, 0x99, 0x06, 0x8d, 0xf4, 0xaf, 0x29, 0x7a, 0xc9, 0xe5, 0xd2, 0x16, 0x9e, 0xd4, 0x63, 0x1d, 0x64, 0xa6, 0x47, 0x96, 0x37, 0x6f, 0x93, 0x2c, 0xcc,
/* (2^ 21)P */ 0xc1, 0x94, 0x74, 0x86, 0x75, 0xf2, 0x91, 0x58, 0x23, 0x85, 0x63, 0x76, 0x54, 0xc7, 0xb4, 0x8c, 0xbc, 0x4e, 0xc4, 0xa7, 0xba, 0xa0, 0x55, 0x26, 0x71, 0xd5, 0x33, 0x72, 0xc9, 0xad, 0x1e, 0xf9, 0x5d, 0x78, 0x70, 0x93, 0x4e, 0x85, 0xfc, 0x39, 0x06, 0x73, 0x76, 0xff, 0xe8, 0x64, 0x69, 0x42, 0x45, 0xb2, 0x69, 0xb5, 0x32, 0xe7, 0x2c, 0xde,
/* (2^ 22)P */ 0xde, 0x16, 0xd8, 0x33, 0x49, 0x32, 0xe9, 0x0e, 0x3a, 0x60, 0xee, 0x2e, 0x24, 0x75, 0xe3, 0x9c, 0x92, 0x07, 0xdb, 0xad, 0x92, 0xf5, 0x11, 0xdf, 0xdb, 0xb0, 0x17, 0x5c, 0xd6, 0x1a, 0x70, 0x00, 0xb7, 0xe2, 0x18, 0xec, 0xdc, 0xc2, 0x02, 0x93, 0xb3, 0xc8, 0x3f, 0x4f, 0x1b, 0x96, 0xe6, 0x33, 0x8c, 0xfb, 0xcc, 0xa5, 0x4e, 0xe8, 0xe7, 0x11,
/* (2^ 23)P */ 0x05, 0x7a, 0x74, 0x52, 0xf8, 0xdf, 0x0d, 0x7c, 0x6a, 0x1a, 0x4e, 0x9a, 0x02, 0x1d, 0xae, 0x77, 0xf8, 0x8e, 0xf9, 0xa2, 0x38, 0x54, 0x50, 0xb2, 0x2c, 0x08, 0x9d, 0x9b, 0x9f, 0xfb, 0x2b, 0x06, 0xde, 0x9d, 0xc2, 0x03, 0x0b, 0x22, 0x2b, 0x10, 0x5b, 0x3a, 0x73, 0x29, 0x8e, 0x3e, 0x37, 0x08, 0x2c, 0x3b, 0xf8, 0x80, 0xc1, 0x66, 0x1e, 0x98,
/* (2^ 24)P */ 0xd8, 0xd6, 0x3e, 0xcd, 0x63, 0x8c, 0x2b, 0x41, 0x81, 0xc0, 0x0c, 0x06, 0x87, 0xd6, 0xe7, 0x92, 0xfe, 0xf1, 0x0c, 0x4a, 0x84, 0x5b, 0xaf, 0x40, 0x53, 0x6f, 0x60, 0xd6, 0x6b, 0x76, 0x4b, 0xc2, 0xad, 0xc9, 0xb6, 0xb6, 0x6a, 0xa2, 0xb3, 0xf5, 0xf5, 0xc2, 0x55, 0x83, 0xb2, 0xd3, 0xe9, 0x41, 0x6c, 0x63, 0x51, 0xb8, 0x81, 0x74, 0xc8, 0x2c,
/* (2^ 25)P */ 0xb2, 0xaf, 0x1c, 0xee, 0x07, 0xb0, 0x58, 0xa8, 0x2c, 0x6a, 0xc9, 0x2d, 0x62, 0x28, 0x75, 0x0c, 0x40, 0xb6, 0x11, 0x33, 0x96, 0x80, 0x28, 0x6d, 0xd5, 0x9e, 0x87, 0x90, 0x01, 0x66, 0x1d, 0x1c, 0xf8, 0xb4, 0x92, 0xac, 0x38, 0x18, 0x05, 0xc2, 0x4c, 0x4b, 0x54, 0x7d, 0x80, 0x46, 0x87, 0x2d, 0x99, 0x8e, 0x70, 0x80, 0x69, 0x71, 0x8b, 0xed,
/* (2^ 26)P */ 0x37, 0xa7, 0x6b, 0x71, 0x36, 0x75, 0x8e, 0xff, 0x0f, 0x42, 0xda, 0x5a, 0x46, 0xa6, 0x97, 0x79, 0x7e, 0x30, 0xb3, 0x8f, 0xc7, 0x3a, 0xa0, 0xcb, 0x1d, 0x9c, 0x78, 0x77, 0x36, 0xc2, 0xe7, 0xf4, 0x2f, 0x29, 0x07, 0xb1, 0x07, 0xfd, 0xed, 0x1b, 0x39, 0x77, 0x06, 0x38, 0x77, 0x0f, 0x50, 0x31, 0x12, 0xbf, 0x92, 0xbf, 0x72, 0x79, 0x54, 0xa9,
/* (2^ 27)P */ 0xbd, 0x4d, 0x46, 0x6b, 0x1a, 0x80, 0x46, 0x2d, 0xed, 0xfd, 0x64, 0x6d, 0x94, 0xbc, 0x4a, 0x6e, 0x0c, 0x12, 0xf6, 0x12, 0xab, 0x54, 0x88, 0xd3, 0x85, 0xac, 0x51, 0xae, 0x6f, 0xca, 0xc4, 0xb7, 0xec, 0x22, 0x54, 0x6d, 0x80, 0xb2, 0x1c, 0x63, 0x33, 0x76, 0x6b, 0x8e, 0x6d, 0x59, 0xcd, 0x73, 0x92, 0x5f, 0xff, 0xad, 0x10, 0x35, 0x70, 0x5f,
/* (2^ 28)P */ 0xb3, 0x84, 0xde, 0xc8, 0x04, 0x43, 0x63, 0xfa, 0x29, 0xd9, 0xf0, 0x69, 0x65, 0x5a, 0x0c, 0xe8, 0x2e, 0x0b, 0xfe, 0xb0, 0x7a, 0x42, 0xb3, 0xc3, 0xfc, 0xe6, 0xb8, 0x92, 0x29, 0xae, 0xed, 0xec, 0xd5, 0xe8, 0x4a, 0xa1, 0xbd, 0x3b, 0xd3, 0xc0, 0x07, 0xab, 0x65, 0x65, 0x35, 0x9a, 0xa6, 0x5e, 0x78, 0x18, 0x76, 0x1c, 0x15, 0x49, 0xe6, 0x75,
/* (2^ 29)P */ 0x45, 0xb3, 0x92, 0xa9, 0xc3, 0xb8, 0x11, 0x68, 0x64, 0x3a, 0x83, 0x5d, 0xa8, 0x94, 0x6a, 0x9d, 0xaa, 0x27, 0x9f, 0x98, 0x5d, 0xc0, 0x29, 0xf0, 0xc0, 0x4b, 0x14, 0x3c, 0x05, 0xe7, 0xf8, 0xbd, 0x38, 0x22, 0x96, 0x75, 0x65, 0x5e, 0x0d, 0x3f, 0xbb, 0x6f, 0xe8, 0x3f, 0x96, 0x76, 0x9f, 0xba, 0xd9, 0x44, 0x92, 0x96, 0x22, 0xe7, 0x52, 0xe7,
/* (2^ 30)P */ 0xf4, 0xa3, 0x95, 0x90, 0x47, 0xdf, 0x7d, 0xdc, 0xf4, 0x13, 0x87, 0x67, 0x7d, 0x4f, 0x9d, 0xa0, 0x00, 0x46, 0x72, 0x08, 0xc3, 0xa2, 0x7a, 0x3e, 0xe7, 0x6d, 0x52, 0x7c, 0x11, 0x36, 0x50, 0x83, 0x89, 0x64, 0xcb, 0x1f, 0x08, 0x83, 0x46, 0xcb, 0xac, 0xa6, 0xd8, 0x9c, 0x1b, 0xe8, 0x05, 0x47, 0xc7, 0x26, 0x06, 0x83, 0x39, 0xe9, 0xb1, 0x1c,
/* (2^ 31)P */ 0x11, 0xe8, 0xc8, 0x42, 0xbf, 0x30, 0x9c, 0xa3, 0xf1, 0x85, 0x96, 0x95, 0x4f, 0x4f, 0x52, 0xa2, 0xf5, 0x8b, 0x68, 0x24, 0x16, 0xac, 0x9b, 0xa9, 0x27, 0x28, 0x0e, 0x84, 0x03, 0x46, 0x22, 0x5f, 0xf7, 0x0d, 0xa6, 0x85, 0x88, 0xc1, 0x45, 0x4b, 0x85, 0x1a, 0x10, 0x7f, 0xc9, 0x94, 0x20, 0xb0, 0x04, 0x28, 0x12, 0x30, 0xb9, 0xe6, 0x40, 0x6b,
/* (2^ 32)P */ 0xac, 0x1b, 0x57, 0xb6, 0x42, 0xdb, 0x81, 0x8d, 0x76, 0xfd, 0x9b, 0x1c, 0x29, 0x30, 0xd5, 0x3a, 0xcc, 0x53, 0xd9, 0x26, 0x7a, 0x0f, 0x9c, 0x2e, 0x79, 0xf5, 0x62, 0xeb, 0x61, 0x9d, 0x9b, 0x80, 0x39, 0xcd, 0x60, 0x2e, 0x1f, 0x08, 0x22, 0xbc, 0x19, 0xb3, 0x2a, 0x43, 0x44, 0xf2, 0x4e, 0x66, 0xf4, 0x36, 0xa6, 0xa7, 0xbc, 0xa4, 0x15, 0x7e,
/* (2^ 33)P */ 0xc1, 0x90, 0x8a, 0xde, 0xff, 0x78, 0xc3, 0x73, 0x16, 0xee, 0x76, 0xa0, 0x84, 0x60, 0x8d, 0xe6, 0x82, 0x0f, 0xde, 0x4e, 0xc5, 0x99, 0x34, 0x06, 0x90, 0x44, 0x55, 0xf8, 0x91, 0xd8, 0xe1, 0xe4, 0x2c, 0x8a, 0xde, 0x94, 0x1e, 0x78, 0x25, 0x3d, 0xfd, 0xd8, 0x59, 0x7d, 0xaf, 0x6e, 0xbe, 0x96, 0xbe, 0x3c, 0x16, 0x23, 0x0f, 0x4c, 0xa4, 0x28,
/* (2^ 34)P */ 0xba, 0x11, 0x35, 0x57, 0x03, 0xb6, 0xf4, 0x24, 0x89, 0xb8, 0x5a, 0x0d, 0x50, 0x9c, 0xaa, 0x51, 0x7f, 0xa4, 0x0e, 0xfc, 0x71, 0xb3, 0x3b, 0xf1, 0x96, 0x50, 0x23, 0x15, 0xf5, 0xf5, 0xd4, 0x23, 0xdc, 0x8b, 0x26, 0x9e, 0xae, 0xb7, 0x50, 0xcd, 0xc4, 0x25, 0xf6, 0x75, 0x40, 0x9c, 0x37, 0x79, 0x33, 0x60, 0xd4, 0x4b, 0x13, 0x32, 0xee, 0xe2,
/* (2^ 35)P */ 0x43, 0xb8, 0x56, 0x59, 0xf0, 0x68, 0x23, 0xb3, 0xea, 0x70, 0x58, 0x4c, 0x1e, 0x5a, 0x16, 0x54, 0x03, 0xb2, 0xf4, 0x73, 0xb6, 0xd9, 0x5c, 0x9c, 0x6f, 0xcf, 0x82, 0x2e, 0x54, 0x15, 0x46, 0x2c, 0xa3, 0xda, 0x4e, 0x87, 0xf5, 0x2b, 0xba, 0x91, 0xa3, 0xa0, 0x89, 0xba, 0x48, 0x2b, 0xfa, 0x64, 0x02, 0x7f, 0x78, 0x03, 0xd1, 0xe8, 0x3b, 0xe9,
/* (2^ 36)P */ 0x15, 0xa4, 0x71, 0xd4, 0x0c, 0x24, 0xe9, 0x07, 0xa1, 0x43, 0xf4, 0x7f, 0xbb, 0xa2, 0xa6, 0x6b, 0xfa, 0xb7, 0xea, 0x58, 0xd1, 0x96, 0xb0, 0x24, 0x5c, 0xc7, 0x37, 0x4e, 0x60, 0x0f, 0x40, 0xf2, 0x2f, 0x44, 0x70, 0xea, 0x80, 0x63, 0xfe, 0xfc, 0x46, 0x59, 0x12, 0x27, 0xb5, 0x27, 0xfd, 0xb7, 0x73, 0x0b, 0xca, 0x8b, 0xc2, 0xd3, 0x71, 0x08,
/* (2^ 37)P */ 0x26, 0x0e, 0xd7, 0x52, 0x6f, 0xf1, 0xf2, 0x9d, 0xb8, 0x3d, 0xbd, 0xd4, 0x75, 0x97, 0xd8, 0xbf, 0xa8, 0x86, 0x96, 0xa5, 0x80, 0xa0, 0x45, 0x75, 0xf6, 0x77, 0x71, 0xdb, 0x77, 0x96, 0x55, 0x99, 0x31, 0xd0, 0x4f, 0x34, 0xf4, 0x35, 0x39, 0x41, 0xd3, 0x7d, 0xf7, 0xe2, 0x74, 0xde, 0xbe, 0x5b, 0x1f, 0x39, 0x10, 0x21, 0xa3, 0x4d, 0x3b, 0xc8,
/* (2^ 38)P */ 0x04, 0x00, 0x2a, 0x45, 0xb2, 0xaf, 0x9b, 0x18, 0x6a, 0xeb, 0x96, 0x28, 0xa4, 0x77, 0xd0, 0x13, 0xcf, 0x17, 0x65, 0xe8, 0xc5, 0x81, 0x28, 0xad, 0x39, 0x7a, 0x0b, 0xaa, 0x55, 0x2b, 0xf3, 0xfc, 0x86, 0x40, 0xad, 0x0d, 0x1e, 0x28, 0xa2, 0x2d, 0xc5, 0xd6, 0x04, 0x15, 0xa2, 0x30, 0x3d, 0x12, 0x8e, 0xd6, 0xb5, 0xf7, 0x69, 0xbb, 0x84, 0x20,
/* (2^ 39)P */ 0xd7, 0x7a, 0x77, 0x2c, 0xfb, 0x81, 0x80, 0xe9, 0x1e, 0xc6, 0x36, 0x31, 0x79, 0xc3, 0x7c, 0xa9, 0x57, 0x6b, 0xb5, 0x70, 0xfb, 0xe4, 0xa1, 0xff, 0xfd, 0x21, 0xa5, 0x7c, 0xfa, 0x44, 0xba, 0x0d, 0x96, 0x3d, 0xc4, 0x5c, 0x39, 0x52, 0x87, 0xd7, 0x22, 0x0f, 0x52, 0x88, 0x91, 0x87, 0x96, 0xac, 0xfa, 0x3b, 0xdf, 0xdc, 0x83, 0x8c, 0x99, 0x29,
/* (2^ 40)P */ 0x98, 0x6b, 0x3a, 0x8d, 0x83, 0x17, 0xe1, 0x62, 0xd8, 0x80, 0x4c, 0x97, 0xce, 0x6b, 0xaa, 0x10, 0xa7, 0xc4, 0xe9, 0xeb, 0xa5, 0xfb, 0xc9, 0xdd, 0x2d, 0xeb, 0xfc, 0x9a, 0x71, 0xcd, 0x68, 0x6e, 0xc0, 0x35, 0x64, 0x62, 0x1b, 0x95, 0x12, 0xe8, 0x53, 0xec, 0xf0, 0xf4, 0x86, 0x86, 0x78, 0x18, 0xc4, 0xc6, 0xbc, 0x5a, 0x59, 0x8f, 0x7c, 0x7e,
/* (2^ 41)P */ 0x7f, 0xd7, 0x1e, 0xc5, 0x83, 0xdc, 0x1f, 0xbe, 0x0b, 0xcf, 0x2e, 0x01, 0x01, 0xed, 0xac, 0x17, 0x3b, 0xed, 0xa4, 0x30, 0x96, 0x0e, 0x14, 0x7e, 0x19, 0x2b, 0xa5, 0x67, 0x1e, 0xb3, 0x34, 0x03, 0xa8, 0xbb, 0x0a, 0x7d, 0x08, 0x2d, 0xd5, 0x53, 0x19, 0x6f, 0x13, 0xd5, 0xc0, 0x90, 0x8a, 0xcc, 0xc9, 0x5c, 0xab, 0x24, 0xd7, 0x03, 0xf6, 0x57,
/* (2^ 42)P */ 0x49, 0xcb, 0xb4, 0x96, 0x5f, 0xa6, 0xf8, 0x71, 0x6f, 0x59, 0xad, 0x05, 0x24, 0x2d, 0xaf, 0x67, 0xa8, 0xbe, 0x95, 0xdf, 0x0d, 0x28, 0x5a, 0x7f, 0x6e, 0x87, 0x8c, 0x6e, 0x67, 0x0c, 0xf4, 0xe0, 0x1c, 0x30, 0xc2, 0x66, 0xae, 0x20, 0xa1, 0x34, 0xec, 0x9c, 0xbc, 0xae, 0x3d, 0xa1, 0x28, 0x28, 0x95, 0x1d, 0xc9, 0x3a, 0xa8, 0xfd, 0xfc, 0xa1,
/* (2^ 43)P */ 0xe2, 0x2b, 0x9d, 0xed, 0x02, 0x99, 0x67, 0xbb, 0x2e, 0x16, 0x62, 0x05, 0x70, 0xc7, 0x27, 0xb9, 0x1c, 0x3f, 0xf2, 0x11, 0x01, 0xd8, 0x51, 0xa4, 0x18, 0x92, 0xa9, 0x5d, 0xfb, 0xa9, 0xe4, 0x42, 0xba, 0x38, 0x34, 0x1a, 0x4a, 0xc5, 0x6a, 0x37, 0xde, 0xa7, 0x0c, 0xb4, 0x7e, 0x7f, 0xde, 0xa6, 0xee, 0xcd, 0x55, 0x57, 0x05, 0x06, 0xfd, 0x5d,
/* (2^ 44)P */ 0x2f, 0x32, 0xcf, 0x2e, 0x2c, 0x7b, 0xbe, 0x9a, 0x0c, 0x57, 0x35, 0xf8, 0x87, 0xda, 0x9c, 0xec, 0x48, 0xf2, 0xbb, 0xe2, 0xda, 0x10, 0x58, 0x20, 0xc6, 0xd3, 0x87, 0xe9, 0xc7, 0x26, 0xd1, 0x9a, 0x46, 0x87, 0x90, 0xda, 0xdc, 0xde, 0xc3, 0xb3, 0xf2, 0xe8, 0x6f, 0x4a, 0xe6, 0xe8, 0x9d, 0x98, 0x36, 0x20, 0x03, 0x47, 0x15, 0x3f, 0x64, 0x59,
/* (2^ 45)P */ 0xd4, 0x71, 0x49, 0x0a, 0x67, 0x97, 0xaa, 0x3f, 0xf4, 0x1b, 0x3a, 0x6e, 0x5e, 0x17, 0xcc, 0x0a, 0x8f, 0x81, 0x6a, 0x41, 0x38, 0x77, 0x40, 0x8a, 0x11, 0x42, 0x62, 0xd2, 0x50, 0x32, 0x79, 0x78, 0x28, 0xc2, 0x2e, 0x10, 0x01, 0x94, 0x30, 0x4f, 0x7f, 0x18, 0x17, 0x56, 0x85, 0x4e, 0xad, 0xf7, 0xcb, 0x87, 0x3c, 0x3f, 0x50, 0x2c, 0xc0, 0xba,
/* (2^ 46)P */ 0xbc, 0x30, 0x8e, 0x65, 0x8e, 0x57, 0x5b, 0x38, 0x7a, 0xd4, 0x95, 0x52, 0x7a, 0x32, 0x59, 0x69, 0xcd, 0x9d, 0x47, 0x34, 0x5b, 0x55, 0xa5, 0x24, 0x60, 0xdd, 0xc0, 0xc1, 0x62, 0x73, 0x44, 0xae, 0x4c, 0x9c, 0x65, 0x55, 0x1b, 0x9d, 0x8a, 0x29, 0xb0, 0x1a, 0x52, 0xa8, 0xf1, 0xe6, 0x9a, 0xb3, 0xf6, 0xa3, 0xc9, 0x0a, 0x70, 0x7d, 0x0f, 0xee,
/* (2^ 47)P */ 0x77, 0xd3, 0xe5, 0x8e, 0xfa, 0x00, 0xeb, 0x1b, 0x7f, 0xdc, 0x68, 0x3f, 0x92, 0xbd, 0xb7, 0x0b, 0xb7, 0xb5, 0x24, 0xdf, 0xc5, 0x67, 0x53, 0xd4, 0x36, 0x79, 0xc4, 0x7b, 0x57, 0xbc, 0x99, 0x97, 0x60, 0xef, 0xe4, 0x01, 0xa1, 0xa7, 0xaa, 0x12, 0x36, 0x29, 0xb1, 0x03, 0xc2, 0x83, 0x1c, 0x2b, 0x83, 0xef, 0x2e, 0x2c, 0x23, 0x92, 0xfd, 0xd1,
/* (2^ 48)P */ 0x94, 0xef, 0x03, 0x59, 0xfa, 0x8a, 0x18, 0x76, 0xee, 0x58, 0x08, 0x4d, 0x44, 0xce, 0xf1, 0x52, 0x33, 0x49, 0xf6, 0x69, 0x71, 0xe3, 0xa9, 0xbc, 0x86, 0xe3, 0x43, 0xde, 0x33, 0x7b, 0x90, 0x8b, 0x3e, 0x7d, 0xd5, 0x4a, 0xf0, 0x23, 0x99, 0xa6, 0xea, 0x5f, 0x08, 0xe5, 0xb9, 0x49, 0x8b, 0x0d, 0x6a, 0x21, 0xab, 0x07, 0x62, 0xcd, 0xc4, 0xbe,
/* (2^ 49)P */ 0x61, 0xbf, 0x70, 0x14, 0xfa, 0x4e, 0x9e, 0x7c, 0x0c, 0xf8, 0xb2, 0x48, 0x71, 0x62, 0x83, 0xd6, 0xd1, 0xdc, 0x9c, 0x29, 0x66, 0xb1, 0x34, 0x9c, 0x8d, 0xe6, 0x88, 0xaf, 0xbe, 0xdc, 0x4d, 0xeb, 0xb0, 0xe7, 0x28, 0xae, 0xb2, 0x05, 0x56, 0xc6, 0x0e, 0x10, 0x26, 0xab, 0x2c, 0x59, 0x72, 0x03, 0x66, 0xfe, 0x8f, 0x2c, 0x51, 0x2d, 0xdc, 0xae,
/* (2^ 50)P */ 0xdc, 0x63, 0xf1, 0x8b, 0x5c, 0x65, 0x0b, 0xf1, 0xa6, 0x22, 0xe2, 0xd9, 0xdb, 0x49, 0xb1, 0x3c, 0x47, 0xc2, 0xfe, 0xac, 0x86, 0x07, 0x52, 0xec, 0xb0, 0x08, 0x69, 0xfb, 0xd1, 0x06, 0xdc, 0x48, 0x5c, 0x3d, 0xb2, 0x4d, 0xb8, 0x1a, 0x4e, 0xda, 0xb9, 0xc1, 0x2b, 0xab, 0x4b, 0x62, 0x81, 0x21, 0x9a, 0xfc, 0x3d, 0x39, 0x83, 0x11, 0x36, 0xeb,
/* (2^ 51)P */ 0x94, 0xf3, 0x17, 0xef, 0xf9, 0x60, 0x54, 0xc3, 0xd7, 0x27, 0x35, 0xc5, 0x98, 0x5e, 0xf6, 0x63, 0x6c, 0xa0, 0x4a, 0xd3, 0xa3, 0x98, 0xd9, 0x42, 0xe3, 0xf1, 0xf8, 0x81, 0x96, 0xa9, 0xea, 0x6d, 0x4b, 0x8e, 0x33, 0xca, 0x94, 0x0d, 0xa0, 0xf7, 0xbb, 0x64, 0xa3, 0x36, 0x6f, 0xdc, 0x5a, 0x94, 0x42, 0xca, 0x06, 0xb2, 0x2b, 0x9a, 0x9f, 0x71,
/* (2^ 52)P */ 0xec, 0xdb, 0xa6, 0x1f, 0xdf, 0x15, 0x36, 0xa3, 0xda, 0x8a, 0x7a, 0xb6, 0xa7, 0xe3, 0xaf, 0x52, 0xe0, 0x8d, 0xe8, 0xf2, 0x44, 0x20, 0xeb, 0xa1, 0x20, 0xc4, 0x65, 0x3c, 0x7c, 0x6c, 0x49, 0xed, 0x2f, 0x66, 0x23, 0x68, 0x61, 0x91, 0x40, 0x9f, 0x50, 0x19, 0xd1, 0x84, 0xa7, 0xe2, 0xed, 0x34, 0x37, 0xe3, 0xe4, 0x11, 0x7f, 0x87, 0x55, 0x0f,
/* (2^ 53)P */ 0xb3, 0xa1, 0x0f, 0xb0, 0x48, 0xc0, 0x4d, 0x96, 0xa7, 0xcf, 0x5a, 0x81, 0xb8, 0x4a, 0x46, 0xef, 0x0a, 0xd3, 0x40, 0x7e, 0x02, 0xe3, 0x63, 0xaa, 0x50, 0xd1, 0x2a, 0x37, 0x22, 0x4a, 0x7f, 0x4f, 0xb6, 0xf9, 0x01, 0x82, 0x78, 0x3d, 0x93, 0x14, 0x11, 0x8a, 0x90, 0x60, 0xcd, 0x45, 0x4e, 0x7b, 0x42, 0xb9, 0x3e, 0x6e, 0x68, 0x1f, 0x36, 0x41,
/* (2^ 54)P */ 0x13, 0x73, 0x0e, 0x4f, 0x79, 0x93, 0x9e, 0x29, 0x70, 0x7b, 0x4a, 0x59, 0x1a, 0x9a, 0xf4, 0x55, 0x08, 0xf0, 0xdb, 0x17, 0x58, 0xec, 0x64, 0xad, 0x7f, 0x29, 0xeb, 0x3f, 0x85, 0x4e, 0x60, 0x28, 0x98, 0x1f, 0x73, 0x4e, 0xe6, 0xa8, 0xab, 0xd5, 0xd6, 0xfc, 0xa1, 0x36, 0x6d, 0x15, 0xc6, 0x13, 0x83, 0xa0, 0xc2, 0x6e, 0xd9, 0xdb, 0xc9, 0xcc,
/* (2^ 55)P */ 0xff, 0xd8, 0x52, 0xa3, 0xdc, 0x99, 0xcf, 0x3e, 0x19, 0xb3, 0x68, 0xd0, 0xb5, 0x0d, 0xb8, 0xee, 0x3f, 0xef, 0x6e, 0xc0, 0x38, 0x28, 0x44, 0x92, 0x78, 0x91, 0x1a, 0x08, 0x78, 0x6c, 0x65, 0x24, 0xf3, 0xa2, 0x3d, 0xf2, 0xe5, 0x79, 0x62, 0x69, 0x29, 0xf4, 0x22, 0xc5, 0xdb, 0x6a, 0xae, 0xf4, 0x44, 0xa3, 0x6f, 0xc7, 0x86, 0xab, 0xef, 0xef,
/* (2^ 56)P */ 0xbf, 0x54, 0x9a, 0x09, 0x5d, 0x17, 0xd0, 0xde, 0xfb, 0xf5, 0xca, 0xff, 0x13, 0x20, 0x88, 0x82, 0x3a, 0xe2, 0xd0, 0x3b, 0xfb, 0x05, 0x76, 0xd1, 0xc0, 0x02, 0x71, 0x3b, 0x94, 0xe8, 0xc9, 0x84, 0xcf, 0xa4, 0xe9, 0x28, 0x7b, 0xf5, 0x09, 0xc3, 0x2b, 0x22, 0x40, 0xf1, 0x68, 0x24, 0x24, 0x7d, 0x9f, 0x6e, 0xcd, 0xfe, 0xb0, 0x19, 0x61, 0xf5,
/* (2^ 57)P */ 0xe8, 0x63, 0x51, 0xb3, 0x95, 0x6b, 0x7b, 0x74, 0x92, 0x52, 0x45, 0xa4, 0xed, 0xea, 0x0e, 0x0d, 0x2b, 0x01, 0x1e, 0x2c, 0xbc, 0x91, 0x06, 0x69, 0xdb, 0x1f, 0xb5, 0x77, 0x1d, 0x56, 0xf5, 0xb4, 0x02, 0x80, 0x49, 0x56, 0x12, 0xce, 0x86, 0x05, 0xc9, 0xd9, 0xae, 0xf3, 0x6d, 0xe6, 0x3f, 0x40, 0x52, 0xe9, 0x49, 0x2b, 0x31, 0x06, 0x86, 0x14,
/* (2^ 58)P */ 0xf5, 0x09, 0x3b, 0xd2, 0xff, 0xdf, 0x11, 0xa5, 0x1c, 0x99, 0xe8, 0x1b, 0xa4, 0x2c, 0x7d, 0x8e, 0xc8, 0xf7, 0x03, 0x46, 0xfa, 0xb6, 0xde, 0x73, 0x91, 0x7e, 0x5a, 0x7a, 0xd7, 0x9a, 0x5b, 0x80, 0x24, 0x62, 0x5e, 0x92, 0xf1, 0xa3, 0x45, 0xa3, 0x43, 0x92, 0x8a, 0x2a, 0x5b, 0x0c, 0xb4, 0xc8, 0xad, 0x1c, 0xb6, 0x6c, 0x5e, 0x81, 0x18, 0x91,
/* (2^ 59)P */ 0x96, 0xb3, 0xca, 0x2b, 0xe3, 0x7a, 0x59, 0x72, 0x17, 0x74, 0x29, 0x21, 0xe7, 0x78, 0x07, 0xad, 0xda, 0xb6, 0xcd, 0xf9, 0x27, 0x4d, 0xc8, 0xf2, 0x98, 0x22, 0xca, 0xf2, 0x33, 0x74, 0x7a, 0xdd, 0x1e, 0x71, 0xec, 0xe3, 0x3f, 0xe2, 0xa2, 0xd2, 0x38, 0x75, 0xb0, 0xd0, 0x0a, 0xcf, 0x7d, 0x36, 0xdc, 0x49, 0x38, 0x25, 0x34, 0x4f, 0x20, 0x9a,
/* (2^ 60)P */ 0x2b, 0x6e, 0x04, 0x0d, 0x4f, 0x3d, 0x3b, 0x24, 0xf6, 0x4e, 0x5e, 0x0a, 0xbd, 0x48, 0x96, 0xba, 0x81, 0x8f, 0x39, 0x82, 0x13, 0xe6, 0x72, 0xf3, 0x0f, 0xb6, 0x94, 0xf4, 0xc5, 0x90, 0x74, 0x91, 0xa8, 0xf2, 0xc9, 0xca, 0x9a, 0x4d, 0x98, 0xf2, 0xdf, 0x52, 0x4e, 0x97, 0x2f, 0xeb, 0x84, 0xd3, 0xaf, 0xc2, 0xcc, 0xfb, 0x4c, 0x26, 0x4b, 0xe4,
/* (2^ 61)P */ 0x12, 0x9e, 0xfb, 0x9d, 0x78, 0x79, 0x99, 0xdd, 0xb3, 0x0b, 0x2e, 0x56, 0x41, 0x8e, 0x3f, 0x39, 0xb8, 0x97, 0x89, 0x53, 0x9b, 0x8a, 0x3c, 0x40, 0x9d, 0xa4, 0x6c, 0x2e, 0x31, 0x71, 0xc6, 0x0a, 0x41, 0xd4, 0x95, 0x06, 0x5e, 0xc1, 0xab, 0xc2, 0x14, 0xc4, 0xc7, 0x15, 0x08, 0x3a, 0xad, 0x7a, 0xb4, 0x62, 0xa3, 0x0c, 0x90, 0xf4, 0x47, 0x08,
/* (2^ 62)P */ 0x7f, 0xec, 0x09, 0x82, 0xf5, 0x94, 0x09, 0x93, 0x32, 0xd3, 0xdc, 0x56, 0x80, 0x7b, 0x5b, 0x22, 0x80, 0x6a, 0x96, 0x72, 0xb1, 0xc2, 0xd9, 0xa1, 0x8b, 0x66, 0x42, 0x16, 0xe2, 0x07, 0xb3, 0x2d, 0xf1, 0x75, 0x35, 0x72, 0xc7, 0x98, 0xbe, 0x63, 0x3b, 0x20, 0x75, 0x05, 0xc1, 0x3e, 0x31, 0x5a, 0xf7, 0xaa, 0xae, 0x4b, 0xdb, 0x1d, 0xd0, 0x74,
/* (2^ 63)P */ 0x36, 0x5c, 0x74, 0xe6, 0x5d, 0x59, 0x3f, 0x15, 0x4b, 0x4d, 0x4e, 0x67, 0x41, 0xfe, 0x98, 0x1f, 0x49, 0x76, 0x91, 0x0f, 0x9b, 0xf4, 0xaf, 0x86, 0xaf, 0x66, 0x19, 0xed, 0x46, 0xf1, 0x05, 0x9a, 0xcc, 0xd1, 0x14, 0x1f, 0x82, 0x12, 0x8e, 0xe6, 0xf4, 0xc3, 0x42, 0x5c, 0x4e, 0x33, 0x93, 0xbe, 0x30, 0xe7, 0x64, 0xa9, 0x35, 0x00, 0x4d, 0xf9,
/* (2^ 64)P */ 0x1f, 0xc1, 0x1e, 0xb7, 0xe3, 0x7c, 0xfa, 0xa3, 0x6b, 0x76, 0xaf, 0x9c, 0x05, 0x85, 0x4a, 0xa9, 0xfb, 0xe3, 0x7e, 0xf2, 0x49, 0x56, 0xdc, 0x2f, 0x57, 0x10, 0xba, 0x37, 0xb2, 0x62, 0xf5, 0x6b, 0xe5, 0x8f, 0x0a, 0x87, 0xd1, 0x6a, 0xcb, 0x9d, 0x07, 0xd0, 0xf6, 0x38, 0x99, 0x2c, 0x61, 0x4a, 0x4e, 0xd8, 0xd2, 0x88, 0x29, 0x99, 0x11, 0x95,
/* (2^ 65)P */ 0x6f, 0xdc, 0xd5, 0xd6, 0xd6, 0xa7, 0x4c, 0x46, 0x93, 0x65, 0x62, 0x23, 0x95, 0x32, 0x9c, 0xde, 0x40, 0x41, 0x68, 0x2c, 0x18, 0x4e, 0x5a, 0x8c, 0xc0, 0xc5, 0xc5, 0xea, 0x5c, 0x45, 0x0f, 0x60, 0x78, 0x39, 0xb6, 0x36, 0x23, 0x12, 0xbc, 0x21, 0x9a, 0xf8, 0x91, 0xac, 0xc4, 0x70, 0xdf, 0x85, 0x8e, 0x3c, 0xec, 0x22, 0x04, 0x98, 0xa8, 0xaa,
/* (2^ 66)P */ 0xcc, 0x52, 0x10, 0x5b, 0x4b, 0x6c, 0xc5, 0xfa, 0x3e, 0xd4, 0xf8, 0x1c, 0x04, 0x14, 0x48, 0x33, 0xd9, 0xfc, 0x5f, 0xb0, 0xa5, 0x48, 0x8c, 0x45, 0x8a, 0xee, 0x3e, 0xa7, 0xc1, 0x2e, 0x34, 0xca, 0xf6, 0xc9, 0xeb, 0x10, 0xbb, 0xe1, 0x59, 0x84, 0x25, 0xe8, 0x81, 0x70, 0xc0, 0x09, 0x42, 0xa7, 0x3b, 0x0d, 0x33, 0x00, 0xb5, 0x77, 0xbe, 0x25,
/* (2^ 67)P */ 0xcd, 0x1f, 0xbc, 0x7d, 0xef, 0xe5, 0xca, 0x91, 0xaf, 0xa9, 0x59, 0x6a, 0x09, 0xca, 0xd6, 0x1b, 0x3d, 0x55, 0xde, 0xa2, 0x6a, 0x80, 0xd6, 0x95, 0x47, 0xe4, 0x5f, 0x68, 0x54, 0x08, 0xdf, 0x29, 0xba, 0x2a, 0x02, 0x84, 0xe8, 0xe9, 0x00, 0x77, 0x99, 0x36, 0x03, 0xf6, 0x4a, 0x3e, 0x21, 0x81, 0x7d, 0xb8, 0xa4, 0x8a, 0xa2, 0x05, 0xef, 0xbc,
/* (2^ 68)P */ 0x7c, 0x59, 0x5f, 0x66, 0xd9, 0xb7, 0x83, 0x43, 0x8a, 0xa1, 0x8d, 0x51, 0x70, 0xba, 0xf2, 0x9b, 0x95, 0xc0, 0x4b, 0x4c, 0xa0, 0x14, 0xd3, 0xa4, 0x5d, 0x4a, 0x37, 0x36, 0x97, 0x31, 0x1e, 0x12, 0xe7, 0xbb, 0x08, 0x67, 0xa5, 0x23, 0xd7, 0xfb, 0x97, 0xd8, 0x6a, 0x03, 0xb1, 0xf8, 0x7f, 0xda, 0x58, 0xd9, 0x3f, 0x73, 0x4a, 0x53, 0xe1, 0x7b,
/* (2^ 69)P */ 0x55, 0x83, 0x98, 0x78, 0x6c, 0x56, 0x5e, 0xed, 0xf7, 0x23, 0x3e, 0x4c, 0x7d, 0x09, 0x2d, 0x09, 0x9c, 0x58, 0x8b, 0x32, 0xca, 0xfe, 0xbf, 0x47, 0x03, 0xeb, 0x4d, 0xe7, 0xeb, 0x9c, 0x83, 0x05, 0x68, 0xaa, 0x80, 0x89, 0x44, 0xf9, 0xd4, 0xdc, 0xdb, 0xb1, 0xdb, 0x77, 0xac, 0xf9, 0x2a, 0xae, 0x35, 0xac, 0x74, 0xb5, 0x95, 0x62, 0x18, 0x85,
/* (2^ 70)P */ 0xab, 0x82, 0x7e, 0x10, 0xd7, 0xe6, 0x57, 0xd1, 0x66, 0x12, 0x31, 0x9c, 0x9c, 0xa6, 0x27, 0x59, 0x71, 0x2e, 0xeb, 0xa0, 0x68, 0xc5, 0x87, 0x51, 0xf4, 0xca, 0x3f, 0x98, 0x56, 0xb0, 0x89, 0xb1, 0xc7, 0x7b, 0x46, 0xb3, 0xae, 0x36, 0xf2, 0xee, 0x15, 0x1a, 0x60, 0xf4, 0x50, 0x76, 0x4f, 0xc4, 0x53, 0x0d, 0x36, 0x4d, 0x31, 0xb1, 0x20, 0x51,
/* (2^ 71)P */ 0xf7, 0x1d, 0x8c, 0x1b, 0x5e, 0xe5, 0x02, 0x6f, 0xc5, 0xa5, 0xe0, 0x5f, 0xc6, 0xb6, 0x63, 0x43, 0xaf, 0x3c, 0x19, 0x6c, 0xf4, 0xaf, 0xa4, 0x33, 0xb1, 0x0a, 0x37, 0x3d, 0xd9, 0x4d, 0xe2, 0x29, 0x24, 0x26, 0x94, 0x7c, 0x02, 0xe4, 0xe2, 0xf2, 0xbe, 0xbd, 0xac, 0x1b, 0x48, 0xb8, 0xdd, 0xe9, 0x0d, 0x9a, 0x50, 0x1a, 0x98, 0x71, 0x6e, 0xdc,
/* (2^ 72)P */ 0x9f, 0x40, 0xb1, 0xb3, 0x66, 0x28, 0x6c, 0xfe, 0xa6, 0x7d, 0xf8, 0x3e, 0xb8, 0xf3, 0xde, 0x52, 0x76, 0x52, 0xa3, 0x92, 0x98, 0x23, 0xab, 0x4f, 0x88, 0x97, 0xfc, 0x22, 0xe1, 0x6b, 0x67, 0xcd, 0x13, 0x95, 0xda, 0x65, 0xdd, 0x3b, 0x67, 0x3f, 0x5f, 0x4c, 0xf2, 0x8a, 0xad, 0x98, 0xa7, 0x94, 0x24, 0x45, 0x87, 0x11, 0x7c, 0x75, 0x79, 0x85,
/* (2^ 73)P */ 0x70, 0xbf, 0xf9, 0x3b, 0xa9, 0x44, 0x57, 0x72, 0x96, 0xc9, 0xa4, 0x98, 0x65, 0xbf, 0x87, 0xb3, 0x3a, 0x39, 0x12, 0xde, 0xe5, 0x39, 0x01, 0x4f, 0xf7, 0xc0, 0x71, 0x52, 0x36, 0x85, 0xb3, 0x18, 0xf8, 0x14, 0xc0, 0x6d, 0xae, 0x9e, 0x4f, 0xb0, 0x72, 0x87, 0xac, 0x5c, 0xd1, 0x6c, 0x41, 0x6c, 0x90, 0x9d, 0x22, 0x81, 0xe4, 0x2b, 0xea, 0xe5,
/* (2^ 74)P */ 0xfc, 0xea, 0x1a, 0x65, 0xd9, 0x49, 0x6a, 0x39, 0xb5, 0x96, 0x72, 0x7b, 0x32, 0xf1, 0xd0, 0xe9, 0x45, 0xd9, 0x31, 0x55, 0xc7, 0x34, 0xe9, 0x5a, 0xec, 0x73, 0x0b, 0x03, 0xc4, 0xb3, 0xe6, 0xc9, 0x5e, 0x0a, 0x17, 0xfe, 0x53, 0x66, 0x7f, 0x21, 0x18, 0x74, 0x54, 0x1b, 0xc9, 0x49, 0x16, 0xd2, 0x48, 0xaf, 0x5b, 0x47, 0x7b, 0xeb, 0xaa, 0xc9,
/* (2^ 75)P */ 0x47, 0x04, 0xf5, 0x5a, 0x87, 0x77, 0x9e, 0x21, 0x34, 0x4e, 0x83, 0x88, 0xaf, 0x02, 0x1d, 0xb0, 0x5a, 0x1d, 0x1d, 0x7d, 0x8d, 0x2c, 0xd3, 0x8d, 0x63, 0xa9, 0x45, 0xfb, 0x15, 0x6d, 0x86, 0x45, 0xcd, 0x38, 0x0e, 0xf7, 0x37, 0x79, 0xed, 0x6d, 0x5a, 0xbc, 0x32, 0xcc, 0x66, 0xf1, 0x3a, 0xb2, 0x87, 0x6f, 0x70, 0x71, 0xd9, 0xf2, 0xfa, 0x7b,
/* (2^ 76)P */ 0x68, 0x07, 0xdc, 0x61, 0x40, 0xe4, 0xec, 0x32, 0xc8, 0xbe, 0x66, 0x30, 0x54, 0x80, 0xfd, 0x13, 0x7a, 0xef, 0xae, 0xed, 0x2e, 0x00, 0x6d, 0x3f, 0xbd, 0xfc, 0x91, 0x24, 0x53, 0x7f, 0x63, 0x9d, 0x2e, 0xe3, 0x76, 0xe0, 0xf3, 0xe1, 0x8f, 0x7a, 0xc4, 0x77, 0x0c, 0x91, 0xc0, 0xc2, 0x18, 0x6b, 0x04, 0xad, 0xb6, 0x70, 0x9a, 0x64, 0xc5, 0x82,
/* (2^ 77)P */ 0x7f, 0xea, 0x13, 0xd8, 0x9e, 0xfc, 0x5b, 0x06, 0xb5, 0x4f, 0xda, 0x38, 0xe0, 0x9c, 0xd2, 0x3a, 0xc1, 0x1c, 0x62, 0x70, 0x7f, 0xc6, 0x24, 0x0a, 0x47, 0x04, 0x01, 0xc4, 0x55, 0x09, 0xd1, 0x7a, 0x07, 0xba, 0xa3, 0x80, 0x4f, 0xc1, 0x65, 0x36, 0x6d, 0xc0, 0x10, 0xcf, 0x94, 0xa9, 0xa2, 0x01, 0x44, 0xd1, 0xf9, 0x1c, 0x4c, 0xfb, 0xf8, 0x99,
/* (2^ 78)P */ 0x6c, 0xb9, 0x6b, 0xee, 0x43, 0x5b, 0xb9, 0xbb, 0xee, 0x2e, 0x52, 0xc1, 0xc6, 0xb9, 0x61, 0xd2, 0x93, 0xa5, 0xaf, 0x52, 0xf4, 0xa4, 0x1a, 0x51, 0x61, 0xa7, 0xcb, 0x9e, 0xbb, 0x56, 0x65, 0xe2, 0xbf, 0x75, 0xb9, 0x9c, 0x50, 0x96, 0x60, 0x81, 0x74, 0x47, 0xc0, 0x04, 0x88, 0x71, 0x76, 0x39, 0x9a, 0xa7, 0xb1, 0x4e, 0x43, 0x15, 0xe0, 0xbb,
/* (2^ 79)P */ 0xbb, 0xce, 0xe2, 0xbb, 0xf9, 0x17, 0x0f, 0x82, 0x40, 0xad, 0x73, 0xe3, 0xeb, 0x3b, 0x06, 0x1a, 0xcf, 0x8e, 0x6e, 0x28, 0xb8, 0x26, 0xd9, 0x5b, 0xb7, 0xb3, 0xcf, 0xb4, 0x6a, 0x1c, 0xbf, 0x7f, 0xb8, 0xb5, 0x79, 0xcf, 0x45, 0x68, 0x7d, 0xc5, 0xeb, 0xf3, 0xbe, 0x39, 0x40, 0xfc, 0x07, 0x90, 0x7a, 0x62, 0xad, 0x86, 0x08, 0x71, 0x25, 0xe1,
/* (2^ 80)P */ 0x9b, 0x46, 0xac, 0xef, 0xc1, 0x4e, 0xa1, 0x97, 0x95, 0x76, 0xf9, 0x1b, 0xc2, 0xb2, 0x6a, 0x41, 0xea, 0x80, 0x3d, 0xe9, 0x08, 0x52, 0x5a, 0xe3, 0xf2, 0x08, 0xc5, 0xea, 0x39, 0x3f, 0x44, 0x71, 0x4d, 0xea, 0x0d, 0x05, 0x23, 0xe4, 0x2e, 0x3c, 0x89, 0xfe, 0x12, 0x8a, 0x95, 0x42, 0x0a, 0x68, 0xea, 0x5a, 0x28, 0x06, 0x9e, 0xe3, 0x5f, 0xe0,
/* (2^ 81)P */ 0x00, 0x61, 0x6c, 0x98, 0x9b, 0xe7, 0xb9, 0x06, 0x1c, 0xc5, 0x1b, 0xed, 0xbe, 0xc8, 0xb3, 0xea, 0x87, 0xf0, 0xc4, 0x24, 0x7d, 0xbb, 0x5d, 0xa4, 0x1d, 0x7a, 0x16, 0x00, 0x55, 0x94, 0x67, 0x78, 0xbd, 0x58, 0x02, 0x82, 0x90, 0x53, 0x76, 0xd4, 0x72, 0x99, 0x51, 0x6f, 0x7b, 0xcf, 0x80, 0x30, 0x31, 0x3b, 0x01, 0xc7, 0xc1, 0xef, 0xe6, 0x42,
/* (2^ 82)P */ 0xe2, 0x35, 0xaf, 0x4b, 0x79, 0xc6, 0x12, 0x24, 0x99, 0xc0, 0x68, 0xb0, 0x43, 0x3e, 0xe5, 0xef, 0xe2, 0x29, 0xea, 0xb8, 0xb3, 0xbc, 0x6a, 0x53, 0x2c, 0x69, 0x18, 0x5a, 0xf9, 0x15, 0xae, 0x66, 0x58, 0x18, 0xd3, 0x2d, 0x4b, 0x00, 0xfd, 0x84, 0xab, 0x4f, 0xae, 0x70, 0x6b, 0x9e, 0x9a, 0xdf, 0x83, 0xfd, 0x2e, 0x3c, 0xcf, 0xf8, 0x88, 0x5b,
/* (2^ 83)P */ 0xa4, 0x90, 0x31, 0x85, 0x13, 0xcd, 0xdf, 0x64, 0xc9, 0xa1, 0x0b, 0xe7, 0xb6, 0x73, 0x8a, 0x1b, 0x22, 0x78, 0x4c, 0xd4, 0xae, 0x48, 0x18, 0x00, 0x00, 0xa8, 0x9f, 0x06, 0xf9, 0xfb, 0x2d, 0xc3, 0xb1, 0x2a, 0xbc, 0x13, 0x99, 0x57, 0xaf, 0xf0, 0x8d, 0x61, 0x54, 0x29, 0xd5, 0xf2, 0x72, 0x00, 0x96, 0xd1, 0x85, 0x12, 0x8a, 0xf0, 0x23, 0xfb,
/* (2^ 84)P */ 0x69, 0xc7, 0xdb, 0xd9, 0x92, 0x75, 0x08, 0x9b, 0xeb, 0xa5, 0x93, 0xd1, 0x1a, 0xf4, 0xf5, 0xaf, 0xe6, 0xc4, 0x4a, 0x0d, 0x35, 0x26, 0x39, 0x9d, 0xd3, 0x17, 0x3e, 0xae, 0x2d, 0xbf, 0x73, 0x9f, 0xb7, 0x74, 0x91, 0xd1, 0xd8, 0x5c, 0x14, 0xf9, 0x75, 0xdf, 0xeb, 0xc2, 0x22, 0xd8, 0x14, 0x8d, 0x86, 0x23, 0x4d, 0xd1, 0x2d, 0xdb, 0x6b, 0x42,
/* (2^ 85)P */ 0x8c, 0xda, 0xc6, 0xf8, 0x71, 0xba, 0x2b, 0x06, 0x78, 0xae, 0xcc, 0x3a, 0xe3, 0xe3, 0xa1, 0x8b, 0xe2, 0x34, 0x6d, 0x28, 0x9e, 0x46, 0x13, 0x4d, 0x9e, 0xa6, 0x73, 0x49, 0x65, 0x79, 0x88, 0xb9, 0x3a, 0xd1, 0x6d, 0x2f, 0x48, 0x2b, 0x0a, 0x7f, 0x58, 0x20, 0x37, 0xf4, 0x0e, 0xbb, 0x4a, 0x95, 0x58, 0x0c, 0x88, 0x30, 0xc4, 0x74, 0xdd, 0xfd,
/* (2^ 86)P */ 0x6d, 0x13, 0x4e, 0x89, 0x2d, 0xa9, 0xa3, 0xed, 0x09, 0xe3, 0x0e, 0x71, 0x3e, 0x4a, 0xab, 0x90, 0xde, 0x03, 0xeb, 0x56, 0x46, 0x60, 0x06, 0xf5, 0x71, 0xe5, 0xee, 0x9b, 0xef, 0xff, 0xc4, 0x2c, 0x9f, 0x37, 0x48, 0x45, 0x94, 0x12, 0x41, 0x81, 0x15, 0x70, 0x91, 0x99, 0x5e, 0x56, 0x6b, 0xf4, 0xa6, 0xc9, 0xf5, 0x69, 0x9d, 0x78, 0x37, 0x57,
/* (2^ 87)P */ 0xf3, 0x51, 0x57, 0x7e, 0x43, 0x6f, 0xc6, 0x67, 0x59, 0x0c, 0xcf, 0x94, 0xe6, 0x3d, 0xb5, 0x07, 0xc9, 0x77, 0x48, 0xc9, 0x68, 0x0d, 0x98, 0x36, 0x62, 0x35, 0x38, 0x1c, 0xf5, 0xc5, 0xec, 0x66, 0x78, 0xfe, 0x47, 0xab, 0x26, 0xd6, 0x44, 0xb6, 0x06, 0x0f, 0x89, 0xe3, 0x19, 0x40, 0x1a, 0xe7, 0xd8, 0x65, 0x55, 0xf7, 0x1a, 0xfc, 0xa3, 0x0e,
/* (2^ 88)P */ 0x0e, 0x30, 0xa6, 0xb7, 0x58, 0x60, 0x62, 0x2a, 0x6c, 0x13, 0xa8, 0x14, 0x9b, 0xb8, 0xf2, 0x70, 0xd8, 0xb1, 0x71, 0x88, 0x8c, 0x18, 0x31, 0x25, 0x93, 0x90, 0xb4, 0xc7, 0x49, 0xd8, 0xd4, 0xdb, 0x1e, 0x1e, 0x7f, 0xaa, 0xba, 0xc9, 0xf2, 0x5d, 0xa9, 0x3a, 0x43, 0xb4, 0x5c, 0xee, 0x7b, 0xc7, 0x97, 0xb7, 0x66, 0xd7, 0x23, 0xd9, 0x22, 0x59,
/* (2^ 89)P */ 0x28, 0x19, 0xa6, 0xf9, 0x89, 0x20, 0x78, 0xd4, 0x6d, 0xcb, 0x79, 0x8f, 0x61, 0x6f, 0xb2, 0x5c, 0x4f, 0xa6, 0x54, 0x84, 0x95, 0x24, 0x36, 0x64, 0xcb, 0x39, 0xe7, 0x8f, 0x97, 0x9c, 0x5c, 0x3c, 0xfb, 0x51, 0x11, 0x01, 0x17, 0xdb, 0xc9, 0x9b, 0x51, 0x03, 0x9a, 0xe9, 0xe5, 0x24, 0x1e, 0xf5, 0xda, 0xe0, 0x48, 0x02, 0x23, 0xd0, 0x2c, 0x81,
/* (2^ 90)P */ 0x42, 0x1b, 0xe4, 0x91, 0x85, 0x2a, 0x0c, 0xd2, 0x28, 0x66, 0x57, 0x9e, 0x33, 0x8d, 0x25, 0x71, 0x10, 0x65, 0x76, 0xa2, 0x8c, 0x21, 0x86, 0x81, 0x15, 0xc2, 0x27, 0xeb, 0x54, 0x2d, 0x4f, 0x6c, 0xe6, 0xd6, 0x24, 0x9c, 0x1a, 0x12, 0xb8, 0x81, 0xe2, 0x0a, 0xf3, 0xd3, 0xf0, 0xd3, 0xe1, 0x74, 0x1f, 0x9b, 0x11, 0x47, 0xd0, 0xcf, 0xb6, 0x54,
/* (2^ 91)P */ 0x26, 0x45, 0xa2, 0x10, 0xd4, 0x2d, 0xae, 0xc0, 0xb0, 0xe8, 0x86, 0xb3, 0xc7, 0xea, 0x70, 0x87, 0x61, 0xb5, 0xa5, 0x55, 0xbe, 0x88, 0x1d, 0x7a, 0xd9, 0x6f, 0xeb, 0x83, 0xe2, 0x44, 0x7f, 0x98, 0x04, 0xd6, 0x50, 0x9d, 0xa7, 0x86, 0x66, 0x09, 0x63, 0xe1, 0xed, 0x72, 0xb1, 0xe4, 0x1d, 0x3a, 0xfd, 0x47, 0xce, 0x1c, 0xaa, 0x3b, 0x8f, 0x1b,
/* (2^ 92)P */ 0xf4, 0x3c, 0x4a, 0xb6, 0xc2, 0x9c, 0xe0, 0x2e, 0xb7, 0x38, 0xea, 0x61, 0x35, 0x97, 0x10, 0x90, 0xae, 0x22, 0x48, 0xb3, 0xa9, 0xc6, 0x7a, 0xbb, 0x23, 0xf2, 0xf8, 0x1b, 0xa7, 0xa1, 0x79, 0xcc, 0xc4, 0xf8, 0x08, 0x76, 0x8a, 0x5a, 0x1c, 0x1b, 0xc5, 0x33, 0x91, 0xa9, 0xb8, 0xb9, 0xd3, 0xf8, 0x49, 0xcd, 0xe5, 0x82, 0x43, 0xf7, 0xca, 0x68,
/* (2^ 93)P */ 0x38, 0xba, 0xae, 0x44, 0xfe, 0x57, 0x64, 0x56, 0x7c, 0x0e, 0x9c, 0xca, 0xff, 0xa9, 0x82, 0xbb, 0x38, 0x4a, 0xa7, 0xf7, 0x47, 0xab, 0xbe, 0x6d, 0x23, 0x0b, 0x8a, 0xed, 0xc2, 0xb9, 0x8f, 0xf1, 0xec, 0x91, 0x44, 0x73, 0x64, 0xba, 0xd5, 0x8f, 0x37, 0x38, 0x0d, 0xd5, 0xf8, 0x73, 0x57, 0xb6, 0xc2, 0x45, 0xdc, 0x25, 0xb2, 0xb6, 0xea, 0xd9,
/* (2^ 94)P */ 0xbf, 0xe9, 0x1a, 0x40, 0x4d, 0xcc, 0xe6, 0x1d, 0x70, 0x1a, 0x65, 0xcc, 0x34, 0x2c, 0x37, 0x2c, 0x2d, 0x6b, 0x6d, 0xe5, 0x2f, 0x19, 0x9e, 0xe4, 0xe1, 0xaa, 0xd4, 0xab, 0x54, 0xf4, 0xa8, 0xe4, 0x69, 0x2d, 0x8e, 0x4d, 0xd7, 0xac, 0xb0, 0x5b, 0xfe, 0xe3, 0x26, 0x07, 0xc3, 0xf8, 0x1b, 0x43, 0xa8, 0x1d, 0x64, 0xa5, 0x25, 0x88, 0xbb, 0x77,
/* (2^ 95)P */ 0x92, 0xcd, 0x6e, 0xa0, 0x79, 0x04, 0x18, 0xf4, 0x11, 0x58, 0x48, 0xb5, 0x3c, 0x7b, 0xd1, 0xcc, 0xd3, 0x14, 0x2c, 0xa0, 0xdd, 0x04, 0x44, 0x11, 0xb3, 0x6d, 0x2f, 0x0d, 0xf5, 0x2a, 0x75, 0x5d, 0x1d, 0xda, 0x86, 0x8d, 0x7d, 0x6b, 0x32, 0x68, 0xb6, 0x6c, 0x64, 0x9e, 0xde, 0x80, 0x88, 0xce, 0x08, 0xbf, 0x0b, 0xe5, 0x8e, 0x4f, 0x1d, 0xfb,
/* (2^ 96)P */ 0xaf, 0xe8, 0x85, 0xbf, 0x7f, 0x37, 0x8d, 0x66, 0x7c, 0xd5, 0xd3, 0x96, 0xa5, 0x81, 0x67, 0x95, 0xff, 0x48, 0xde, 0xde, 0xd7, 0x7a, 0x46, 0x34, 0xb1, 0x13, 0x70, 0x29, 0xed, 0x87, 0x90, 0xb0, 0x40, 0x2c, 0xa6, 0x43, 0x6e, 0xb6, 0xbc, 0x48, 0x8a, 0xc1, 0xae, 0xb8, 0xd4, 0xe2, 0xc0, 0x32, 0xb2, 0xa6, 0x2a, 0x8f, 0xb5, 0x16, 0x9e, 0xc3,
/* (2^ 97)P */ 0xff, 0x4d, 0xd2, 0xd6, 0x74, 0xef, 0x2c, 0x96, 0xc1, 0x11, 0xa8, 0xb8, 0xfe, 0x94, 0x87, 0x3e, 0xa0, 0xfb, 0x57, 0xa3, 0xfc, 0x7a, 0x7e, 0x6a, 0x59, 0x6c, 0x54, 0xbb, 0xbb, 0xa2, 0x25, 0x38, 0x1b, 0xdf, 0x5d, 0x7b, 0x94, 0x14, 0xde, 0x07, 0x6e, 0xd3, 0xab, 0x02, 0x26, 0x74, 0x16, 0x12, 0xdf, 0x2e, 0x2a, 0xa7, 0xb0, 0xe8, 0x29, 0xc0,
/* (2^ 98)P */ 0x6a, 0x38, 0x0b, 0xd3, 0xba, 0x45, 0x23, 0xe0, 0x04, 0x3b, 0x83, 0x39, 0xc5, 0x11, 0xe6, 0xcf, 0x39, 0x0a, 0xb3, 0xb0, 0x3b, 0x27, 0x29, 0x63, 0x1c, 0xf3, 0x00, 0xe6, 0xd2, 0x55, 0x21, 0x1f, 0x84, 0x97, 0x9f, 0x01, 0x49, 0x43, 0x30, 0x5f, 0xe0, 0x1d, 0x24, 0xc4, 0x4e, 0xa0, 0x2b, 0x0b, 0x12, 0x55, 0xc3, 0x27, 0xae, 0x08, 0x83, 0x7c,
/* (2^ 99)P */ 0x5d, 0x1a, 0xb7, 0xa9, 0xf5, 0xfd, 0xec, 0xad, 0xb7, 0x87, 0x02, 0x5f, 0x0d, 0x30, 0x4d, 0xe2, 0x65, 0x87, 0xa4, 0x41, 0x45, 0x1d, 0x67, 0xe0, 0x30, 0x5c, 0x13, 0x87, 0xf6, 0x2e, 0x08, 0xc1, 0xc7, 0x12, 0x45, 0xc8, 0x9b, 0xad, 0xb8, 0xd5, 0x57, 0xbb, 0x5c, 0x48, 0x3a, 0xe1, 0x91, 0x5e, 0xf6, 0x4d, 0x8a, 0x63, 0x75, 0x69, 0x0c, 0x01,
/* (2^100)P */ 0x8f, 0x53, 0x2d, 0xa0, 0x71, 0x3d, 0xfc, 0x45, 0x10, 0x96, 0xcf, 0x56, 0xf9, 0xbb, 0x40, 0x3c, 0x86, 0x52, 0x76, 0xbe, 0x84, 0xf9, 0xa6, 0x9d, 0x3d, 0x27, 0xbe, 0xb4, 0x00, 0x49, 0x94, 0xf5, 0x5d, 0xe1, 0x62, 0x85, 0x66, 0xe5, 0xb8, 0x20, 0x2c, 0x09, 0x7d, 0x9d, 0x3d, 0x6e, 0x74, 0x39, 0xab, 0xad, 0xa0, 0x90, 0x97, 0x5f, 0xbb, 0xa7,
/* (2^101)P */ 0xdb, 0x2d, 0x99, 0x08, 0x16, 0x46, 0x83, 0x7a, 0xa8, 0xea, 0x3d, 0x28, 0x5b, 0x49, 0xfc, 0xb9, 0x6d, 0x00, 0x9e, 0x54, 0x4f, 0x47, 0x64, 0x9b, 0x58, 0x4d, 0x07, 0x0c, 0x6f, 0x29, 0x56, 0x0b, 0x00, 0x14, 0x85, 0x96, 0x41, 0x04, 0xb9, 0x5c, 0xa4, 0xf6, 0x16, 0x73, 0x6a, 0xc7, 0x62, 0x0c, 0x65, 0x2f, 0x93, 0xbf, 0xf7, 0xb9, 0xb7, 0xf1,
/* (2^102)P */ 0xeb, 0x6d, 0xb3, 0x46, 0x32, 0xd2, 0xcb, 0x08, 0x94, 0x14, 0xbf, 0x3f, 0xc5, 0xcb, 0x5f, 0x9f, 0x8a, 0x89, 0x0c, 0x1b, 0x45, 0xad, 0x4c, 0x50, 0xb4, 0xe1, 0xa0, 0x6b, 0x11, 0x92, 0xaf, 0x1f, 0x00, 0xcc, 0xe5, 0x13, 0x7e, 0xe4, 0x2e, 0xa0, 0x57, 0xf3, 0xa7, 0x84, 0x79, 0x7a, 0xc2, 0xb7, 0xb7, 0xfc, 0x5d, 0xa5, 0xa9, 0x64, 0xcc, 0xd8,
/* (2^103)P */ 0xa9, 0xc4, 0x12, 0x8b, 0x34, 0x78, 0x3e, 0x38, 0xfd, 0x3f, 0x87, 0xfa, 0x88, 0x94, 0xd5, 0xd9, 0x7f, 0xeb, 0x58, 0xff, 0xb9, 0x45, 0xdb, 0xa1, 0xed, 0x22, 0x28, 0x1d, 0x00, 0x6d, 0x79, 0x85, 0x7a, 0x75, 0x5d, 0xf0, 0xb1, 0x9e, 0x47, 0x28, 0x8c, 0x62, 0xdf, 0xfb, 0x4c, 0x7b, 0xc5, 0x1a, 0x42, 0x95, 0xef, 0x9a, 0xb7, 0x27, 0x7e, 0xda,
/* (2^104)P */ 0xca, 0xd5, 0xc0, 0x17, 0xa1, 0x66, 0x79, 0x9c, 0x2a, 0xb7, 0x0a, 0xfe, 0x62, 0xe4, 0x26, 0x78, 0x90, 0xa7, 0xcb, 0xb0, 0x4f, 0x6d, 0xf9, 0x8f, 0xf7, 0x7d, 0xac, 0xb8, 0x78, 0x1f, 0x41, 0xea, 0x97, 0x1e, 0x62, 0x97, 0x43, 0x80, 0x58, 0x80, 0xb6, 0x69, 0x7d, 0xee, 0x16, 0xd2, 0xa1, 0x81, 0xd7, 0xb1, 0x27, 0x03, 0x48, 0xda, 0xab, 0xec,
/* (2^105)P */ 0x5b, 0xed, 0x40, 0x8e, 0x8c, 0xc1, 0x66, 0x90, 0x7f, 0x0c, 0xb2, 0xfc, 0xbd, 0x16, 0xac, 0x7d, 0x4c, 0x6a, 0xf9, 0xae, 0xe7, 0x4e, 0x11, 0x12, 0xe9, 0xbe, 0x17, 0x09, 0xc6, 0xc1, 0x5e, 0xb5, 0x7b, 0x50, 0x5c, 0x27, 0xfb, 0x80, 0xab, 0x01, 0xfa, 0x5b, 0x9b, 0x75, 0x16, 0x6e, 0xb2, 0x5c, 0x8c, 0x2f, 0xa5, 0x6a, 0x1a, 0x68, 0xa6, 0x90,
/* (2^106)P */ 0x75, 0xfe, 0xb6, 0x96, 0x96, 0x87, 0x4c, 0x12, 0xa9, 0xd1, 0xd8, 0x03, 0xa3, 0xc1, 0x15, 0x96, 0xe8, 0xa0, 0x75, 0x82, 0xa0, 0x6d, 0xea, 0x54, 0xdc, 0x5f, 0x0d, 0x7e, 0xf6, 0x70, 0xb5, 0xdc, 0x7a, 0xf6, 0xc4, 0xd4, 0x21, 0x49, 0xf5, 0xd4, 0x14, 0x6d, 0x48, 0x1d, 0x7c, 0x99, 0x42, 0xdf, 0x78, 0x6b, 0x9d, 0xb9, 0x30, 0x3c, 0xd0, 0x29,
/* (2^107)P */ 0x85, 0xd6, 0xd8, 0xf3, 0x91, 0x74, 0xdd, 0xbd, 0x72, 0x96, 0x10, 0xe4, 0x76, 0x02, 0x5a, 0x72, 0x67, 0xd3, 0x17, 0x72, 0x14, 0x9a, 0x20, 0x5b, 0x0f, 0x8d, 0xed, 0x6d, 0x4e, 0xe3, 0xd9, 0x82, 0xc2, 0x99, 0xee, 0x39, 0x61, 0x69, 0x8a, 0x24, 0x01, 0x92, 0x15, 0xe7, 0xfc, 0xf9, 0x4d, 0xac, 0xf1, 0x30, 0x49, 0x01, 0x0b, 0x6e, 0x0f, 0x20,
/* (2^108)P */ 0xd8, 0x25, 0x94, 0x5e, 0x43, 0x29, 0xf5, 0xcc, 0xe8, 0xe3, 0x55, 0x41, 0x3c, 0x9f, 0x58, 0x5b, 0x00, 0xeb, 0xc5, 0xdf, 0xcf, 0xfb, 0xfd, 0x6e, 0x92, 0xec, 0x99, 0x30, 0xd6, 0x05, 0xdd, 0x80, 0x7a, 0x5d, 0x6d, 0x16, 0x85, 0xd8, 0x9d, 0x43, 0x65, 0xd8, 0x2c, 0x33, 0x2f, 0x5c, 0x41, 0xea, 0xb7, 0x95, 0x77, 0xf2, 0x9e, 0x59, 0x09, 0xe8,
/* (2^109)P */ 0x00, 0xa0, 0x03, 0x80, 0xcd, 0x60, 0xe5, 0x17, 0xd4, 0x15, 0x99, 0xdd, 0x4f, 0xbf, 0x66, 0xb8, 0xc0, 0xf5, 0xf9, 0xfc, 0x6d, 0x42, 0x18, 0x34, 0x1c, 0x7d, 0x5b, 0xb5, 0x09, 0xd0, 0x99, 0x57, 0x81, 0x0b, 0x62, 0xb3, 0xa2, 0xf9, 0x0b, 0xae, 0x95, 0xb8, 0xc2, 0x3b, 0x0d, 0x5b, 0x00, 0xf1, 0xed, 0xbc, 0x05, 0x9d, 0x61, 0xbc, 0x73, 0x9d,
/* (2^110)P */ 0xd4, 0xdb, 0x29, 0xe5, 0x85, 0xe9, 0xc6, 0x89, 0x2a, 0xa8, 0x54, 0xab, 0xb3, 0x7f, 0x88, 0xc0, 0x4d, 0xe0, 0xd1, 0x74, 0x6e, 0xa3, 0xa7, 0x39, 0xd5, 0xcc, 0xa1, 0x8a, 0xcb, 0x5b, 0x34, 0xad, 0x92, 0xb4, 0xd8, 0xd5, 0x17, 0xf6, 0x77, 0x18, 0x9e, 0xaf, 0x45, 0x3b, 0x03, 0xe2, 0xf8, 0x52, 0x60, 0xdc, 0x15, 0x20, 0x9e, 0xdf, 0xd8, 0x5d,
/* (2^111)P */ 0x02, 0xc1, 0xac, 0x1a, 0x15, 0x8e, 0x6c, 0xf5, 0x1e, 0x1e, 0xba, 0x7e, 0xc2, 0xda, 0x7d, 0x02, 0xda, 0x43, 0xae, 0x04, 0x70, 0x28, 0x54, 0x78, 0x94, 0xf5, 0x4f, 0x07, 0x84, 0x8f, 0xed, 0xaa, 0xc0, 0xb8, 0xcd, 0x7f, 0x7e, 0x33, 0xa3, 0xbe, 0x21, 0x29, 0xc8, 0x56, 0x34, 0xc0, 0x76, 0x87, 0x8f, 0xc7, 0x73, 0x58, 0x90, 0x16, 0xfc, 0xd6,
/* (2^112)P */ 0xb8, 0x3f, 0xe1, 0xdf, 0x3a, 0x91, 0x25, 0x0c, 0xf6, 0x47, 0xa8, 0x89, 0xc4, 0xc6, 0x61, 0xec, 0x86, 0x2c, 0xfd, 0xbe, 0xa4, 0x6f, 0xc2, 0xd4, 0x46, 0x19, 0x70, 0x5d, 0x09, 0x02, 0x86, 0xd3, 0x4b, 0xe9, 0x16, 0x7b, 0xf0, 0x0d, 0x6c, 0xff, 0x91, 0x05, 0xbf, 0x55, 0xb4, 0x00, 0x8d, 0xe5, 0x6d, 0x68, 0x20, 0x90, 0x12, 0xb5, 0x5c, 0x32,
/* (2^113)P */ 0x80, 0x45, 0xc8, 0x51, 0x87, 0xba, 0x1c, 0x5c, 0xcf, 0x5f, 0x4b, 0x3c, 0x9e, 0x3b, 0x36, 0xd2, 0x26, 0xa2, 0x7f, 0xab, 0xb7, 0xbf, 0xda, 0x68, 0x23, 0x8f, 0xc3, 0xa0, 0xfd, 0xad, 0xf1, 0x56, 0x3b, 0xd0, 0x75, 0x2b, 0x44, 0x61, 0xd8, 0xf4, 0xf1, 0x05, 0x49, 0x53, 0x07, 0xee, 0x47, 0xef, 0xc0, 0x7c, 0x9d, 0xe4, 0x15, 0x88, 0xc5, 0x47,
/* (2^114)P */ 0x2d, 0xb5, 0x09, 0x80, 0xb9, 0xd3, 0xd8, 0xfe, 0x4c, 0xd2, 0xa6, 0x6e, 0xd3, 0x75, 0xcf, 0xb0, 0x99, 0xcb, 0x50, 0x8d, 0xe9, 0x67, 0x9b, 0x20, 0xe8, 0x57, 0xd8, 0x14, 0x85, 0x73, 0x6a, 0x74, 0xe0, 0x99, 0xf0, 0x6b, 0x6e, 0x59, 0x30, 0x31, 0x33, 0x96, 0x5f, 0xa1, 0x0c, 0x1b, 0xf4, 0xca, 0x09, 0xe1, 0x9b, 0xb5, 0xcf, 0x6d, 0x0b, 0xeb,
/* (2^115)P */ 0x1a, 0xde, 0x50, 0xa9, 0xac, 0x3e, 0x10, 0x43, 0x4f, 0x82, 0x4f, 0xc0, 0xfe, 0x3f, 0x33, 0xd2, 0x64, 0x86, 0x50, 0xa9, 0x51, 0x76, 0x5e, 0x50, 0x97, 0x6c, 0x73, 0x8d, 0x77, 0xa3, 0x75, 0x03, 0xbc, 0xc9, 0xfb, 0x50, 0xd9, 0x6d, 0x16, 0xad, 0x5d, 0x32, 0x3d, 0xac, 0x44, 0xdf, 0x51, 0xf7, 0x19, 0xd4, 0x0b, 0x57, 0x78, 0x0b, 0x81, 0x4e,
/* (2^116)P */ 0x32, 0x24, 0xf1, 0x6c, 0x55, 0x62, 0x1d, 0xb3, 0x1f, 0xda, 0xfa, 0x6a, 0x8f, 0x98, 0x01, 0x16, 0xde, 0x44, 0x50, 0x0d, 0x2e, 0x6c, 0x0b, 0xa2, 0xd3, 0x74, 0x0e, 0xa9, 0xbf, 0x8d, 0xa9, 0xc8, 0xc8, 0x2f, 0x62, 0xc1, 0x35, 0x5e, 0xfd, 0x3a, 0xb3, 0x83, 0x2d, 0xee, 0x4e, 0xfd, 0x5c, 0x5e, 0xad, 0x85, 0xa5, 0x10, 0xb5, 0x4f, 0x34, 0xa7,
/* (2^117)P */ 0xd1, 0x58, 0x6f, 0xe6, 0x54, 0x2c, 0xc2, 0xcd, 0xcf, 0x83, 0xdc, 0x88, 0x0c, 0xb9, 0xb4, 0x62, 0x18, 0x89, 0x65, 0x28, 0xe9, 0x72, 0x4b, 0x65, 0xcf, 0xd6, 0x90, 0x88, 0xd7, 0x76, 0x17, 0x4f, 0x74, 0x64, 0x1e, 0xcb, 0xd3, 0xf5, 0x4b, 0xaa, 0x2e, 0x4d, 0x2d, 0x7c, 0x13, 0x1f, 0xfd, 0xd9, 0x60, 0x83, 0x7e, 0xda, 0x64, 0x1c, 0xdc, 0x9f,
/* (2^118)P */ 0xad, 0xef, 0xac, 0x1b, 0xc1, 0x30, 0x5a, 0x15, 0xc9, 0x1f, 0xac, 0xf1, 0xca, 0x44, 0x95, 0x95, 0xea, 0xf2, 0x22, 0xe7, 0x8d, 0x25, 0xf0, 0xff, 0xd8, 0x71, 0xf7, 0xf8, 0x8f, 0x8f, 0xcd, 0xf4, 0x1e, 0xfe, 0x6c, 0x68, 0x04, 0xb8, 0x78, 0xa1, 0x5f, 0xa6, 0x5d, 0x5e, 0xf9, 0x8d, 0xea, 0x80, 0xcb, 0xf3, 0x17, 0xa6, 0x03, 0xc9, 0x38, 0xd5,
/* (2^119)P */ 0x79, 0x14, 0x31, 0xc3, 0x38, 0xe5, 0xaa, 0xbf, 0x17, 0xa3, 0x04, 0x4e, 0x80, 0x59, 0x9c, 0x9f, 0x19, 0x39, 0xe4, 0x2d, 0x23, 0x54, 0x4a, 0x7f, 0x3e, 0xf3, 0xd9, 0xc7, 0xba, 0x6c, 0x8f, 0x6b, 0xfa, 0x34, 0xb5, 0x23, 0x17, 0x1d, 0xff, 0x1d, 0xea, 0x1f, 0xd7, 0xba, 0x61, 0xb2, 0xe0, 0x38, 0x6a, 0xe9, 0xcf, 0x48, 0x5d, 0x6a, 0x10, 0x9c,
/* (2^120)P */ 0xc8, 0xbb, 0x13, 0x1c, 0x3f, 0x3c, 0x34, 0xfd, 0xac, 0x37, 0x52, 0x44, 0x25, 0xa8, 0xde, 0x1d, 0x63, 0xf4, 0x81, 0x9a, 0xbe, 0x0b, 0x74, 0x2e, 0xc8, 0x51, 0x16, 0xd3, 0xac, 0x4a, 0xaf, 0xe2, 0x5f, 0x3a, 0x89, 0x32, 0xd1, 0x9b, 0x7c, 0x90, 0x0d, 0xac, 0xdc, 0x8b, 0x73, 0x45, 0x45, 0x97, 0xb1, 0x90, 0x2c, 0x1b, 0x31, 0xca, 0xb1, 0x94,
/* (2^121)P */ 0x07, 0x28, 0xdd, 0x10, 0x14, 0xa5, 0x95, 0x7e, 0xf3, 0xe4, 0xd4, 0x14, 0xb4, 0x7e, 0x76, 0xdb, 0x42, 0xd6, 0x94, 0x3e, 0xeb, 0x44, 0x64, 0x88, 0x0d, 0xec, 0xc1, 0x21, 0xf0, 0x79, 0xe0, 0x83, 0x67, 0x55, 0x53, 0xc2, 0xf6, 0xc5, 0xc5, 0x89, 0x39, 0xe8, 0x42, 0xd0, 0x17, 0xbd, 0xff, 0x35, 0x59, 0x0e, 0xc3, 0x06, 0x86, 0xd4, 0x64, 0xcf,
/* (2^122)P */ 0x91, 0xa8, 0xdb, 0x57, 0x9b, 0xe2, 0x96, 0x31, 0x10, 0x6e, 0xd7, 0x9a, 0x97, 0xb3, 0xab, 0xb5, 0x15, 0x66, 0xbe, 0xcc, 0x6d, 0x9a, 0xac, 0x06, 0xb3, 0x0d, 0xaa, 0x4b, 0x9c, 0x96, 0x79, 0x6c, 0x34, 0xee, 0x9e, 0x53, 0x4d, 0x6e, 0xbd, 0x88, 0x02, 0xbf, 0x50, 0x54, 0x12, 0x5d, 0x01, 0x02, 0x46, 0xc6, 0x74, 0x02, 0x8c, 0x24, 0xae, 0xb1,
/* (2^123)P */ 0xf5, 0x22, 0xea, 0xac, 0x7d, 0x9c, 0x33, 0x8a, 0xa5, 0x36, 0x79, 0x6a, 0x4f, 0xa4, 0xdc, 0xa5, 0x73, 0x64, 0xc4, 0x6f, 0x43, 0x02, 0x3b, 0x94, 0x66, 0xd2, 0x4b, 0x4f, 0xf6, 0x45, 0x33, 0x5d, 0x10, 0x33, 0x18, 0x1e, 0xa3, 0xfc, 0xf7, 0xd2, 0xb8, 0xc8, 0xa7, 0xe0, 0x76, 0x8a, 0xcd, 0xff, 0x4f, 0x99, 0x34, 0x47, 0x84, 0x91, 0x96, 0x9f,
/* (2^124)P */ 0x8a, 0x48, 0x3b, 0x48, 0x4a, 0xbc, 0xac, 0xe2, 0x80, 0xd6, 0xd2, 0x35, 0xde, 0xd0, 0x56, 0x42, 0x33, 0xb3, 0x56, 0x5a, 0xcd, 0xb8, 0x3d, 0xb5, 0x25, 0xc1, 0xed, 0xff, 0x87, 0x0b, 0x79, 0xff, 0xf2, 0x62, 0xe1, 0x76, 0xc6, 0xa2, 0x0f, 0xa8, 0x9b, 0x0d, 0xcc, 0x3f, 0x3d, 0x35, 0x27, 0x8d, 0x0b, 0x74, 0xb0, 0xc3, 0x78, 0x8c, 0xcc, 0xc8,
/* (2^125)P */ 0xfc, 0x9a, 0x0c, 0xa8, 0x49, 0x42, 0xb8, 0xdf, 0xcf, 0xb3, 0x19, 0xa6, 0x64, 0x57, 0xfe, 0xe8, 0xf8, 0xa6, 0x4b, 0x86, 0xa1, 0xd5, 0x83, 0x7f, 0x14, 0x99, 0x18, 0x0c, 0x7d, 0x5b, 0xf7, 0x3d, 0xf9, 0x4b, 0x79, 0xb1, 0x86, 0x30, 0xb4, 0x5e, 0x6a, 0xe8, 0x9d, 0xfa, 0x8a, 0x41, 0xc4, 0x30, 0xfc, 0x56, 0x74, 0x14, 0x42, 0xc8, 0x96, 0x0e,
/* (2^126)P */ 0xdf, 0x66, 0xec, 0xbc, 0x44, 0xdb, 0x19, 0xce, 0xd4, 0xb5, 0x49, 0x40, 0x07, 0x49, 0xe0, 0x3a, 0x61, 0x10, 0xfb, 0x7d, 0xba, 0xb1, 0xe0, 0x28, 0x5b, 0x99, 0x59, 0x96, 0xa2, 0xee, 0xe0, 0x23, 0x37, 0x39, 0x1f, 0xe6, 0x57, 0x9f, 0xf8, 0xf8, 0xdc, 0x74, 0xf6, 0x8f, 0x4f, 0x5e, 0x51, 0xa4, 0x12, 0xac, 0xbe, 0xe4, 0xf3, 0xd1, 0xf0, 0x24,
/* (2^127)P */ 0x1e, 0x3e, 0x9a, 0x5f, 0xdf, 0x9f, 0xd6, 0x4e, 0x8a, 0x28, 0xc3, 0xcd, 0x96, 0x9d, 0x57, 0xc7, 0x61, 0x81, 0x90, 0xff, 0xae, 0xb1, 0x4f, 0xc2, 0x96, 0x8b, 0x1a, 0x18, 0xf4, 0x50, 0xcb, 0x31, 0xe1, 0x57, 0xf4, 0x90, 0xa8, 0xea, 0xac, 0xe7, 0x61, 0x98, 0xb6, 0x15, 0xc1, 0x7b, 0x29, 0xa4, 0xc3, 0x18, 0xef, 0xb9, 0xd8, 0xdf, 0xf6, 0xac,
/* (2^128)P */ 0xca, 0xa8, 0x6c, 0xf1, 0xb4, 0xca, 0xfe, 0x31, 0xee, 0x48, 0x38, 0x8b, 0x0e, 0xbb, 0x7a, 0x30, 0xaa, 0xf9, 0xee, 0x27, 0x53, 0x24, 0xdc, 0x2e, 0x15, 0xa6, 0x48, 0x8f, 0xa0, 0x7e, 0xf1, 0xdc, 0x93, 0x87, 0x39, 0xeb, 0x7f, 0x38, 0x92, 0x92, 0x4c, 0x29, 0xe9, 0x57, 0xd8, 0x59, 0xfc, 0xe9, 0x9c, 0x44, 0xc0, 0x65, 0xcf, 0xac, 0x4b, 0xdc,
/* (2^129)P */ 0xa3, 0xd0, 0x37, 0x8f, 0x86, 0x2f, 0xc6, 0x47, 0x55, 0x46, 0x65, 0x26, 0x4b, 0x91, 0xe2, 0x18, 0x5c, 0x4f, 0x23, 0xc1, 0x37, 0x29, 0xb9, 0xc1, 0x27, 0xc5, 0x3c, 0xbf, 0x7e, 0x23, 0xdb, 0x73, 0x99, 0xbd, 0x1b, 0xb2, 0x31, 0x68, 0x3a, 0xad, 0xb7, 0xb0, 0x10, 0xc5, 0xe5, 0x11, 0x51, 0xba, 0xa7, 0x60, 0x66, 0x54, 0xf0, 0x08, 0xd7, 0x69,
/* (2^130)P */ 0x89, 0x41, 0x79, 0xcc, 0xeb, 0x0a, 0xf5, 0x4b, 0xa3, 0x4c, 0xce, 0x52, 0xb0, 0xa7, 0xe4, 0x41, 0x75, 0x7d, 0x04, 0xbb, 0x09, 0x4c, 0x50, 0x9f, 0xdf, 0xea, 0x74, 0x61, 0x02, 0xad, 0xb4, 0x9d, 0xb7, 0x05, 0xb9, 0xea, 0xeb, 0x91, 0x35, 0xe7, 0x49, 0xea, 0xd3, 0x4f, 0x3c, 0x60, 0x21, 0x7a, 0xde, 0xc7, 0xe2, 0x5a, 0xee, 0x8e, 0x93, 0xc7,
/* (2^131)P */ 0x00, 0xe8, 0xed, 0xd0, 0xb3, 0x0d, 0xaf, 0xb2, 0xde, 0x2c, 0xf6, 0x00, 0xe2, 0xea, 0x6d, 0xf8, 0x0e, 0xd9, 0x67, 0x59, 0xa9, 0x50, 0xbb, 0x17, 0x8f, 0xff, 0xb1, 0x9f, 0x17, 0xb6, 0xf2, 0xb5, 0xba, 0x80, 0xf7, 0x0f, 0xba, 0xd5, 0x09, 0x43, 0xaa, 0x4e, 0x3a, 0x67, 0x6a, 0x89, 0x9b, 0x18, 0x65, 0x35, 0xf8, 0x3a, 0x49, 0x91, 0x30, 0x51,
/* (2^132)P */ 0x8d, 0x25, 0xe9, 0x0e, 0x7d, 0x50, 0x76, 0xe4, 0x58, 0x7e, 0xb9, 0x33, 0xe6, 0x65, 0x90, 0xc2, 0x50, 0x9d, 0x50, 0x2e, 0x11, 0xad, 0xd5, 0x43, 0x52, 0x32, 0x41, 0x4f, 0x7b, 0xb6, 0xa0, 0xec, 0x81, 0x75, 0x36, 0x7c, 0x77, 0x85, 0x59, 0x70, 0xe4, 0xf9, 0xef, 0x66, 0x8d, 0x35, 0xc8, 0x2a, 0x6e, 0x5b, 0xc6, 0x0d, 0x0b, 0x29, 0x60, 0x68,
/* (2^133)P */ 0xf8, 0xce, 0xb0, 0x3a, 0x56, 0x7d, 0x51, 0x9a, 0x25, 0x73, 0xea, 0xdd, 0xe4, 0xe0, 0x0e, 0xf0, 0x07, 0xc0, 0x31, 0x00, 0x73, 0x35, 0xd0, 0x39, 0xc4, 0x9b, 0xb7, 0x95, 0xe0, 0x62, 0x70, 0x36, 0x0b, 0xcb, 0xa0, 0x42, 0xde, 0x51, 0xcf, 0x41, 0xe0, 0xb8, 0xb4, 0xc0, 0xe5, 0x46, 0x99, 0x9f, 0x02, 0x7f, 0x14, 0x8c, 0xc1, 0x4e, 0xef, 0xe8,
/* (2^134)P */ 0x10, 0x01, 0x57, 0x0a, 0xbe, 0x8b, 0x18, 0xc8, 0xca, 0x00, 0x28, 0x77, 0x4a, 0x9a, 0xc7, 0x55, 0x2a, 0xcc, 0x0c, 0x7b, 0xb9, 0xe9, 0xc8, 0x97, 0x7c, 0x02, 0xe3, 0x09, 0x2f, 0x62, 0x30, 0xb8, 0x40, 0x09, 0x65, 0xe9, 0x55, 0x63, 0xb5, 0x07, 0xca, 0x9f, 0x00, 0xdf, 0x9d, 0x5c, 0xc7, 0xee, 0x57, 0xa5, 0x90, 0x15, 0x1e, 0x22, 0xa0, 0x12,
/* (2^135)P */ 0x71, 0x2d, 0xc9, 0xef, 0x27, 0xb9, 0xd8, 0x12, 0x43, 0x6b, 0xa8, 0xce, 0x3b, 0x6d, 0x6e, 0x91, 0x43, 0x23, 0xbc, 0x32, 0xb3, 0xbf, 0xe1, 0xc7, 0x39, 0xcf, 0x7c, 0x42, 0x4c, 0xb1, 0x30, 0xe2, 0xdd, 0x69, 0x06, 0xe5, 0xea, 0xf0, 0x2a, 0x16, 0x50, 0x71, 0xca, 0x92, 0xdf, 0xc1, 0xcc, 0xec, 0xe6, 0x54, 0x07, 0xf3, 0x18, 0x8d, 0xd8, 0x29,
/* (2^136)P */ 0x98, 0x51, 0x48, 0x8f, 0xfa, 0x2e, 0x5e, 0x67, 0xb0, 0xc6, 0x17, 0x12, 0xb6, 0x7d, 0xc9, 0xad, 0x81, 0x11, 0xad, 0x0c, 0x1c, 0x2d, 0x45, 0xdf, 0xac, 0x66, 0xbd, 0x08, 0x6f, 0x7c, 0xc7, 0x06, 0x6e, 0x19, 0x08, 0x39, 0x64, 0xd7, 0xe4, 0xd1, 0x11, 0x5f, 0x1c, 0xf4, 0x67, 0xc3, 0x88, 0x6a, 0xe6, 0x07, 0xa3, 0x83, 0xd7, 0xfd, 0x2a, 0xf9,
/* (2^137)P */ 0x87, 0xed, 0xeb, 0xd9, 0xdf, 0xff, 0x43, 0x8b, 0xaa, 0x20, 0x58, 0xb0, 0xb4, 0x6b, 0x14, 0xb8, 0x02, 0xc5, 0x40, 0x20, 0x22, 0xbb, 0xf7, 0xb4, 0xf3, 0x05, 0x1e, 0x4d, 0x94, 0xff, 0xe3, 0xc5, 0x22, 0x82, 0xfe, 0xaf, 0x90, 0x42, 0x98, 0x6b, 0x76, 0x8b, 0x3e, 0x89, 0x3f, 0x42, 0x2a, 0xa7, 0x26, 0x00, 0xda, 0x5c, 0xa2, 0x2b, 0xec, 0xdd,
/* (2^138)P */ 0x5c, 0x21, 0x16, 0x0d, 0x46, 0xb8, 0xd0, 0xa7, 0x88, 0xe7, 0x25, 0xcb, 0x3e, 0x50, 0x73, 0x61, 0xe7, 0xaf, 0x5a, 0x3f, 0x47, 0x8b, 0x3d, 0x97, 0x79, 0x2c, 0xe6, 0x6d, 0x95, 0x74, 0x65, 0x70, 0x36, 0xfd, 0xd1, 0x9e, 0x13, 0x18, 0x63, 0xb1, 0x2d, 0x0b, 0xb5, 0x36, 0x3e, 0xe7, 0x35, 0x42, 0x3b, 0xe6, 0x1f, 0x4d, 0x9d, 0x59, 0xa2, 0x43,
/* (2^139)P */ 0x8c, 0x0c, 0x7c, 0x24, 0x9e, 0xe0, 0xf8, 0x05, 0x1c, 0x9e, 0x1f, 0x31, 0xc0, 0x70, 0xb3, 0xfb, 0x4e, 0xf8, 0x0a, 0x57, 0xb7, 0x49, 0xb5, 0x73, 0xa1, 0x5f, 0x9b, 0x6a, 0x07, 0x6c, 0x87, 0x71, 0x87, 0xd4, 0xbe, 0x98, 0x1e, 0x98, 0xee, 0x52, 0xc1, 0x7b, 0x95, 0x0f, 0x28, 0x32, 0x36, 0x28, 0xd0, 0x3a, 0x0f, 0x7d, 0x2a, 0xa9, 0x62, 0xb9,
/* (2^140)P */ 0x97, 0xe6, 0x18, 0x77, 0xf9, 0x34, 0xac, 0xbc, 0xe0, 0x62, 0x9f, 0x42, 0xde, 0xbd, 0x2f, 0xf7, 0x1f, 0xb7, 0x14, 0x52, 0x8a, 0x79, 0xb2, 0x3f, 0xd2, 0x95, 0x71, 0x01, 0xe8, 0xaf, 0x8c, 0xa4, 0xa4, 0xa7, 0x27, 0xf3, 0x5c, 0xdf, 0x3e, 0x57, 0x7a, 0xf1, 0x76, 0x49, 0xe6, 0x42, 0x3f, 0x8f, 0x1e, 0x63, 0x4a, 0x65, 0xb5, 0x41, 0xf5, 0x02,
/* (2^141)P */ 0x72, 0x85, 0xc5, 0x0b, 0xe1, 0x47, 0x64, 0x02, 0xc5, 0x4d, 0x81, 0x69, 0xb2, 0xcf, 0x0f, 0x6c, 0xd4, 0x6d, 0xd0, 0xc7, 0xb4, 0x1c, 0xd0, 0x32, 0x59, 0x89, 0xe2, 0xe0, 0x96, 0x8b, 0x12, 0x98, 0xbf, 0x63, 0x7a, 0x4c, 0x76, 0x7e, 0x58, 0x17, 0x8f, 0x5b, 0x0a, 0x59, 0x65, 0x75, 0xbc, 0x61, 0x1f, 0xbe, 0xc5, 0x6e, 0x0a, 0x57, 0x52, 0x70,
/* (2^142)P */ 0x92, 0x1c, 0x77, 0xbb, 0x62, 0x02, 0x6c, 0x25, 0x9c, 0x66, 0x07, 0x83, 0xab, 0xcc, 0x80, 0x5d, 0xd2, 0x76, 0x0c, 0xa4, 0xc5, 0xb4, 0x8a, 0x68, 0x23, 0x31, 0x32, 0x29, 0x8a, 0x47, 0x92, 0x12, 0x80, 0xb3, 0xfa, 0x18, 0xe4, 0x8d, 0xc0, 0x4d, 0xfe, 0x97, 0x5f, 0x72, 0x41, 0xb5, 0x5c, 0x7a, 0xbd, 0xf0, 0xcf, 0x5e, 0x97, 0xaa, 0x64, 0x32,
/* (2^143)P */ 0x35, 0x3f, 0x75, 0xc1, 0x7a, 0x75, 0x7e, 0xa9, 0xc6, 0x0b, 0x4e, 0x32, 0x62, 0xec, 0xe3, 0x5c, 0xfb, 0x01, 0x43, 0xb6, 0xd4, 0x5b, 0x75, 0xd2, 0xee, 0x7f, 0x5d, 0x23, 0x2b, 0xb3, 0x54, 0x34, 0x4c, 0xd3, 0xb4, 0x32, 0x84, 0x81, 0xb5, 0x09, 0x76, 0x19, 0xda, 0x58, 0xda, 0x7c, 0xdb, 0x2e, 0xdd, 0x4c, 0x8e, 0xdd, 0x5d, 0x89, 0x10, 0x10,
/* (2^144)P */ 0x57, 0x25, 0x6a, 0x08, 0x37, 0x92, 0xa8, 0xdf, 0x24, 0xef, 0x8f, 0x33, 0x34, 0x52, 0xa4, 0x4c, 0xf0, 0x77, 0x9f, 0x69, 0x77, 0xd5, 0x8f, 0xd2, 0x9a, 0xb3, 0xb6, 0x1d, 0x2d, 0xa6, 0xf7, 0x1f, 0xda, 0xd7, 0xcb, 0x75, 0x11, 0xc3, 0x6b, 0xc0, 0x38, 0xb1, 0xd5, 0x2d, 0x96, 0x84, 0x16, 0xfa, 0x26, 0xb9, 0xcc, 0x3f, 0x16, 0x47, 0x23, 0x74,
/* (2^145)P */ 0x9b, 0x61, 0x2a, 0x1c, 0xdd, 0x39, 0xa5, 0xfa, 0x1c, 0x7d, 0x63, 0x50, 0xca, 0xe6, 0x9d, 0xfa, 0xb7, 0xc4, 0x4c, 0x6a, 0x97, 0x5f, 0x36, 0x4e, 0x47, 0xdd, 0x17, 0xf7, 0xf9, 0x19, 0xce, 0x75, 0x17, 0xad, 0xce, 0x2a, 0xf3, 0xfe, 0x27, 0x8f, 0x3e, 0x48, 0xc0, 0x60, 0x87, 0x24, 0x19, 0xae, 0x59, 0xe4, 0x5a, 0x00, 0x2a, 0xba, 0xa2, 0x1f,
/* (2^146)P */ 0x26, 0x88, 0x42, 0x60, 0x9f, 0x6e, 0x2c, 0x7c, 0x39, 0x0f, 0x47, 0x6a, 0x0e, 0x02, 0xbb, 0x4b, 0x34, 0x29, 0x55, 0x18, 0x36, 0xcf, 0x3b, 0x47, 0xf1, 0x2e, 0xfc, 0x6e, 0x94, 0xff, 0xe8, 0x6b, 0x06, 0xd2, 0xba, 0x77, 0x5e, 0x60, 0xd7, 0x19, 0xef, 0x02, 0x9d, 0x3a, 0xc2, 0xb7, 0xa9, 0xd8, 0x57, 0xee, 0x7e, 0x2b, 0xf2, 0x6d, 0x28, 0xda,
/* (2^147)P */ 0xdf, 0xd9, 0x92, 0x11, 0x98, 0x23, 0xe2, 0x45, 0x2f, 0x74, 0x70, 0xee, 0x0e, 0x55, 0x65, 0x79, 0x86, 0x38, 0x17, 0x92, 0x85, 0x87, 0x99, 0x50, 0xd9, 0x7c, 0xdb, 0xa1, 0x10, 0xec, 0x30, 0xb7, 0x40, 0xa3, 0x23, 0x9b, 0x0e, 0x27, 0x49, 0x29, 0x03, 0x94, 0xff, 0x53, 0xdc, 0xd7, 0xed, 0x49, 0xa9, 0x5a, 0x3b, 0xee, 0xd7, 0xc7, 0x65, 0xaf,
/* (2^148)P */ 0xa0, 0xbd, 0xbe, 0x03, 0xee, 0x0c, 0xbe, 0x32, 0x00, 0x7b, 0x52, 0xcb, 0x92, 0x29, 0xbf, 0xa0, 0xc6, 0xd9, 0xd2, 0xd6, 0x15, 0xe8, 0x3a, 0x75, 0x61, 0x65, 0x56, 0xae, 0xad, 0x3c, 0x2a, 0x64, 0x14, 0x3f, 0x8e, 0xc1, 0x2d, 0x0c, 0x8d, 0x20, 0xdb, 0x58, 0x4b, 0xe5, 0x40, 0x15, 0x4b, 0xdc, 0xa8, 0xbd, 0xef, 0x08, 0xa7, 0xd1, 0xf4, 0xb0,
/* (2^149)P */ 0xa9, 0x0f, 0x05, 0x94, 0x66, 0xac, 0x1f, 0x65, 0x3f, 0xe1, 0xb8, 0xe1, 0x34, 0x5e, 0x1d, 0x8f, 0xe3, 0x93, 0x03, 0x15, 0xff, 0xb6, 0x65, 0xb6, 0x6e, 0xc0, 0x2f, 0xd4, 0x2e, 0xb9, 0x2c, 0x13, 0x3c, 0x99, 0x1c, 0xb5, 0x87, 0xba, 0x79, 0xcb, 0xf0, 0x18, 0x06, 0x86, 0x04, 0x14, 0x25, 0x09, 0xcd, 0x1c, 0x14, 0xda, 0x35, 0xd0, 0x38, 0x3b,
/* (2^150)P */ 0x1b, 0x04, 0xa3, 0x27, 0xb4, 0xd3, 0x37, 0x48, 0x1e, 0x8f, 0x69, 0xd3, 0x5a, 0x2f, 0x20, 0x02, 0x36, 0xbe, 0x06, 0x7b, 0x6b, 0x6c, 0x12, 0x5b, 0x80, 0x74, 0x44, 0xe6, 0xf8, 0xf5, 0x95, 0x59, 0x29, 0xab, 0x51, 0x47, 0x83, 0x28, 0xe0, 0xad, 0xde, 0xaa, 0xd3, 0xb1, 0x1a, 0xcb, 0xa3, 0xcd, 0x8b, 0x6a, 0xb1, 0xa7, 0x0a, 0xd1, 0xf9, 0xbe,
/* (2^151)P */ 0xce, 0x2f, 0x85, 0xca, 0x74, 0x6d, 0x49, 0xb8, 0xce, 0x80, 0x44, 0xe0, 0xda, 0x5b, 0xcf, 0x2f, 0x79, 0x74, 0xfe, 0xb4, 0x2c, 0x99, 0x20, 0x6e, 0x09, 0x04, 0xfb, 0x6d, 0x57, 0x5b, 0x95, 0x0c, 0x45, 0xda, 0x4f, 0x7f, 0x63, 0xcc, 0x85, 0x5a, 0x67, 0x50, 0x68, 0x71, 0xb4, 0x67, 0xb1, 0x2e, 0xc1, 0x1c, 0xdc, 0xff, 0x2a, 0x7c, 0x10, 0x5e,
/* (2^152)P */ 0xa6, 0xde, 0xf3, 0xd4, 0x22, 0x30, 0x24, 0x9e, 0x0b, 0x30, 0x54, 0x59, 0x7e, 0xa2, 0xeb, 0x89, 0x54, 0x65, 0x3e, 0x40, 0xd1, 0xde, 0xe6, 0xee, 0x4d, 0xbf, 0x5e, 0x40, 0x1d, 0xee, 0x4f, 0x68, 0xd9, 0xa7, 0x2f, 0xb3, 0x64, 0xb3, 0xf5, 0xc8, 0xd3, 0xaa, 0x70, 0x70, 0x3d, 0xef, 0xd3, 0x95, 0x54, 0xdb, 0x3e, 0x94, 0x95, 0x92, 0x1f, 0x45,
/* (2^153)P */ 0x22, 0x80, 0x1d, 0x9d, 0x96, 0xa5, 0x78, 0x6f, 0xe0, 0x1e, 0x1b, 0x66, 0x42, 0xc8, 0xae, 0x9e, 0x46, 0x45, 0x08, 0x41, 0xdf, 0x80, 0xae, 0x6f, 0xdb, 0x15, 0x5a, 0x21, 0x31, 0x7a, 0xd0, 0xf2, 0x54, 0x15, 0x88, 0xd3, 0x0f, 0x7f, 0x14, 0x5a, 0x14, 0x97, 0xab, 0xf4, 0x58, 0x6a, 0x9f, 0xea, 0x74, 0xe5, 0x6b, 0x90, 0x59, 0x2b, 0x48, 0xd9,
/* (2^154)P */ 0x12, 0x24, 0x04, 0xf5, 0x50, 0xc2, 0x8c, 0xb0, 0x7c, 0x46, 0x98, 0xd5, 0x24, 0xad, 0xf6, 0x72, 0xdc, 0x82, 0x1a, 0x60, 0xc1, 0xeb, 0x48, 0xef, 0x7f, 0x6e, 0xe6, 0xcc, 0xdb, 0x7b, 0xae, 0xbe, 0x5e, 0x1e, 0x5c, 0xe6, 0x0a, 0x70, 0xdf, 0xa4, 0xa3, 0x85, 0x1b, 0x1b, 0x7f, 0x72, 0xb9, 0x96, 0x6f, 0xdc, 0x03, 0x76, 0x66, 0xfb, 0xa0, 0x33,
/* (2^155)P */ 0x37, 0x40, 0xbb, 0xbc, 0x68, 0x58, 0x86, 0xca, 0xbb, 0xa5, 0x24, 0x76, 0x3d, 0x48, 0xd1, 0xad, 0xb4, 0xa8, 0xcf, 0xc3, 0xb6, 0xa8, 0xba, 0x1a, 0x3a, 0xbe, 0x33, 0x75, 0x04, 0x5c, 0x13, 0x8c, 0x0d, 0x70, 0x8d, 0xa6, 0x4e, 0x2a, 0xeb, 0x17, 0x3c, 0x22, 0xdd, 0x3e, 0x96, 0x40, 0x11, 0x9e, 0x4e, 0xae, 0x3d, 0xf8, 0x91, 0xd7, 0x50, 0xc8,
/* (2^156)P */ 0xd8, 0xca, 0xde, 0x19, 0xcf, 0x00, 0xe4, 0x73, 0x18, 0x7f, 0x9b, 0x9f, 0xf4, 0x5b, 0x49, 0x49, 0x99, 0xdc, 0xa4, 0x46, 0x21, 0xb5, 0xd7, 0x3e, 0xb7, 0x47, 0x1b, 0xa9, 0x9f, 0x4c, 0x69, 0x7d, 0xec, 0x33, 0xd6, 0x1c, 0x51, 0x7f, 0x47, 0x74, 0x7a, 0x6c, 0xf3, 0xd2, 0x2e, 0xbf, 0xdf, 0x6c, 0x9e, 0x77, 0x3b, 0x34, 0xf6, 0x73, 0x80, 0xed,
/* (2^157)P */ 0x16, 0xfb, 0x16, 0xc3, 0xc2, 0x83, 0xe4, 0xf4, 0x03, 0x7f, 0x52, 0xb0, 0x67, 0x51, 0x7b, 0x24, 0x5a, 0x51, 0xd3, 0xb6, 0x4e, 0x59, 0x76, 0xcd, 0x08, 0x7b, 0x1d, 0x7a, 0x9c, 0x65, 0xae, 0xce, 0xaa, 0xd2, 0x1c, 0x85, 0x66, 0x68, 0x06, 0x15, 0xa8, 0x06, 0xe6, 0x16, 0x37, 0xf4, 0x49, 0x9e, 0x0f, 0x50, 0x37, 0xb1, 0xb2, 0x93, 0x70, 0x43,
/* (2^158)P */ 0x18, 0x3a, 0x16, 0xe5, 0x8d, 0xc8, 0x35, 0xd6, 0x7b, 0x09, 0xec, 0x61, 0x5f, 0x5c, 0x2a, 0x19, 0x96, 0x2e, 0xc3, 0xfd, 0xab, 0xe6, 0x23, 0xae, 0xab, 0xc5, 0xcb, 0xb9, 0x7b, 0x2d, 0x34, 0x51, 0xb9, 0x41, 0x9e, 0x7d, 0xca, 0xda, 0x25, 0x45, 0x14, 0xb0, 0xc7, 0x4d, 0x26, 0x2b, 0xfe, 0x43, 0xb0, 0x21, 0x5e, 0xfa, 0xdc, 0x7c, 0xf9, 0x5a,
/* (2^159)P */ 0x94, 0xad, 0x42, 0x17, 0xf5, 0xcd, 0x1c, 0x0d, 0xf6, 0x41, 0xd2, 0x55, 0xbb, 0x50, 0xf1, 0xc6, 0xbc, 0xa6, 0xc5, 0x3a, 0xfd, 0x9b, 0x75, 0x3e, 0xf6, 0x1a, 0xa7, 0xb2, 0x6e, 0x64, 0x12, 0xdc, 0x3c, 0xe5, 0xf6, 0xfc, 0x3b, 0xfa, 0x43, 0x81, 0xd4, 0xa5, 0xee, 0xf5, 0x9c, 0x47, 0x2f, 0xd0, 0x9c, 0xde, 0xa1, 0x48, 0x91, 0x9a, 0x34, 0xc1,
/* (2^160)P */ 0x37, 0x1b, 0xb3, 0x88, 0xc9, 0x98, 0x4e, 0xfb, 0x84, 0x4f, 0x2b, 0x0a, 0xb6, 0x8f, 0x35, 0x15, 0xcd, 0x61, 0x7a, 0x5f, 0x5c, 0xa0, 0xca, 0x23, 0xa0, 0x93, 0x1f, 0xcc, 0x3c, 0x39, 0x3a, 0x24, 0xa7, 0x49, 0xad, 0x8d, 0x59, 0xcc, 0x94, 0x5a, 0x16, 0xf5, 0x70, 0xe8, 0x52, 0x1e, 0xee, 0x20, 0x30, 0x17, 0x7e, 0xf0, 0x4c, 0x93, 0x06, 0x5a,
/* (2^161)P */ 0x81, 0xba, 0x3b, 0xd7, 0x3e, 0xb4, 0x32, 0x3a, 0x22, 0x39, 0x2a, 0xfc, 0x19, 0xd9, 0xd2, 0xf6, 0xc5, 0x79, 0x6c, 0x0e, 0xde, 0xda, 0x01, 0xff, 0x52, 0xfb, 0xb6, 0x95, 0x4e, 0x7a, 0x10, 0xb8, 0x06, 0x86, 0x3c, 0xcd, 0x56, 0xd6, 0x15, 0xbf, 0x6e, 0x3e, 0x4f, 0x35, 0x5e, 0xca, 0xbc, 0xa5, 0x95, 0xa2, 0xdf, 0x2d, 0x1d, 0xaf, 0x59, 0xf9,
/* (2^162)P */ 0x69, 0xe5, 0xe2, 0xfa, 0xc9, 0x7f, 0xdd, 0x09, 0xf5, 0x6b, 0x4e, 0x2e, 0xbe, 0xb4, 0xbf, 0x3e, 0xb2, 0xf2, 0x81, 0x30, 0xe1, 0x07, 0xa8, 0x0d, 0x2b, 0xd2, 0x5a, 0x55, 0xbe, 0x4b, 0x86, 0x5d, 0xb0, 0x5e, 0x7c, 0x8f, 0xc1, 0x3c, 0x81, 0x4c, 0xf7, 0x6d, 0x7d, 0xe6, 0x4f, 0x8a, 0x85, 0xc2, 0x2f, 0x28, 0xef, 0x8c, 0x69, 0xc2, 0xc2, 0x1a,
/* (2^163)P */ 0xd9, 0xe4, 0x0e, 0x1e, 0xc2, 0xf7, 0x2f, 0x9f, 0xa1, 0x40, 0xfe, 0x46, 0x16, 0xaf, 0x2e, 0xd1, 0xec, 0x15, 0x9b, 0x61, 0x92, 0xce, 0xfc, 0x10, 0x43, 0x1d, 0x00, 0xf6, 0xbe, 0x20, 0x80, 0x80, 0x6f, 0x3c, 0x16, 0x94, 0x59, 0xba, 0x03, 0x53, 0x6e, 0xb6, 0xdd, 0x25, 0x7b, 0x86, 0xbf, 0x96, 0xf4, 0x2f, 0xa1, 0x96, 0x8d, 0xf9, 0xb3, 0x29,
/* (2^164)P */ 0x3b, 0x04, 0x60, 0x6e, 0xce, 0xab, 0xd2, 0x63, 0x18, 0x53, 0x88, 0x16, 0x4a, 0x6a, 0xab, 0x72, 0x03, 0x68, 0xa5, 0xd4, 0x0d, 0xb2, 0x82, 0x81, 0x1f, 0x2b, 0x5c, 0x75, 0xe8, 0xd2, 0x1d, 0x7f, 0xe7, 0x1b, 0x35, 0x02, 0xde, 0xec, 0xbd, 0xcb, 0xc7, 0x01, 0xd3, 0x95, 0x61, 0xfe, 0xb2, 0x7a, 0x66, 0x09, 0x4c, 0x6d, 0xfd, 0x39, 0xf7, 0x52,
/* (2^165)P */ 0x42, 0xc1, 0x5f, 0xf8, 0x35, 0x52, 0xc1, 0xfe, 0xc5, 0x11, 0x80, 0x1c, 0x11, 0x46, 0x31, 0x11, 0xbe, 0xd0, 0xc4, 0xb6, 0x07, 0x13, 0x38, 0xa0, 0x8d, 0x65, 0xf0, 0x56, 0x9e, 0x16, 0xbf, 0x9d, 0xcd, 0x51, 0x34, 0xf9, 0x08, 0x48, 0x7b, 0x76, 0x0c, 0x7b, 0x30, 0x07, 0xa8, 0x76, 0xaf, 0xa3, 0x29, 0x38, 0xb0, 0x58, 0xde, 0x72, 0x4b, 0x45,
/* (2^166)P */ 0xd4, 0x16, 0xa7, 0xc0, 0xb4, 0x9f, 0xdf, 0x1a, 0x37, 0xc8, 0x35, 0xed, 0xc5, 0x85, 0x74, 0x64, 0x09, 0x22, 0xef, 0xe9, 0x0c, 0xaf, 0x12, 0x4c, 0x9e, 0xf8, 0x47, 0x56, 0xe0, 0x7f, 0x4e, 0x24, 0x6b, 0x0c, 0xe7, 0xad, 0xc6, 0x47, 0x1d, 0xa4, 0x0d, 0x86, 0x89, 0x65, 0xe8, 0x5f, 0x71, 0xc7, 0xe9, 0xcd, 0xec, 0x6c, 0x62, 0xc7, 0xe3, 0xb3,
/* (2^167)P */ 0xb5, 0xea, 0x86, 0xe3, 0x15, 0x18, 0x3f, 0x6d, 0x7b, 0x05, 0x95, 0x15, 0x53, 0x26, 0x1c, 0xeb, 0xbe, 0x7e, 0x16, 0x42, 0x4b, 0xa2, 0x3d, 0xdd, 0x0e, 0xff, 0xba, 0x67, 0xb5, 0xae, 0x7a, 0x17, 0xde, 0x23, 0xad, 0x14, 0xcc, 0xd7, 0xaf, 0x57, 0x01, 0xe0, 0xdd, 0x48, 0xdd, 0xd7, 0xe3, 0xdf, 0xe9, 0x2d, 0xda, 0x67, 0xa4, 0x9f, 0x29, 0x04,
/* (2^168)P */ 0x16, 0x53, 0xe6, 0x9c, 0x4e, 0xe5, 0x1e, 0x70, 0x81, 0x25, 0x02, 0x9b, 0x47, 0x6d, 0xd2, 0x08, 0x73, 0xbe, 0x0a, 0xf1, 0x7b, 0xeb, 0x24, 0xeb, 0x38, 0x23, 0x5c, 0xb6, 0x3e, 0xce, 0x1e, 0xe3, 0xbc, 0x82, 0x35, 0x1f, 0xaf, 0x3a, 0x3a, 0xe5, 0x4e, 0xc1, 0xca, 0xbf, 0x47, 0xb4, 0xbb, 0xbc, 0x5f, 0xea, 0xc6, 0xca, 0xf3, 0xa0, 0xa2, 0x73,
/* (2^169)P */ 0xef, 0xa4, 0x7a, 0x4e, 0xe4, 0xc7, 0xb6, 0x43, 0x2e, 0xa5, 0xe4, 0xa5, 0xba, 0x1e, 0xa5, 0xfe, 0x9e, 0xce, 0xa9, 0x80, 0x04, 0xcb, 0x4f, 0xd8, 0x74, 0x05, 0x48, 0xfa, 0x99, 0x11, 0x5d, 0x97, 0x3b, 0x07, 0x0d, 0xdd, 0xe6, 0xb1, 0x74, 0x87, 0x1a, 0xd3, 0x26, 0xb7, 0x8f, 0xe1, 0x63, 0x3d, 0xec, 0x53, 0x93, 0xb0, 0x81, 0x78, 0x34, 0xa4,
/* (2^170)P */ 0xe1, 0xe7, 0xd4, 0x58, 0x9d, 0x0e, 0x8b, 0x65, 0x66, 0x37, 0x16, 0x48, 0x6f, 0xaa, 0x42, 0x37, 0x77, 0xad, 0xb1, 0x56, 0x48, 0xdf, 0x65, 0x36, 0x30, 0xb8, 0x00, 0x12, 0xd8, 0x32, 0x28, 0x7f, 0xc1, 0x71, 0xeb, 0x93, 0x0f, 0x48, 0x04, 0xe1, 0x5a, 0x6a, 0x96, 0xc1, 0xca, 0x89, 0x6d, 0x1b, 0x82, 0x4c, 0x18, 0x6d, 0x55, 0x4b, 0xea, 0xfd,
/* (2^171)P */ 0x62, 0x1a, 0x53, 0xb4, 0xb1, 0xbe, 0x6f, 0x15, 0x18, 0x88, 0xd4, 0x66, 0x61, 0xc7, 0x12, 0x69, 0x02, 0xbd, 0x03, 0x23, 0x2b, 0xef, 0xf9, 0x54, 0xa4, 0x85, 0xa8, 0xe3, 0xb7, 0xbd, 0xa9, 0xa3, 0xf3, 0x2a, 0xdd, 0xf1, 0xd4, 0x03, 0x0f, 0xa9, 0xa1, 0xd8, 0xa3, 0xcd, 0xb2, 0x71, 0x90, 0x4b, 0x35, 0x62, 0xf2, 0x2f, 0xce, 0x67, 0x1f, 0xaa,
/* (2^172)P */ 0x9e, 0x1e, 0xcd, 0x43, 0x7e, 0x87, 0x37, 0x94, 0x3a, 0x97, 0x4c, 0x7e, 0xee, 0xc9, 0x37, 0x85, 0xf1, 0xd9, 0x4f, 0xbf, 0xf9, 0x6f, 0x39, 0x9a, 0x39, 0x87, 0x2e, 0x25, 0x84, 0x42, 0xc3, 0x80, 0xcb, 0x07, 0x22, 0xae, 0x30, 0xd5, 0x50, 0xa1, 0x23, 0xcc, 0x31, 0x81, 0x9d, 0xf1, 0x30, 0xd9, 0x2b, 0x73, 0x41, 0x16, 0x50, 0xab, 0x2d, 0xa2,
/* (2^173)P */ 0xa4, 0x69, 0x4f, 0xa1, 0x4e, 0xb9, 0xbf, 0x14, 0xe8, 0x2b, 0x04, 0x93, 0xb7, 0x6e, 0x9f, 0x7d, 0x73, 0x0a, 0xc5, 0x14, 0xb8, 0xde, 0x8c, 0xc1, 0xfe, 0xc0, 0xa7, 0xa4, 0xcc, 0x42, 0x42, 0x81, 0x15, 0x65, 0x8a, 0x80, 0xb9, 0xde, 0x1f, 0x60, 0x33, 0x0e, 0xcb, 0xfc, 0xe0, 0xdb, 0x83, 0xa1, 0xe5, 0xd0, 0x16, 0x86, 0x2c, 0xe2, 0x87, 0xed,
/* (2^174)P */ 0x7a, 0xc0, 0xeb, 0x6b, 0xf6, 0x0d, 0x4c, 0x6d, 0x1e, 0xdb, 0xab, 0xe7, 0x19, 0x45, 0xc6, 0xe3, 0xb2, 0x06, 0xbb, 0xbc, 0x70, 0x99, 0x83, 0x33, 0xeb, 0x28, 0xc8, 0x77, 0xf6, 0x4d, 0x01, 0xb7, 0x59, 0xa0, 0xd2, 0xb3, 0x2a, 0x72, 0x30, 0xe7, 0x11, 0x39, 0xb6, 0x41, 0x29, 0x65, 0x5a, 0x14, 0xb9, 0x86, 0x08, 0xe0, 0x7d, 0x32, 0x8c, 0xf0,
/* (2^175)P */ 0x5c, 0x11, 0x30, 0x9e, 0x05, 0x27, 0xf5, 0x45, 0x0f, 0xb3, 0xc9, 0x75, 0xc3, 0xd7, 0xe1, 0x82, 0x3b, 0x8e, 0x87, 0x23, 0x00, 0x15, 0x19, 0x07, 0xd9, 0x21, 0x53, 0xc7, 0xf1, 0xa3, 0xbf, 0x70, 0x64, 0x15, 0x18, 0xca, 0x23, 0x9e, 0xd3, 0x08, 0xc3, 0x2a, 0x8b, 0xe5, 0x83, 0x04, 0x89, 0x14, 0xfd, 0x28, 0x25, 0x1c, 0xe3, 0x26, 0xa7, 0x22,
/* (2^176)P */ 0xdc, 0xd4, 0x75, 0x60, 0x99, 0x94, 0xea, 0x09, 0x8e, 0x8a, 0x3c, 0x1b, 0xf9, 0xbd, 0x33, 0x0d, 0x51, 0x3d, 0x12, 0x6f, 0x4e, 0x72, 0xe0, 0x17, 0x20, 0xe9, 0x75, 0xe6, 0x3a, 0xb2, 0x13, 0x83, 0x4e, 0x7a, 0x08, 0x9e, 0xd1, 0x04, 0x5f, 0x6b, 0x42, 0x0b, 0x76, 0x2a, 0x2d, 0x77, 0x53, 0x6c, 0x65, 0x6d, 0x8e, 0x25, 0x3c, 0xb6, 0x8b, 0x69,
/* (2^177)P */ 0xb9, 0x49, 0x28, 0xd0, 0xdc, 0x6c, 0x8f, 0x4c, 0xc9, 0x14, 0x8a, 0x38, 0xa3, 0xcb, 0xc4, 0x9d, 0x53, 0xcf, 0xe9, 0xe3, 0xcf, 0xe0, 0xb1, 0xf2, 0x1b, 0x4c, 0x7f, 0x83, 0x2a, 0x7a, 0xe9, 0x8b, 0x3b, 0x86, 0x61, 0x30, 0xe9, 0x99, 0xbd, 0xba, 0x19, 0x6e, 0x65, 0x2a, 0x12, 0x3e, 0x9c, 0xa8, 0xaf, 0xc3, 0xcf, 0xf8, 0x1f, 0x77, 0x86, 0xea,
/* (2^178)P */ 0x30, 0xde, 0xe7, 0xff, 0x54, 0xf7, 0xa2, 0x59, 0xf6, 0x0b, 0xfb, 0x7a, 0xf2, 0x39, 0xf0, 0xdb, 0x39, 0xbc, 0xf0, 0xfa, 0x60, 0xeb, 0x6b, 0x4f, 0x47, 0x17, 0xc8, 0x00, 0x65, 0x6d, 0x25, 0x1c, 0xd0, 0x48, 0x56, 0x53, 0x45, 0x11, 0x30, 0x02, 0x49, 0x20, 0x27, 0xac, 0xf2, 0x4c, 0xac, 0x64, 0x3d, 0x52, 0xb8, 0x89, 0xe0, 0x93, 0x16, 0x0f,
/* (2^179)P */ 0x84, 0x09, 0xba, 0x40, 0xb2, 0x2f, 0xa3, 0xa8, 0xc2, 0xba, 0x46, 0x33, 0x05, 0x9d, 0x62, 0xad, 0xa1, 0x3c, 0x33, 0xef, 0x0d, 0xeb, 0xf0, 0x77, 0x11, 0x5a, 0xb0, 0x21, 0x9c, 0xdf, 0x55, 0x24, 0x25, 0x35, 0x51, 0x61, 0x92, 0xf0, 0xb1, 0xce, 0xf5, 0xd4, 0x7b, 0x6c, 0x21, 0x9d, 0x56, 0x52, 0xf8, 0xa1, 0x4c, 0xe9, 0x27, 0x55, 0xac, 0x91,
/* (2^180)P */ 0x03, 0x3e, 0x30, 0xd2, 0x0a, 0xfa, 0x7d, 0x82, 0x3d, 0x1f, 0x8b, 0xcb, 0xb6, 0x04, 0x5c, 0xcc, 0x8b, 0xda, 0xe2, 0x68, 0x74, 0x08, 0x8c, 0x44, 0x83, 0x57, 0x6d, 0x6f, 0x80, 0xb0, 0x7e, 0xa9, 0x82, 0x91, 0x7b, 0x4c, 0x37, 0x97, 0xd1, 0x63, 0xd1, 0xbd, 0x45, 0xe6, 0x8a, 0x86, 0xd6, 0x89, 0x54, 0xfd, 0xd2, 0xb1, 0xd7, 0x54, 0xad, 0xaf,
/* (2^181)P */ 0x8b, 0x33, 0x62, 0x49, 0x9f, 0x63, 0xf9, 0x87, 0x42, 0x58, 0xbf, 0xb3, 0xe6, 0x68, 0x02, 0x60, 0x5c, 0x76, 0x62, 0xf7, 0x61, 0xd7, 0x36, 0x31, 0xf7, 0x9c, 0xb5, 0xe5, 0x13, 0x6c, 0xea, 0x78, 0xae, 0xcf, 0xde, 0xbf, 0xb6, 0xeb, 0x4f, 0xc8, 0x2a, 0xb4, 0x9a, 0x9f, 0xf3, 0xd1, 0x6a, 0xec, 0x0c, 0xbd, 0x85, 0x98, 0x40, 0x06, 0x1c, 0x2a,
/* (2^182)P */ 0x74, 0x3b, 0xe7, 0x81, 0xd5, 0xae, 0x54, 0x56, 0x03, 0xe8, 0x97, 0x16, 0x76, 0xcf, 0x24, 0x96, 0x96, 0x5b, 0xcc, 0x09, 0xab, 0x23, 0x6f, 0x54, 0xae, 0x8f, 0xe4, 0x12, 0xcb, 0xfd, 0xbc, 0xac, 0x93, 0x45, 0x3d, 0x68, 0x08, 0x22, 0x59, 0xc6, 0xf0, 0x47, 0x19, 0x8c, 0x79, 0x93, 0x1e, 0x0e, 0x30, 0xb0, 0x94, 0xfb, 0x17, 0x1d, 0x5a, 0x12,
/* (2^183)P */ 0x85, 0xff, 0x40, 0x18, 0x85, 0xff, 0x44, 0x37, 0x69, 0x23, 0x4d, 0x34, 0xe1, 0xeb, 0xa3, 0x1b, 0x55, 0x40, 0xc1, 0x64, 0xf4, 0xd4, 0x13, 0x0a, 0x9f, 0xb9, 0x19, 0xfc, 0x88, 0x7d, 0xc0, 0x72, 0xcf, 0x69, 0x2f, 0xd2, 0x0c, 0x82, 0x0f, 0xda, 0x08, 0xba, 0x0f, 0xaa, 0x3b, 0xe9, 0xe5, 0x83, 0x7a, 0x06, 0xe8, 0x1b, 0x38, 0x43, 0xc3, 0x54,
/* (2^184)P */ 0x14, 0xaa, 0xb3, 0x6e, 0xe6, 0x28, 0xee, 0xc5, 0x22, 0x6c, 0x7c, 0xf9, 0xa8, 0x71, 0xcc, 0xfe, 0x68, 0x7e, 0xd3, 0xb8, 0x37, 0x96, 0xca, 0x0b, 0xd9, 0xb6, 0x06, 0xa9, 0xf6, 0x71, 0xe8, 0x31, 0xf7, 0xd8, 0xf1, 0x5d, 0xab, 0xb9, 0xf0, 0x5c, 0x98, 0xcf, 0x22, 0xa2, 0x2a, 0xf6, 0xd0, 0x59, 0xf0, 0x9d, 0xd9, 0x6a, 0x4f, 0x59, 0x57, 0xad,
/* (2^185)P */ 0xd7, 0x2b, 0x3d, 0x38, 0x4c, 0x2e, 0x23, 0x4d, 0x49, 0xa2, 0x62, 0x62, 0xf9, 0x0f, 0xde, 0x08, 0xf3, 0x86, 0x71, 0xb6, 0xc7, 0xf9, 0x85, 0x9c, 0x33, 0xa1, 0xcf, 0x16, 0xaa, 0x60, 0xb9, 0xb7, 0xea, 0xed, 0x01, 0x1c, 0x59, 0xdb, 0x3f, 0x3f, 0x97, 0x2e, 0xf0, 0x09, 0x9f, 0x10, 0x85, 0x5f, 0x53, 0x39, 0xf3, 0x13, 0x40, 0x56, 0x95, 0xf9,
/* (2^186)P */ 0xb4, 0xe3, 0xda, 0xc6, 0x1f, 0x78, 0x8e, 0xac, 0xd4, 0x20, 0x1d, 0xa0, 0xbf, 0x4c, 0x09, 0x16, 0xa7, 0x30, 0xb5, 0x8d, 0x9e, 0xa1, 0x5f, 0x6d, 0x52, 0xf4, 0x71, 0xb6, 0x32, 0x2d, 0x21, 0x51, 0xc6, 0xfc, 0x2f, 0x08, 0xf4, 0x13, 0x6c, 0x55, 0xba, 0x72, 0x81, 0x24, 0x49, 0x0e, 0x4f, 0x06, 0x36, 0x39, 0x6a, 0xc5, 0x81, 0xfc, 0xeb, 0xb2,
/* (2^187)P */ 0x7d, 0x8d, 0xc8, 0x6c, 0xea, 0xb4, 0xb9, 0xe8, 0x40, 0xc9, 0x69, 0xc9, 0x30, 0x05, 0xfd, 0x34, 0x46, 0xfd, 0x94, 0x05, 0x16, 0xf5, 0x4b, 0x13, 0x3d, 0x24, 0x1a, 0xd6, 0x64, 0x2b, 0x9c, 0xe2, 0xa5, 0xd9, 0x98, 0xe0, 0xe8, 0xf4, 0xbc, 0x2c, 0xbd, 0xa2, 0x56, 0xe3, 0x9e, 0x14, 0xdb, 0xbf, 0x05, 0xbf, 0x9a, 0x13, 0x5d, 0xf7, 0x91, 0xa3,
/* (2^188)P */ 0x8b, 0xcb, 0x27, 0xf3, 0x15, 0x26, 0x05, 0x40, 0x0f, 0xa6, 0x15, 0x13, 0x71, 0x95, 0xa2, 0xc6, 0x38, 0x04, 0x67, 0xf8, 0x9a, 0x83, 0x06, 0xaa, 0x25, 0x36, 0x72, 0x01, 0x6f, 0x74, 0x5f, 0xe5, 0x6e, 0x44, 0x99, 0xce, 0x13, 0xbc, 0x82, 0xc2, 0x0d, 0xa4, 0x98, 0x50, 0x38, 0xf3, 0xa2, 0xc5, 0xe5, 0x24, 0x1f, 0x6f, 0x56, 0x3e, 0x07, 0xb2,
/* (2^189)P */ 0xbd, 0x0f, 0x32, 0x60, 0x07, 0xb1, 0xd7, 0x0b, 0x11, 0x07, 0x57, 0x02, 0x89, 0xe8, 0x8b, 0xe8, 0x5a, 0x1f, 0xee, 0x54, 0x6b, 0xff, 0xb3, 0x04, 0x07, 0x57, 0x13, 0x0b, 0x94, 0xa8, 0x4d, 0x81, 0xe2, 0x17, 0x16, 0x45, 0xd4, 0x4b, 0xf7, 0x7e, 0x64, 0x66, 0x20, 0xe8, 0x0b, 0x26, 0xfd, 0xa9, 0x8a, 0x47, 0x52, 0x89, 0x14, 0xd0, 0xd1, 0xa1,
/* (2^190)P */ 0xdc, 0x03, 0xe6, 0x20, 0x44, 0x47, 0x8f, 0x04, 0x16, 0x24, 0x22, 0xc1, 0x55, 0x5c, 0xbe, 0x43, 0xc3, 0x92, 0xc5, 0x54, 0x3d, 0x5d, 0xd1, 0x05, 0x9c, 0xc6, 0x7c, 0xbf, 0x23, 0x84, 0x1a, 0xba, 0x4f, 0x1f, 0xfc, 0xa1, 0xae, 0x1a, 0x64, 0x02, 0x51, 0xf1, 0xcb, 0x7a, 0x20, 0xce, 0xb2, 0x34, 0x3c, 0xca, 0xe0, 0xe4, 0xba, 0x22, 0xd4, 0x7b,
/* (2^191)P */ 0xca, 0xfd, 0xca, 0xd7, 0xde, 0x61, 0xae, 0xf0, 0x79, 0x0c, 0x20, 0xab, 0xbc, 0x6f, 0x4d, 0x61, 0xf0, 0xc7, 0x9c, 0x8d, 0x4b, 0x52, 0xf3, 0xb9, 0x48, 0x63, 0x0b, 0xb6, 0xd2, 0x25, 0x9a, 0x96, 0x72, 0xc1, 0x6b, 0x0c, 0xb5, 0xfb, 0x71, 0xaa, 0xad, 0x47, 0x5b, 0xe7, 0xc0, 0x0a, 0x55, 0xb2, 0xd4, 0x16, 0x2f, 0xb1, 0x01, 0xfd, 0xce, 0x27,
/* (2^192)P */ 0x64, 0x11, 0x4b, 0xab, 0x57, 0x09, 0xc6, 0x49, 0x4a, 0x37, 0xc3, 0x36, 0xc4, 0x7b, 0x81, 0x1f, 0x42, 0xed, 0xbb, 0xe0, 0xa0, 0x8d, 0x51, 0xe6, 0xca, 0x8b, 0xb9, 0xcd, 0x99, 0x2d, 0x91, 0x53, 0xa9, 0x47, 0xcb, 0x32, 0xc7, 0xa4, 0x92, 0xec, 0x46, 0x74, 0x44, 0x6d, 0x71, 0x9f, 0x6d, 0x0c, 0x69, 0xa4, 0xf8, 0xbe, 0x9f, 0x7f, 0xa0, 0xd7,
/* (2^193)P */ 0x5f, 0x33, 0xb6, 0x91, 0xc8, 0xa5, 0x3f, 0x5d, 0x7f, 0x38, 0x6e, 0x74, 0x20, 0x4a, 0xd6, 0x2b, 0x98, 0x2a, 0x41, 0x4b, 0x83, 0x64, 0x0b, 0x92, 0x7a, 0x06, 0x1e, 0xc6, 0x2c, 0xf6, 0xe4, 0x91, 0xe5, 0xb1, 0x2e, 0x6e, 0x4e, 0xa8, 0xc8, 0x14, 0x32, 0x57, 0x44, 0x1c, 0xe4, 0xb9, 0x7f, 0x54, 0x51, 0x08, 0x81, 0xaa, 0x4e, 0xce, 0xa1, 0x5d,
/* (2^194)P */ 0x5c, 0xd5, 0x9b, 0x5e, 0x7c, 0xb5, 0xb1, 0x52, 0x73, 0x00, 0x41, 0x56, 0x79, 0x08, 0x7e, 0x07, 0x28, 0x06, 0xa6, 0xfb, 0x7f, 0x69, 0xbd, 0x7a, 0x3c, 0xae, 0x9f, 0x39, 0xbb, 0x54, 0xa2, 0x79, 0xb9, 0x0e, 0x7f, 0xbb, 0xe0, 0xe6, 0xb7, 0x27, 0x64, 0x38, 0x45, 0xdb, 0x84, 0xe4, 0x61, 0x72, 0x3f, 0xe2, 0x24, 0xfe, 0x7a, 0x31, 0x9a, 0xc9,
/* (2^195)P */ 0xa1, 0xd2, 0xa4, 0xee, 0x24, 0x96, 0xe5, 0x5b, 0x79, 0x78, 0x3c, 0x7b, 0x82, 0x3b, 0x8b, 0x58, 0x0b, 0xa3, 0x63, 0x2d, 0xbc, 0x75, 0x46, 0xe8, 0x83, 0x1a, 0xc0, 0x2a, 0x92, 0x61, 0xa8, 0x75, 0x37, 0x3c, 0xbf, 0x0f, 0xef, 0x8f, 0x6c, 0x97, 0x75, 0x10, 0x05, 0x7a, 0xde, 0x23, 0xe8, 0x2a, 0x35, 0xeb, 0x41, 0x64, 0x7d, 0xcf, 0xe0, 0x52,
/* (2^196)P */ 0x4a, 0xd0, 0x49, 0x93, 0xae, 0xf3, 0x24, 0x8c, 0xe1, 0x09, 0x98, 0x45, 0xd8, 0xb9, 0xfe, 0x8e, 0x8c, 0xa8, 0x2c, 0xc9, 0x9f, 0xce, 0x01, 0xdc, 0x38, 0x11, 0xab, 0x85, 0xb9, 0xe8, 0x00, 0x51, 0xfd, 0x82, 0xe1, 0x9b, 0x4e, 0xfc, 0xb5, 0x2a, 0x0f, 0x8b, 0xda, 0x4e, 0x02, 0xca, 0xcc, 0xe3, 0x91, 0xc4, 0xe0, 0xcf, 0x7b, 0xd6, 0xe6, 0x6a,
/* (2^197)P */ 0xfe, 0x11, 0xd7, 0xaa, 0xe3, 0x0c, 0x52, 0x2e, 0x04, 0xe0, 0xe0, 0x61, 0xc8, 0x05, 0xd7, 0x31, 0x4c, 0xc3, 0x9b, 0x2d, 0xce, 0x59, 0xbe, 0x12, 0xb7, 0x30, 0x21, 0xfc, 0x81, 0xb8, 0x5e, 0x57, 0x73, 0xd0, 0xad, 0x8e, 0x9e, 0xe4, 0xeb, 0xcd, 0xcf, 0xd2, 0x0f, 0x01, 0x35, 0x16, 0xed, 0x7a, 0x43, 0x8e, 0x42, 0xdc, 0xea, 0x4c, 0xa8, 0x7c,
/* (2^198)P */ 0x37, 0x26, 0xcc, 0x76, 0x0b, 0xe5, 0x76, 0xdd, 0x3e, 0x19, 0x3c, 0xc4, 0x6c, 0x7f, 0xd0, 0x03, 0xc1, 0xb8, 0x59, 0x82, 0xca, 0x36, 0xc1, 0xe4, 0xc8, 0xb2, 0x83, 0x69, 0x9c, 0xc5, 0x9d, 0x12, 0x82, 0x1c, 0xea, 0xb2, 0x84, 0x9f, 0xf3, 0x52, 0x6b, 0xbb, 0xd8, 0x81, 0x56, 0x83, 0x04, 0x66, 0x05, 0x22, 0x49, 0x37, 0x93, 0xb1, 0xfd, 0xd5,
/* (2^199)P */ 0xaf, 0x96, 0xbf, 0x03, 0xbe, 0xe6, 0x5d, 0x78, 0x19, 0xba, 0x37, 0x46, 0x0a, 0x2b, 0x52, 0x7c, 0xd8, 0x51, 0x9e, 0x3d, 0x29, 0x42, 0xdb, 0x0e, 0x31, 0x20, 0x94, 0xf8, 0x43, 0x9a, 0x2d, 0x22, 0xd3, 0xe3, 0xa1, 0x79, 0x68, 0xfb, 0x2d, 0x7e, 0xd6, 0x79, 0xda, 0x0b, 0xc6, 0x5b, 0x76, 0x68, 0xf0, 0xfe, 0x72, 0x59, 0xbb, 0xa1, 0x9c, 0x74,
/* (2^200)P */ 0x0a, 0xd9, 0xec, 0xc5, 0xbd, 0xf0, 0xda, 0xcf, 0x82, 0xab, 0x46, 0xc5, 0x32, 0x13, 0xdc, 0x5b, 0xac, 0xc3, 0x53, 0x9a, 0x7f, 0xef, 0xa5, 0x40, 0x5a, 0x1f, 0xc1, 0x12, 0x91, 0x54, 0x83, 0x6a, 0xb0, 0x9a, 0x85, 0x4d, 0xbf, 0x36, 0x8e, 0xd3, 0xa2, 0x2b, 0xe5, 0xd6, 0xc6, 0xe1, 0x58, 0x5b, 0x82, 0x9b, 0xc8, 0xf2, 0x03, 0xba, 0xf5, 0x92,
/* (2^201)P */ 0xfb, 0x21, 0x7e, 0xde, 0xe7, 0xb4, 0xc0, 0x56, 0x86, 0x3a, 0x5b, 0x78, 0xf8, 0xf0, 0xf4, 0xe7, 0x5c, 0x00, 0xd2, 0xd7, 0xd6, 0xf8, 0x75, 0x5e, 0x0f, 0x3e, 0xd1, 0x4b, 0x77, 0xd8, 0xad, 0xb0, 0xc9, 0x8b, 0x59, 0x7d, 0x30, 0x76, 0x64, 0x7a, 0x76, 0xd9, 0x51, 0x69, 0xfc, 0xbd, 0x8e, 0xb5, 0x55, 0xe0, 0xd2, 0x07, 0x15, 0xa9, 0xf7, 0xa4,
/* (2^202)P */ 0xaa, 0x2d, 0x2f, 0x2b, 0x3c, 0x15, 0xdd, 0xcd, 0xe9, 0x28, 0x82, 0x4f, 0xa2, 0xaa, 0x31, 0x48, 0xcc, 0xfa, 0x07, 0x73, 0x8a, 0x34, 0x74, 0x0d, 0xab, 0x1a, 0xca, 0xd2, 0xbf, 0x3a, 0xdb, 0x1a, 0x5f, 0x50, 0x62, 0xf4, 0x6b, 0x83, 0x38, 0x43, 0x96, 0xee, 0x6b, 0x39, 0x1e, 0xf0, 0x17, 0x80, 0x1e, 0x9b, 0xed, 0x2b, 0x2f, 0xcc, 0x65, 0xf7,
/* (2^203)P */ 0x03, 0xb3, 0x23, 0x9c, 0x0d, 0xd1, 0xeb, 0x7e, 0x34, 0x17, 0x8a, 0x4c, 0xde, 0x54, 0x39, 0xc4, 0x11, 0x82, 0xd3, 0xa4, 0x00, 0x32, 0x95, 0x9c, 0xa6, 0x64, 0x76, 0x6e, 0xd6, 0x53, 0x27, 0xb4, 0x6a, 0x14, 0x8c, 0x54, 0xf6, 0x58, 0x9e, 0x22, 0x4a, 0x55, 0x18, 0x77, 0xd0, 0x08, 0x6b, 0x19, 0x8a, 0xb5, 0xe7, 0x19, 0xb8, 0x60, 0x92, 0xb1,
/* (2^204)P */ 0x66, 0xec, 0xf3, 0x12, 0xde, 0x67, 0x7f, 0xd4, 0x5b, 0xf6, 0x70, 0x64, 0x0a, 0xb5, 0xc2, 0xf9, 0xb3, 0x64, 0xab, 0x56, 0x46, 0xc7, 0x93, 0xc2, 0x8b, 0x2d, 0xd0, 0xd6, 0x39, 0x3b, 0x1f, 0xcd, 0xb3, 0xac, 0xcc, 0x2c, 0x27, 0x6a, 0xbc, 0xb3, 0x4b, 0xa8, 0x3c, 0x69, 0x20, 0xe2, 0x18, 0x35, 0x17, 0xe1, 0x8a, 0xd3, 0x11, 0x74, 0xaa, 0x4d,
/* (2^205)P */ 0x96, 0xc4, 0x16, 0x7e, 0xfd, 0xf5, 0xd0, 0x7d, 0x1f, 0x32, 0x1b, 0xdb, 0xa6, 0xfd, 0x51, 0x75, 0x4d, 0xd7, 0x00, 0xe5, 0x7f, 0x58, 0x5b, 0xeb, 0x4b, 0x6a, 0x78, 0xfe, 0xe5, 0xd6, 0x8f, 0x99, 0x17, 0xca, 0x96, 0x45, 0xf7, 0x52, 0xdf, 0x84, 0x06, 0x77, 0xb9, 0x05, 0x63, 0x5d, 0xe9, 0x91, 0xb1, 0x4b, 0x82, 0x5a, 0xdb, 0xd7, 0xca, 0x69,
/* (2^206)P */ 0x02, 0xd3, 0x38, 0x38, 0x87, 0xea, 0xbd, 0x9f, 0x11, 0xca, 0xf3, 0x21, 0xf1, 0x9b, 0x35, 0x97, 0x98, 0xff, 0x8e, 0x6d, 0x3d, 0xd6, 0xb2, 0xfa, 0x68, 0xcb, 0x7e, 0x62, 0x85, 0xbb, 0xc7, 0x5d, 0xee, 0x32, 0x30, 0x2e, 0x71, 0x96, 0x63, 0x43, 0x98, 0xc4, 0xa7, 0xde, 0x60, 0xb2, 0xd9, 0x43, 0x4a, 0xfa, 0x97, 0x2d, 0x5f, 0x21, 0xd4, 0xfe,
/* (2^207)P */ 0x3b, 0x20, 0x29, 0x07, 0x07, 0xb5, 0x78, 0xc3, 0xc7, 0xab, 0x56, 0xba, 0x40, 0xde, 0x1d, 0xcf, 0xc3, 0x00, 0x56, 0x21, 0x0c, 0xc8, 0x42, 0xd9, 0x0e, 0xcd, 0x02, 0x7c, 0x07, 0xb9, 0x11, 0xd7, 0x96, 0xaf, 0xff, 0xad, 0xc5, 0xba, 0x30, 0x6d, 0x82, 0x3a, 0xbf, 0xef, 0x7b, 0xf7, 0x0a, 0x74, 0xbd, 0x31, 0x0c, 0xe4, 0xec, 0x1a, 0xe5, 0xc5,
/* (2^208)P */ 0xcc, 0xf2, 0x28, 0x16, 0x12, 0xbf, 0xef, 0x85, 0xbc, 0xf7, 0xcb, 0x9f, 0xdb, 0xa8, 0xb2, 0x49, 0x53, 0x48, 0xa8, 0x24, 0xa8, 0x68, 0x8d, 0xbb, 0x21, 0x0a, 0x5a, 0xbd, 0xb2, 0x91, 0x61, 0x47, 0xc4, 0x43, 0x08, 0xa6, 0x19, 0xef, 0x8e, 0x88, 0x39, 0xc6, 0x33, 0x30, 0xf3, 0x0e, 0xc5, 0x92, 0x66, 0xd6, 0xfe, 0xc5, 0x12, 0xd9, 0x4c, 0x2d,
/* (2^209)P */ 0x30, 0x34, 0x07, 0xbf, 0x9c, 0x5a, 0x4e, 0x65, 0xf1, 0x39, 0x35, 0x38, 0xae, 0x7b, 0x55, 0xac, 0x6a, 0x92, 0x24, 0x7e, 0x50, 0xd3, 0xba, 0x78, 0x51, 0xfe, 0x4d, 0x32, 0x05, 0x11, 0xf5, 0x52, 0xf1, 0x31, 0x45, 0x39, 0x98, 0x7b, 0x28, 0x56, 0xc3, 0x5d, 0x4f, 0x07, 0x6f, 0x84, 0xb8, 0x1a, 0x58, 0x0b, 0xc4, 0x7c, 0xc4, 0x8d, 0x32, 0x8e,
/* (2^210)P */ 0x7e, 0xaf, 0x98, 0xce, 0xc5, 0x2b, 0x9d, 0xf6, 0xfa, 0x2c, 0xb6, 0x2a, 0x5a, 0x1d, 0xc0, 0x24, 0x8d, 0xa4, 0xce, 0xb1, 0x12, 0x01, 0xf9, 0x79, 0xc6, 0x79, 0x38, 0x0c, 0xd4, 0x07, 0xc9, 0xf7, 0x37, 0xa1, 0x0b, 0xfe, 0x72, 0xec, 0x5d, 0xd6, 0xb0, 0x1c, 0x70, 0xbe, 0x70, 0x01, 0x13, 0xe0, 0x86, 0x95, 0xc7, 0x2e, 0x12, 0x3b, 0xe6, 0xa6,
/* (2^211)P */ 0x24, 0x82, 0x67, 0xe0, 0x14, 0x7b, 0x56, 0x08, 0x38, 0x44, 0xdb, 0xa0, 0x3a, 0x05, 0x47, 0xb2, 0xc0, 0xac, 0xd1, 0xcc, 0x3f, 0x82, 0xb8, 0x8a, 0x88, 0xbc, 0xf5, 0x33, 0xa1, 0x35, 0x0f, 0xf6, 0xe2, 0xef, 0x6c, 0xf7, 0x37, 0x9e, 0xe8, 0x10, 0xca, 0xb0, 0x8e, 0x80, 0x86, 0x00, 0x23, 0xd0, 0x4a, 0x76, 0x9f, 0xf7, 0x2c, 0x52, 0x15, 0x0e,
/* (2^212)P */ 0x5e, 0x49, 0xe1, 0x2c, 0x9a, 0x01, 0x76, 0xa6, 0xb3, 0x07, 0x5b, 0xa4, 0x07, 0xef, 0x1d, 0xc3, 0x6a, 0xbb, 0x64, 0xbe, 0x71, 0x15, 0x6e, 0x32, 0x31, 0x46, 0x9a, 0x9e, 0x8f, 0x45, 0x73, 0xce, 0x0b, 0x94, 0x1a, 0x52, 0x07, 0xf4, 0x50, 0x30, 0x49, 0x53, 0x50, 0xfb, 0x71, 0x1f, 0x5a, 0x03, 0xa9, 0x76, 0xf2, 0x8f, 0x42, 0xff, 0xed, 0xed,
/* (2^213)P */ 0xed, 0x08, 0xdb, 0x91, 0x1c, 0xee, 0xa2, 0xb4, 0x47, 0xa2, 0xfa, 0xcb, 0x03, 0xd1, 0xff, 0x8c, 0xad, 0x64, 0x50, 0x61, 0xcd, 0xfc, 0x88, 0xa0, 0x31, 0x95, 0x30, 0xb9, 0x58, 0xdd, 0xd7, 0x43, 0xe4, 0x46, 0xc2, 0x16, 0xd9, 0x72, 0x4a, 0x56, 0x51, 0x70, 0x85, 0xf1, 0xa1, 0x80, 0x40, 0xd5, 0xba, 0x67, 0x81, 0xda, 0xcd, 0x03, 0xea, 0x51,
/* (2^214)P */ 0x42, 0x50, 0xf0, 0xef, 0x37, 0x61, 0x72, 0x85, 0xe1, 0xf1, 0xff, 0x6f, 0x3d, 0xe8, 0x7b, 0x21, 0x5c, 0xe5, 0x50, 0x03, 0xde, 0x00, 0xc1, 0xf7, 0x3a, 0x55, 0x12, 0x1c, 0x9e, 0x1e, 0xce, 0xd1, 0x2f, 0xaf, 0x05, 0x70, 0x5b, 0x47, 0xf2, 0x04, 0x7a, 0x89, 0xbc, 0x78, 0xa6, 0x65, 0x6c, 0xaa, 0x3c, 0xa2, 0x3c, 0x8b, 0x5c, 0xa9, 0x22, 0x48,
/* (2^215)P */ 0x7e, 0x8c, 0x8f, 0x2f, 0x60, 0xe3, 0x5a, 0x94, 0xd4, 0xce, 0xdd, 0x9d, 0x83, 0x3b, 0x77, 0x78, 0x43, 0x1d, 0xfd, 0x8f, 0xc8, 0xe8, 0x02, 0x90, 0xab, 0xf6, 0xc9, 0xfc, 0xf1, 0x63, 0xaa, 0x5f, 0x42, 0xf1, 0x78, 0x34, 0x64, 0x16, 0x75, 0x9c, 0x7d, 0xd0, 0xe4, 0x74, 0x5a, 0xa8, 0xfb, 0xcb, 0xac, 0x20, 0xa3, 0xc2, 0xa6, 0x20, 0xf8, 0x1b,
/* (2^216)P */ 0x00, 0x4f, 0x1e, 0x56, 0xb5, 0x34, 0xb2, 0x87, 0x31, 0xe5, 0xee, 0x8d, 0xf1, 0x41, 0x67, 0xb7, 0x67, 0x3a, 0x54, 0x86, 0x5c, 0xf0, 0x0b, 0x37, 0x2f, 0x1b, 0x92, 0x5d, 0x58, 0x93, 0xdc, 0xd8, 0x58, 0xcc, 0x9e, 0x67, 0xd0, 0x97, 0x3a, 0xaf, 0x49, 0x39, 0x2d, 0x3b, 0xd8, 0x98, 0xfb, 0x76, 0x6b, 0xe7, 0xaf, 0xc3, 0x45, 0x44, 0x53, 0x94,
/* (2^217)P */ 0x30, 0xbd, 0x90, 0x75, 0xd3, 0xbd, 0x3b, 0x58, 0x27, 0x14, 0x9f, 0x6b, 0xd4, 0x31, 0x99, 0xcd, 0xde, 0x3a, 0x21, 0x1e, 0xb4, 0x02, 0xe4, 0x33, 0x04, 0x02, 0xb0, 0x50, 0x66, 0x68, 0x90, 0xdd, 0x7b, 0x69, 0x31, 0xd9, 0xcf, 0x68, 0x73, 0xf1, 0x60, 0xdd, 0xc8, 0x1d, 0x5d, 0xe3, 0xd6, 0x5b, 0x2a, 0xa4, 0xea, 0xc4, 0x3f, 0x08, 0xcd, 0x9c,
/* (2^218)P */ 0x6b, 0x1a, 0xbf, 0x55, 0xc1, 0x1b, 0x0c, 0x05, 0x09, 0xdf, 0xf5, 0x5e, 0xa3, 0x77, 0x95, 0xe9, 0xdf, 0x19, 0xdd, 0xc7, 0x94, 0xcb, 0x06, 0x73, 0xd0, 0x88, 0x02, 0x33, 0x94, 0xca, 0x7a, 0x2f, 0x8e, 0x3d, 0x72, 0x61, 0x2d, 0x4d, 0xa6, 0x61, 0x1f, 0x32, 0x5e, 0x87, 0x53, 0x36, 0x11, 0x15, 0x20, 0xb3, 0x5a, 0x57, 0x51, 0x93, 0x20, 0xd8,
/* (2^219)P */ 0xb7, 0x56, 0xf4, 0xab, 0x7d, 0x0c, 0xfb, 0x99, 0x1a, 0x30, 0x29, 0xb0, 0x75, 0x2a, 0xf8, 0x53, 0x71, 0x23, 0xbd, 0xa7, 0xd8, 0x0a, 0xe2, 0x27, 0x65, 0xe9, 0x74, 0x26, 0x98, 0x4a, 0x69, 0x19, 0xb2, 0x4d, 0x0a, 0x17, 0x98, 0xb2, 0xa9, 0x57, 0x4e, 0xf6, 0x86, 0xc8, 0x01, 0xa4, 0xc6, 0x98, 0xad, 0x5a, 0x90, 0x2c, 0x05, 0x46, 0x64, 0xb7,
/* (2^220)P */ 0x7b, 0x91, 0xdf, 0xfc, 0xf8, 0x1c, 0x8c, 0x15, 0x9e, 0xf7, 0xd5, 0xa8, 0xe8, 0xe7, 0xe3, 0xa3, 0xb0, 0x04, 0x74, 0xfa, 0x78, 0xfb, 0x26, 0xbf, 0x67, 0x42, 0xf9, 0x8c, 0x9b, 0xb4, 0x69, 0x5b, 0x02, 0x13, 0x6d, 0x09, 0x6c, 0xd6, 0x99, 0x61, 0x7b, 0x89, 0x4a, 0x67, 0x75, 0xa3, 0x98, 0x13, 0x23, 0x1d, 0x18, 0x24, 0x0e, 0xef, 0x41, 0x79,
/* (2^221)P */ 0x86, 0x33, 0xab, 0x08, 0xcb, 0xbf, 0x1e, 0x76, 0x3c, 0x0b, 0xbd, 0x30, 0xdb, 0xe9, 0xa3, 0x35, 0x87, 0x1b, 0xe9, 0x07, 0x00, 0x66, 0x7f, 0x3b, 0x35, 0x0c, 0x8a, 0x3f, 0x61, 0xbc, 0xe0, 0xae, 0xf6, 0xcc, 0x54, 0xe1, 0x72, 0x36, 0x2d, 0xee, 0x93, 0x24, 0xf8, 0xd7, 0xc5, 0xf9, 0xcb, 0xb0, 0xe5, 0x88, 0x0d, 0x23, 0x4b, 0x76, 0x15, 0xa2,
/* (2^222)P */ 0x37, 0xdb, 0x83, 0xd5, 0x6d, 0x06, 0x24, 0x37, 0x1b, 0x15, 0x85, 0x15, 0xe2, 0xc0, 0x4e, 0x02, 0xa9, 0x6d, 0x0a, 0x3a, 0x94, 0x4a, 0x6f, 0x49, 0x00, 0x01, 0x72, 0xbb, 0x60, 0x14, 0x35, 0xae, 0xb4, 0xc6, 0x01, 0x0a, 0x00, 0x9e, 0xc3, 0x58, 0xc5, 0xd1, 0x5e, 0x30, 0x73, 0x96, 0x24, 0x85, 0x9d, 0xf0, 0xf9, 0xec, 0x09, 0xd3, 0xe7, 0x70,
/* (2^223)P */ 0xf3, 0xbd, 0x96, 0x87, 0xe9, 0x71, 0xbd, 0xd6, 0xa2, 0x45, 0xeb, 0x0a, 0xcd, 0x2c, 0xf1, 0x72, 0xa6, 0x31, 0xa9, 0x6f, 0x09, 0xa1, 0x5e, 0xdd, 0xc8, 0x8d, 0x0d, 0xbc, 0x5a, 0x8d, 0xb1, 0x2c, 0x9a, 0xcc, 0x37, 0x74, 0xc2, 0xa9, 0x4e, 0xd6, 0xc0, 0x3c, 0xa0, 0x23, 0xb0, 0xa0, 0x77, 0x14, 0x80, 0x45, 0x71, 0x6a, 0x2d, 0x41, 0xc3, 0x82,
/* (2^224)P */ 0x37, 0x44, 0xec, 0x8a, 0x3e, 0xc1, 0x0c, 0xa9, 0x12, 0x9c, 0x08, 0x88, 0xcb, 0xd9, 0xf8, 0xba, 0x00, 0xd6, 0xc3, 0xdf, 0xef, 0x7a, 0x44, 0x7e, 0x25, 0x69, 0xc9, 0xc1, 0x46, 0xe5, 0x20, 0x9e, 0xcc, 0x0b, 0x05, 0x3e, 0xf4, 0x78, 0x43, 0x0c, 0xa6, 0x2f, 0xc1, 0xfa, 0x70, 0xb2, 0x3c, 0x31, 0x7a, 0x63, 0x58, 0xab, 0x17, 0xcf, 0x4c, 0x4f,
/* (2^225)P */ 0x2b, 0x08, 0x31, 0x59, 0x75, 0x8b, 0xec, 0x0a, 0xa9, 0x79, 0x70, 0xdd, 0xf1, 0x11, 0xc3, 0x11, 0x1f, 0xab, 0x37, 0xaa, 0x26, 0xea, 0x53, 0xc4, 0x79, 0xa7, 0x91, 0x00, 0xaa, 0x08, 0x42, 0xeb, 0x8b, 0x8b, 0xe8, 0xc3, 0x2f, 0xb8, 0x78, 0x90, 0x38, 0x0e, 0x8a, 0x42, 0x0c, 0x0f, 0xbf, 0x3e, 0xf8, 0xd8, 0x07, 0xcf, 0x6a, 0x34, 0xc9, 0xfa,
/* (2^226)P */ 0x11, 0xe0, 0x76, 0x4d, 0x23, 0xc5, 0xa6, 0xcc, 0x9f, 0x9a, 0x2a, 0xde, 0x3a, 0xb5, 0x92, 0x39, 0x19, 0x8a, 0xf1, 0x8d, 0xf9, 0x4d, 0xc9, 0xb4, 0x39, 0x9f, 0x57, 0xd8, 0x72, 0xab, 0x1d, 0x61, 0x6a, 0xb2, 0xff, 0x52, 0xba, 0x54, 0x0e, 0xfb, 0x83, 0x30, 0x8a, 0xf7, 0x3b, 0xf4, 0xd8, 0xae, 0x1a, 0x94, 0x3a, 0xec, 0x63, 0xfe, 0x6e, 0x7c,
/* (2^227)P */ 0xdc, 0x70, 0x8e, 0x55, 0x44, 0xbf, 0xd2, 0x6a, 0xa0, 0x14, 0x61, 0x89, 0xd5, 0x55, 0x45, 0x3c, 0xf6, 0x40, 0x0d, 0x83, 0x85, 0x44, 0xb4, 0x62, 0x56, 0xfe, 0x60, 0xd7, 0x07, 0x1d, 0x47, 0x30, 0x3b, 0x73, 0xa4, 0xb5, 0xb7, 0xea, 0xac, 0xda, 0xf1, 0x17, 0xaa, 0x60, 0xdf, 0xe9, 0x84, 0xda, 0x31, 0x32, 0x61, 0xbf, 0xd0, 0x7e, 0x8a, 0x02,
/* (2^228)P */ 0xb9, 0x51, 0xb3, 0x89, 0x21, 0x5d, 0xa2, 0xfe, 0x79, 0x2a, 0xb3, 0x2a, 0x3b, 0xe6, 0x6f, 0x2b, 0x22, 0x03, 0xea, 0x7b, 0x1f, 0xaf, 0x85, 0xc3, 0x38, 0x55, 0x5b, 0x8e, 0xb4, 0xaa, 0x77, 0xfe, 0x03, 0x6e, 0xda, 0x91, 0x24, 0x0c, 0x48, 0x39, 0x27, 0x43, 0x16, 0xd2, 0x0a, 0x0d, 0x43, 0xa3, 0x0e, 0xca, 0x45, 0xd1, 0x7f, 0xf5, 0xd3, 0x16,
/* (2^229)P */ 0x3d, 0x32, 0x9b, 0x38, 0xf8, 0x06, 0x93, 0x78, 0x5b, 0x50, 0x2b, 0x06, 0xd8, 0x66, 0xfe, 0xab, 0x9b, 0x58, 0xc7, 0xd1, 0x4d, 0xd5, 0xf8, 0x3b, 0x10, 0x7e, 0x85, 0xde, 0x58, 0x4e, 0xdf, 0x53, 0xd9, 0x58, 0xe0, 0x15, 0x81, 0x9f, 0x1a, 0x78, 0xfc, 0x9f, 0x10, 0xc2, 0x23, 0xd6, 0x78, 0xd1, 0x9d, 0xd2, 0xd5, 0x1c, 0x53, 0xe2, 0xc9, 0x76,
/* (2^230)P */ 0x98, 0x1e, 0x38, 0x7b, 0x71, 0x18, 0x4b, 0x15, 0xaf, 0xa1, 0xa6, 0x98, 0xcb, 0x26, 0xa3, 0xc8, 0x07, 0x46, 0xda, 0x3b, 0x70, 0x65, 0xec, 0x7a, 0x2b, 0x34, 0x94, 0xa8, 0xb6, 0x14, 0xf8, 0x1a, 0xce, 0xf7, 0xc8, 0x60, 0xf3, 0x88, 0xf4, 0x33, 0x60, 0x7b, 0xd1, 0x02, 0xe7, 0xda, 0x00, 0x4a, 0xea, 0xd2, 0xfd, 0x88, 0xd2, 0x99, 0x28, 0xf3,
/* (2^231)P */ 0x28, 0x24, 0x1d, 0x26, 0xc2, 0xeb, 0x8b, 0x3b, 0xb4, 0x6b, 0xbe, 0x6b, 0x77, 0xff, 0xf3, 0x21, 0x3b, 0x26, 0x6a, 0x8c, 0x8e, 0x2a, 0x44, 0xa8, 0x01, 0x2b, 0x71, 0xea, 0x64, 0x30, 0xfd, 0xfd, 0x95, 0xcb, 0x39, 0x38, 0x48, 0xfa, 0x96, 0x97, 0x8c, 0x2f, 0x33, 0xca, 0x03, 0xe6, 0xd7, 0x94, 0x55, 0x6c, 0xc3, 0xb3, 0xa8, 0xf7, 0xae, 0x8c,
/* (2^232)P */ 0xea, 0x62, 0x8a, 0xb4, 0xeb, 0x74, 0xf7, 0xb8, 0xae, 0xc5, 0x20, 0x71, 0x06, 0xd6, 0x7c, 0x62, 0x9b, 0x69, 0x74, 0xef, 0xa7, 0x6d, 0xd6, 0x8c, 0x37, 0xb9, 0xbf, 0xcf, 0xeb, 0xe4, 0x2f, 0x04, 0x02, 0x21, 0x7d, 0x75, 0x6b, 0x92, 0x48, 0xf8, 0x70, 0xad, 0x69, 0xe2, 0xea, 0x0e, 0x88, 0x67, 0x72, 0xcc, 0x2d, 0x10, 0xce, 0x2d, 0xcf, 0x65,
/* (2^233)P */ 0x49, 0xf3, 0x57, 0x64, 0xe5, 0x5c, 0xc5, 0x65, 0x49, 0x97, 0xc4, 0x8a, 0xcc, 0xa9, 0xca, 0x94, 0x7b, 0x86, 0x88, 0xb6, 0x51, 0x27, 0x69, 0xa5, 0x0f, 0x8b, 0x06, 0x59, 0xa0, 0x94, 0xef, 0x63, 0x1a, 0x01, 0x9e, 0x4f, 0xd2, 0x5a, 0x93, 0xc0, 0x7c, 0xe6, 0x61, 0x77, 0xb6, 0xf5, 0x40, 0xd9, 0x98, 0x43, 0x5b, 0x56, 0x68, 0xe9, 0x37, 0x8f,
/* (2^234)P */ 0xee, 0x87, 0xd2, 0x05, 0x1b, 0x39, 0x89, 0x10, 0x07, 0x6d, 0xe8, 0xfd, 0x8b, 0x4d, 0xb2, 0xa7, 0x7b, 0x1e, 0xa0, 0x6c, 0x0d, 0x3d, 0x3d, 0x49, 0xba, 0x61, 0x36, 0x1f, 0xc2, 0x84, 0x4a, 0xcc, 0x87, 0xa9, 0x1b, 0x23, 0x04, 0xe2, 0x3e, 0x97, 0xe1, 0xdb, 0xd5, 0x5a, 0xe8, 0x41, 0x6b, 0xe5, 0x5a, 0xa1, 0x99, 0xe5, 0x7b, 0xa7, 0xe0, 0x3b,
/* (2^235)P */ 0xea, 0xa3, 0x6a, 0xdd, 0x77, 0x7f, 0x77, 0x41, 0xc5, 0x6a, 0xe4, 0xaf, 0x11, 0x5f, 0x88, 0xa5, 0x10, 0xee, 0xd0, 0x8c, 0x0c, 0xb4, 0xa5, 0x2a, 0xd0, 0xd8, 0x1d, 0x47, 0x06, 0xc0, 0xd5, 0xce, 0x51, 0x54, 0x9b, 0x2b, 0xe6, 0x2f, 0xe7, 0xe7, 0x31, 0x5f, 0x5c, 0x23, 0x81, 0x3e, 0x03, 0x93, 0xaa, 0x2d, 0x71, 0x84, 0xa0, 0x89, 0x32, 0xa6,
/* (2^236)P */ 0x55, 0xa3, 0x13, 0x92, 0x4e, 0x93, 0x7d, 0xec, 0xca, 0x57, 0xfb, 0x37, 0xae, 0xd2, 0x18, 0x2e, 0x54, 0x05, 0x6c, 0xd1, 0x28, 0xca, 0x90, 0x40, 0x82, 0x2e, 0x79, 0xc6, 0x5a, 0xc7, 0xdd, 0x84, 0x93, 0xdf, 0x15, 0xb8, 0x1f, 0xb1, 0xf9, 0xaf, 0x2c, 0xe5, 0x32, 0xcd, 0xc2, 0x99, 0x6d, 0xac, 0x85, 0x5c, 0x63, 0xd3, 0xe2, 0xff, 0x24, 0xda,
/* (2^237)P */ 0x2d, 0x8d, 0xfd, 0x65, 0xcc, 0xe5, 0x02, 0xa0, 0xe5, 0xb9, 0xec, 0x59, 0x09, 0x50, 0x27, 0xb7, 0x3d, 0x2a, 0x79, 0xb2, 0x76, 0x5d, 0x64, 0x95, 0xf8, 0xc5, 0xaf, 0x8a, 0x62, 0x11, 0x5c, 0x56, 0x1c, 0x05, 0x64, 0x9e, 0x5e, 0xbd, 0x54, 0x04, 0xe6, 0x9e, 0xab, 0xe6, 0x22, 0x7e, 0x42, 0x54, 0xb5, 0xa5, 0xd0, 0x8d, 0x28, 0x6b, 0x0f, 0x0b,
/* (2^238)P */ 0x2d, 0xb2, 0x8c, 0x59, 0x10, 0x37, 0x84, 0x3b, 0x9b, 0x65, 0x1b, 0x0f, 0x10, 0xf9, 0xea, 0x60, 0x1b, 0x02, 0xf5, 0xee, 0x8b, 0xe6, 0x32, 0x7d, 0x10, 0x7f, 0x5f, 0x8c, 0x72, 0x09, 0x4e, 0x1f, 0x29, 0xff, 0x65, 0xcb, 0x3e, 0x3a, 0xd2, 0x96, 0x50, 0x1e, 0xea, 0x64, 0x99, 0xb5, 0x4c, 0x7a, 0x69, 0xb8, 0x95, 0xae, 0x48, 0xc0, 0x7c, 0xb1,
/* (2^239)P */ 0xcd, 0x7c, 0x4f, 0x3e, 0xea, 0xf3, 0x90, 0xcb, 0x12, 0x76, 0xd1, 0x17, 0xdc, 0x0d, 0x13, 0x0f, 0xfd, 0x4d, 0xb5, 0x1f, 0xe4, 0xdd, 0xf2, 0x4d, 0x58, 0xea, 0xa5, 0x66, 0x92, 0xcf, 0xe5, 0x54, 0xea, 0x9b, 0x35, 0x83, 0x1a, 0x44, 0x8e, 0x62, 0x73, 0x45, 0x98, 0xa3, 0x89, 0x95, 0x52, 0x93, 0x1a, 0x8d, 0x63, 0x0f, 0xc2, 0x57, 0x3c, 0xb1,
/* (2^240)P */ 0x72, 0xb4, 0xdf, 0x51, 0xb7, 0xf6, 0x52, 0xa2, 0x14, 0x56, 0xe5, 0x0a, 0x2e, 0x75, 0x81, 0x02, 0xee, 0x93, 0x48, 0x0a, 0x92, 0x4e, 0x0c, 0x0f, 0xdf, 0x09, 0x89, 0x99, 0xf6, 0xf9, 0x22, 0xa2, 0x32, 0xf8, 0xb0, 0x76, 0x0c, 0xb2, 0x4d, 0x6e, 0xbe, 0x83, 0x35, 0x61, 0x44, 0xd2, 0x58, 0xc7, 0xdd, 0x14, 0xcf, 0xc3, 0x4b, 0x7c, 0x07, 0xee,
/* (2^241)P */ 0x8b, 0x03, 0xee, 0xcb, 0xa7, 0x2e, 0x28, 0xbd, 0x97, 0xd1, 0x4c, 0x2b, 0xd1, 0x92, 0x67, 0x5b, 0x5a, 0x12, 0xbf, 0x29, 0x17, 0xfc, 0x50, 0x09, 0x74, 0x76, 0xa2, 0xd4, 0x82, 0xfd, 0x2c, 0x0c, 0x90, 0xf7, 0xe7, 0xe5, 0x9a, 0x2c, 0x16, 0x40, 0xb9, 0x6c, 0xd9, 0xe0, 0x22, 0x9e, 0xf8, 0xdd, 0x73, 0xe4, 0x7b, 0x9e, 0xbe, 0x4f, 0x66, 0x22,
/* (2^242)P */ 0xa4, 0x10, 0xbe, 0xb8, 0x83, 0x3a, 0x77, 0x8e, 0xea, 0x0a, 0xc4, 0x97, 0x3e, 0xb6, 0x6c, 0x81, 0xd7, 0x65, 0xd9, 0xf7, 0xae, 0xe6, 0xbe, 0xab, 0x59, 0x81, 0x29, 0x4b, 0xff, 0xe1, 0x0f, 0xc3, 0x2b, 0xad, 0x4b, 0xef, 0xc4, 0x50, 0x9f, 0x88, 0x31, 0xf2, 0xde, 0x80, 0xd6, 0xf4, 0x20, 0x9c, 0x77, 0x9b, 0xbe, 0xbe, 0x08, 0xf5, 0xf0, 0x95,
/* (2^243)P */ 0x0e, 0x7c, 0x7b, 0x7c, 0xb3, 0xd8, 0x83, 0xfc, 0x8c, 0x75, 0x51, 0x74, 0x1b, 0xe1, 0x6d, 0x11, 0x05, 0x46, 0x24, 0x0d, 0xa4, 0x2b, 0x32, 0xfd, 0x2c, 0x4e, 0x21, 0xdf, 0x39, 0x6b, 0x96, 0xfc, 0xff, 0x92, 0xfc, 0x35, 0x0d, 0x9a, 0x4b, 0xc0, 0x70, 0x46, 0x32, 0x7d, 0xc0, 0xc4, 0x04, 0xe0, 0x2d, 0x83, 0xa7, 0x00, 0xc7, 0xcb, 0xb4, 0x8f,
/* (2^244)P */ 0xa9, 0x5a, 0x7f, 0x0e, 0xdd, 0x2c, 0x85, 0xaa, 0x4d, 0xac, 0xde, 0xb3, 0xb6, 0xaf, 0xe6, 0xd1, 0x06, 0x7b, 0x2c, 0xa4, 0x01, 0x19, 0x22, 0x7d, 0x78, 0xf0, 0x3a, 0xea, 0x89, 0xfe, 0x21, 0x61, 0x6d, 0xb8, 0xfe, 0xa5, 0x2a, 0xab, 0x0d, 0x7b, 0x51, 0x39, 0xb6, 0xde, 0xbc, 0xf0, 0xc5, 0x48, 0xd7, 0x09, 0x82, 0x6e, 0x66, 0x75, 0xc5, 0xcd,
/* (2^245)P */ 0xee, 0xdf, 0x2b, 0x6c, 0xa8, 0xde, 0x61, 0xe1, 0x27, 0xfa, 0x2a, 0x0f, 0x68, 0xe7, 0x7a, 0x9b, 0x13, 0xe9, 0x56, 0xd2, 0x1c, 0x3d, 0x2f, 0x3c, 0x7a, 0xf6, 0x6f, 0x45, 0xee, 0xe8, 0xf4, 0xa0, 0xa6, 0xe8, 0xa5, 0x27, 0xee, 0xf2, 0x85, 0xa9, 0xd5, 0x0e, 0xa9, 0x26, 0x60, 0xfe, 0xee, 0xc7, 0x59, 0x99, 0x5e, 0xa3, 0xdf, 0x23, 0x36, 0xd5,
/* (2^246)P */ 0x15, 0x66, 0x6f, 0xd5, 0x78, 0xa4, 0x0a, 0xf7, 0xb1, 0xe8, 0x75, 0x6b, 0x48, 0x7d, 0xa6, 0x4d, 0x3d, 0x36, 0x9b, 0xc7, 0xcc, 0x68, 0x9a, 0xfe, 0x2f, 0x39, 0x2a, 0x51, 0x31, 0x39, 0x7d, 0x73, 0x6f, 0xc8, 0x74, 0x72, 0x6f, 0x6e, 0xda, 0x5f, 0xad, 0x48, 0xc8, 0x40, 0xe1, 0x06, 0x01, 0x36, 0xa1, 0x88, 0xc8, 0x99, 0x9c, 0xd1, 0x11, 0x8f,
/* (2^247)P */ 0xab, 0xc5, 0xcb, 0xcf, 0xbd, 0x73, 0x21, 0xd0, 0x82, 0xb1, 0x2e, 0x2d, 0xd4, 0x36, 0x1b, 0xed, 0xa9, 0x8a, 0x26, 0x79, 0xc4, 0x17, 0xae, 0xe5, 0x09, 0x0a, 0x0c, 0xa4, 0x21, 0xa0, 0x6e, 0xdd, 0x62, 0x8e, 0x44, 0x62, 0xcc, 0x50, 0xff, 0x93, 0xb3, 0x9a, 0x72, 0x8c, 0x3f, 0xa1, 0xa6, 0x4d, 0x87, 0xd5, 0x1c, 0x5a, 0xc0, 0x0b, 0x1a, 0xd6,
/* (2^248)P */ 0x67, 0x36, 0x6a, 0x1f, 0x96, 0xe5, 0x80, 0x20, 0xa9, 0xe8, 0x0b, 0x0e, 0x21, 0x29, 0x3f, 0xc8, 0x0a, 0x6d, 0x27, 0x47, 0xca, 0xd9, 0x05, 0x55, 0xbf, 0x11, 0xcf, 0x31, 0x7a, 0x37, 0xc7, 0x90, 0xa9, 0xf4, 0x07, 0x5e, 0xd5, 0xc3, 0x92, 0xaa, 0x95, 0xc8, 0x23, 0x2a, 0x53, 0x45, 0xe3, 0x3a, 0x24, 0xe9, 0x67, 0x97, 0x3a, 0x82, 0xf9, 0xa6,
/* (2^249)P */ 0x92, 0x9e, 0x6d, 0x82, 0x67, 0xe9, 0xf9, 0x17, 0x96, 0x2c, 0xa7, 0xd3, 0x89, 0xf9, 0xdb, 0xd8, 0x20, 0xc6, 0x2e, 0xec, 0x4a, 0x76, 0x64, 0xbf, 0x27, 0x40, 0xe2, 0xb4, 0xdf, 0x1f, 0xa0, 0xef, 0x07, 0x80, 0xfb, 0x8e, 0x12, 0xf8, 0xb8, 0xe1, 0xc6, 0xdf, 0x7c, 0x69, 0x35, 0x5a, 0xe1, 0x8e, 0x5d, 0x69, 0x84, 0x56, 0xb6, 0x31, 0x1c, 0x0b,
/* (2^250)P */ 0xd6, 0x94, 0x5c, 0xef, 0xbb, 0x46, 0x45, 0x44, 0x5b, 0xa1, 0xae, 0x03, 0x65, 0xdd, 0xb5, 0x66, 0x88, 0x35, 0x29, 0x95, 0x16, 0x54, 0xa6, 0xf5, 0xc9, 0x78, 0x34, 0xe6, 0x0f, 0xc4, 0x2b, 0x5b, 0x79, 0x51, 0x68, 0x48, 0x3a, 0x26, 0x87, 0x05, 0x70, 0xaf, 0x8b, 0xa6, 0xc7, 0x2e, 0xb3, 0xa9, 0x10, 0x01, 0xb0, 0xb9, 0x31, 0xfd, 0xdc, 0x80,
/* (2^251)P */ 0x25, 0xf2, 0xad, 0xd6, 0x75, 0xa3, 0x04, 0x05, 0x64, 0x8a, 0x97, 0x60, 0x27, 0x2a, 0xe5, 0x6d, 0xb0, 0x73, 0xf4, 0x07, 0x2a, 0x9d, 0xe9, 0x46, 0xb4, 0x1c, 0x51, 0xf8, 0x63, 0x98, 0x7e, 0xe5, 0x13, 0x51, 0xed, 0x98, 0x65, 0x98, 0x4f, 0x8f, 0xe7, 0x7e, 0x72, 0xd7, 0x64, 0x11, 0x2f, 0xcd, 0x12, 0xf8, 0xc4, 0x63, 0x52, 0x0f, 0x7f, 0xc4,
/* (2^252)P */ 0x5c, 0xd9, 0x85, 0x63, 0xc7, 0x8a, 0x65, 0x9a, 0x25, 0x83, 0x31, 0x73, 0x49, 0xf0, 0x93, 0x96, 0x70, 0x67, 0x6d, 0xb1, 0xff, 0x95, 0x54, 0xe4, 0xf8, 0x15, 0x6c, 0x5f, 0xbd, 0xf6, 0x0f, 0x38, 0x7b, 0x68, 0x7d, 0xd9, 0x3d, 0xf0, 0xa9, 0xa0, 0xe4, 0xd1, 0xb6, 0x34, 0x6d, 0x14, 0x16, 0xc2, 0x4c, 0x30, 0x0e, 0x67, 0xd3, 0xbe, 0x2e, 0xc0,
/* (2^253)P */ 0x06, 0x6b, 0x52, 0xc8, 0x14, 0xcd, 0xae, 0x03, 0x93, 0xea, 0xc1, 0xf2, 0xf6, 0x8b, 0xc5, 0xb6, 0xdc, 0x82, 0x42, 0x29, 0x94, 0xe0, 0x25, 0x6c, 0x3f, 0x9f, 0x5d, 0xe4, 0x96, 0xf6, 0x8e, 0x3f, 0xf9, 0x72, 0xc4, 0x77, 0x60, 0x8b, 0xa4, 0xf9, 0xa8, 0xc3, 0x0a, 0x81, 0xb1, 0x97, 0x70, 0x18, 0xab, 0xea, 0x37, 0x8a, 0x08, 0xc7, 0xe2, 0x95,
/* (2^254)P */ 0x94, 0x49, 0xd9, 0x5f, 0x76, 0x72, 0x82, 0xad, 0x2d, 0x50, 0x1a, 0x7a, 0x5b, 0xe6, 0x95, 0x1e, 0x95, 0x65, 0x87, 0x1c, 0x52, 0xd7, 0x44, 0xe6, 0x9b, 0x56, 0xcd, 0x6f, 0x05, 0xff, 0x67, 0xc5, 0xdb, 0xa2, 0xac, 0xe4, 0xa2, 0x28, 0x63, 0x5f, 0xfb, 0x0c, 0x3b, 0xf1, 0x87, 0xc3, 0x36, 0x78, 0x3f, 0x77, 0xfa, 0x50, 0x85, 0xf9, 0xd7, 0x82,
/* (2^255)P */ 0x64, 0xc0, 0xe0, 0xd8, 0x2d, 0xed, 0xcb, 0x6a, 0xfd, 0xcd, 0xbc, 0x7e, 0x9f, 0xc8, 0x85, 0xe9, 0xc1, 0x7c, 0x0f, 0xe5, 0x18, 0xea, 0xd4, 0x51, 0xad, 0x59, 0x13, 0x75, 0xd9, 0x3d, 0xd4, 0x8a, 0xb2, 0xbe, 0x78, 0x52, 0x2b, 0x52, 0x94, 0x37, 0x41, 0xd6, 0xb4, 0xb6, 0x45, 0x20, 0x76, 0xe0, 0x1f, 0x31, 0xdb, 0xb1, 0xa1, 0x43, 0xf0, 0x18,
/* (2^256)P */ 0x74, 0xa9, 0xa4, 0xa9, 0xdd, 0x6e, 0x3e, 0x68, 0xe5, 0xc3, 0x2e, 0x92, 0x17, 0xa4, 0xcb, 0x80, 0xb1, 0xf0, 0x06, 0x93, 0xef, 0xe6, 0x00, 0xe6, 0x3b, 0xb1, 0x32, 0x65, 0x7b, 0x83, 0xb6, 0x8a, 0x49, 0x1b, 0x14, 0x89, 0xee, 0xba, 0xf5, 0x6a, 0x8d, 0x36, 0xef, 0xb0, 0xd8, 0xb2, 0x16, 0x99, 0x17, 0x35, 0x02, 0x16, 0x55, 0x58, 0xdd, 0x82,
/* (2^257)P */ 0x36, 0x95, 0xe8, 0xf4, 0x36, 0x42, 0xbb, 0xc5, 0x3e, 0xfa, 0x30, 0x84, 0x9e, 0x59, 0xfd, 0xd2, 0x95, 0x42, 0xf8, 0x64, 0xd9, 0xb9, 0x0e, 0x9f, 0xfa, 0xd0, 0x7b, 0x20, 0x31, 0x77, 0x48, 0x29, 0x4d, 0xd0, 0x32, 0x57, 0x56, 0x30, 0xa6, 0x17, 0x53, 0x04, 0xbf, 0x08, 0x28, 0xec, 0xb8, 0x46, 0xc1, 0x03, 0x89, 0xdc, 0xed, 0xa0, 0x35, 0x53,
/* (2^258)P */ 0xc5, 0x7f, 0x9e, 0xd8, 0xc5, 0xba, 0x5f, 0x68, 0xc8, 0x23, 0x75, 0xea, 0x0d, 0xd9, 0x5a, 0xfd, 0x61, 0x1a, 0xa3, 0x2e, 0x45, 0x63, 0x14, 0x55, 0x86, 0x21, 0x29, 0xbe, 0xef, 0x5e, 0x50, 0xe5, 0x18, 0x59, 0xe7, 0xe3, 0xce, 0x4d, 0x8c, 0x15, 0x8f, 0x89, 0x66, 0x44, 0x52, 0x3d, 0xfa, 0xc7, 0x9a, 0x59, 0x90, 0x8e, 0xc0, 0x06, 0x3f, 0xc9,
/* (2^259)P */ 0x8e, 0x04, 0xd9, 0x16, 0x50, 0x1d, 0x8c, 0x9f, 0xd5, 0xe3, 0xce, 0xfd, 0x47, 0x04, 0x27, 0x4d, 0xc2, 0xfa, 0x71, 0xd9, 0x0b, 0xb8, 0x65, 0xf4, 0x11, 0xf3, 0x08, 0xee, 0x81, 0xc8, 0x67, 0x99, 0x0b, 0x8d, 0x77, 0xa3, 0x4f, 0xb5, 0x9b, 0xdb, 0x26, 0xf1, 0x97, 0xeb, 0x04, 0x54, 0xeb, 0x80, 0x08, 0x1d, 0x1d, 0xf6, 0x3d, 0x1f, 0x5a, 0xb8,
/* (2^260)P */ 0xb7, 0x9c, 0x9d, 0xee, 0xb9, 0x5c, 0xad, 0x0d, 0x9e, 0xfd, 0x60, 0x3c, 0x27, 0x4e, 0xa2, 0x95, 0xfb, 0x64, 0x7e, 0x79, 0x64, 0x87, 0x10, 0xb4, 0x73, 0xe0, 0x9d, 0x46, 0x4d, 0x3d, 0xee, 0x83, 0xe4, 0x16, 0x88, 0x97, 0xe6, 0x4d, 0xba, 0x70, 0xb6, 0x96, 0x7b, 0xff, 0x4b, 0xc8, 0xcf, 0x72, 0x83, 0x3e, 0x5b, 0x24, 0x2e, 0x57, 0xf1, 0x82,
/* (2^261)P */ 0x30, 0x71, 0x40, 0x51, 0x4f, 0x44, 0xbb, 0xc7, 0xf0, 0x54, 0x6e, 0x9d, 0xeb, 0x15, 0xad, 0xf8, 0x61, 0x43, 0x5a, 0xef, 0xc0, 0xb1, 0x57, 0xae, 0x03, 0x40, 0xe8, 0x68, 0x6f, 0x03, 0x20, 0x4f, 0x8a, 0x51, 0x2a, 0x9e, 0xd2, 0x45, 0xaf, 0xb4, 0xf5, 0xd4, 0x95, 0x7f, 0x3d, 0x3d, 0xb7, 0xb6, 0x28, 0xc5, 0x08, 0x8b, 0x44, 0xd6, 0x3f, 0xe7,
/* (2^262)P */ 0xa9, 0x52, 0x04, 0x67, 0xcb, 0x20, 0x63, 0xf8, 0x18, 0x01, 0x44, 0x21, 0x6a, 0x8a, 0x83, 0x48, 0xd4, 0xaf, 0x23, 0x0f, 0x35, 0x8d, 0xe5, 0x5a, 0xc4, 0x7c, 0x55, 0x46, 0x19, 0x5f, 0x35, 0xe0, 0x5d, 0x97, 0x4c, 0x2d, 0x04, 0xed, 0x59, 0xd4, 0xb0, 0xb2, 0xc6, 0xe3, 0x51, 0xe1, 0x38, 0xc6, 0x30, 0x49, 0x8f, 0xae, 0x61, 0x64, 0xce, 0xa8,
/* (2^263)P */ 0x9b, 0x64, 0x83, 0x3c, 0xd3, 0xdf, 0xb9, 0x27, 0xe7, 0x5b, 0x7f, 0xeb, 0xf3, 0x26, 0xcf, 0xb1, 0x8f, 0xaf, 0x26, 0xc8, 0x48, 0xce, 0xa1, 0xac, 0x7d, 0x10, 0x34, 0x28, 0xe1, 0x1f, 0x69, 0x03, 0x64, 0x77, 0x61, 0xdd, 0x4a, 0x9b, 0x18, 0x47, 0xf8, 0xca, 0x63, 0xc9, 0x03, 0x2d, 0x20, 0x2a, 0x69, 0x6e, 0x42, 0xd0, 0xe7, 0xaa, 0xb5, 0xf3,
/* (2^264)P */ 0xea, 0x31, 0x0c, 0x57, 0x0f, 0x3e, 0xe3, 0x35, 0xd8, 0x30, 0xa5, 0x6f, 0xdd, 0x95, 0x43, 0xc6, 0x66, 0x07, 0x4f, 0x34, 0xc3, 0x7e, 0x04, 0x10, 0x2d, 0xc4, 0x1c, 0x94, 0x52, 0x2e, 0x5b, 0x9a, 0x65, 0x2f, 0x91, 0xaa, 0x4f, 0x3c, 0xdc, 0x23, 0x18, 0xe1, 0x4f, 0x85, 0xcd, 0xf4, 0x8c, 0x51, 0xf7, 0xab, 0x4f, 0xdc, 0x15, 0x5c, 0x9e, 0xc5,
/* (2^265)P */ 0x54, 0x57, 0x23, 0x17, 0xe7, 0x82, 0x2f, 0x04, 0x7d, 0xfe, 0xe7, 0x1f, 0xa2, 0x57, 0x79, 0xe9, 0x58, 0x9b, 0xbe, 0xc6, 0x16, 0x4a, 0x17, 0x50, 0x90, 0x4a, 0x34, 0x70, 0x87, 0x37, 0x01, 0x26, 0xd8, 0xa3, 0x5f, 0x07, 0x7c, 0xd0, 0x7d, 0x05, 0x8a, 0x93, 0x51, 0x2f, 0x99, 0xea, 0xcf, 0x00, 0xd8, 0xc7, 0xe6, 0x9b, 0x8c, 0x62, 0x45, 0x87,
/* (2^266)P */ 0xc3, 0xfd, 0x29, 0x66, 0xe7, 0x30, 0x29, 0x77, 0xe0, 0x0d, 0x63, 0x5b, 0xe6, 0x90, 0x1a, 0x1e, 0x99, 0xc2, 0xa7, 0xab, 0xff, 0xa7, 0xbd, 0x79, 0x01, 0x97, 0xfd, 0x27, 0x1b, 0x43, 0x2b, 0xe6, 0xfe, 0x5e, 0xf1, 0xb9, 0x35, 0x38, 0x08, 0x25, 0x55, 0x90, 0x68, 0x2e, 0xc3, 0x67, 0x39, 0x9f, 0x2b, 0x2c, 0x70, 0x48, 0x8c, 0x47, 0xee, 0x56,
/* (2^267)P */ 0xf7, 0x32, 0x70, 0xb5, 0xe6, 0x42, 0xfd, 0x0a, 0x39, 0x9b, 0x07, 0xfe, 0x0e, 0xf4, 0x47, 0xba, 0x6a, 0x3f, 0xf5, 0x2c, 0x15, 0xf3, 0x60, 0x3f, 0xb1, 0x83, 0x7b, 0x2e, 0x34, 0x58, 0x1a, 0x6e, 0x4a, 0x49, 0x05, 0x45, 0xca, 0xdb, 0x00, 0x01, 0x0c, 0x42, 0x5e, 0x60, 0x40, 0x5f, 0xd9, 0xc7, 0x3a, 0x9e, 0x1c, 0x8d, 0xab, 0x11, 0x55, 0x65,
/* (2^268)P */ 0x87, 0x40, 0xb7, 0x0d, 0xaa, 0x34, 0x89, 0x90, 0x75, 0x6d, 0xa2, 0xfe, 0x3b, 0x6d, 0x5c, 0x39, 0x98, 0x10, 0x9e, 0x15, 0xc5, 0x35, 0xa2, 0x27, 0x23, 0x0a, 0x2d, 0x60, 0xe2, 0xa8, 0x7f, 0x3e, 0x77, 0x8f, 0xcc, 0x44, 0xcc, 0x30, 0x28, 0xe2, 0xf0, 0x04, 0x8c, 0xee, 0xe4, 0x5f, 0x68, 0x8c, 0xdf, 0x70, 0xbf, 0x31, 0xee, 0x2a, 0xfc, 0xce,
/* (2^269)P */ 0x92, 0xf2, 0xa0, 0xd9, 0x58, 0x3b, 0x7c, 0x1a, 0x99, 0x46, 0x59, 0x54, 0x60, 0x06, 0x8d, 0x5e, 0xf0, 0x22, 0xa1, 0xed, 0x92, 0x8a, 0x4d, 0x76, 0x95, 0x05, 0x0b, 0xff, 0xfc, 0x9a, 0xd1, 0xcc, 0x05, 0xb9, 0x5e, 0x99, 0xe8, 0x2a, 0x76, 0x7b, 0xfd, 0xa6, 0xe2, 0xd1, 0x1a, 0xd6, 0x76, 0x9f, 0x2f, 0x0e, 0xd1, 0xa8, 0x77, 0x5a, 0x40, 0x5a,
/* (2^270)P */ 0xff, 0xf9, 0x3f, 0xa9, 0xa6, 0x6c, 0x6d, 0x03, 0x8b, 0xa7, 0x10, 0x5d, 0x3f, 0xec, 0x3e, 0x1c, 0x0b, 0x6b, 0xa2, 0x6a, 0x22, 0xa9, 0x28, 0xd0, 0x66, 0xc9, 0xc2, 0x3d, 0x47, 0x20, 0x7d, 0xa6, 0x1d, 0xd8, 0x25, 0xb5, 0xf2, 0xf9, 0x70, 0x19, 0x6b, 0xf8, 0x43, 0x36, 0xc5, 0x1f, 0xe4, 0x5a, 0x4c, 0x13, 0xe4, 0x6d, 0x08, 0x0b, 0x1d, 0xb1,
/* (2^271)P */ 0x3f, 0x20, 0x9b, 0xfb, 0xec, 0x7d, 0x31, 0xc5, 0xfc, 0x88, 0x0b, 0x30, 0xed, 0x36, 0xc0, 0x63, 0xb1, 0x7d, 0x10, 0xda, 0xb6, 0x2e, 0xad, 0xf3, 0xec, 0x94, 0xe7, 0xec, 0xb5, 0x9c, 0xfe, 0xf5, 0x35, 0xf0, 0xa2, 0x2d, 0x7f, 0xca, 0x6b, 0x67, 0x1a, 0xf6, 0xb3, 0xda, 0x09, 0x2a, 0xaa, 0xdf, 0xb1, 0xca, 0x9b, 0xfb, 0xeb, 0xb3, 0xcd, 0xc0,
/* (2^272)P */ 0xcd, 0x4d, 0x89, 0x00, 0xa4, 0x3b, 0x48, 0xf0, 0x76, 0x91, 0x35, 0xa5, 0xf8, 0xc9, 0xb6, 0x46, 0xbc, 0xf6, 0x9a, 0x45, 0x47, 0x17, 0x96, 0x80, 0x5b, 0x3a, 0x28, 0x33, 0xf9, 0x5a, 0xef, 0x43, 0x07, 0xfe, 0x3b, 0xf4, 0x8e, 0x19, 0xce, 0xd2, 0x94, 0x4b, 0x6d, 0x8e, 0x67, 0x20, 0xc7, 0x4f, 0x2f, 0x59, 0x8e, 0xe1, 0xa1, 0xa9, 0xf9, 0x0e,
/* (2^273)P */ 0xdc, 0x7b, 0xb5, 0x50, 0x2e, 0xe9, 0x7e, 0x8b, 0x78, 0xa1, 0x38, 0x96, 0x22, 0xc3, 0x61, 0x67, 0x6d, 0xc8, 0x58, 0xed, 0x41, 0x1d, 0x5d, 0x86, 0x98, 0x7f, 0x2f, 0x1b, 0x8d, 0x3e, 0xaa, 0xc1, 0xd2, 0x0a, 0xf3, 0xbf, 0x95, 0x04, 0xf3, 0x10, 0x3c, 0x2b, 0x7f, 0x90, 0x46, 0x04, 0xaa, 0x6a, 0xa9, 0x35, 0x76, 0xac, 0x49, 0xb5, 0x00, 0x45,
/* (2^274)P */ 0xb1, 0x93, 0x79, 0x84, 0x4a, 0x2a, 0x30, 0x78, 0x16, 0xaa, 0xc5, 0x74, 0x06, 0xce, 0xa5, 0xa7, 0x32, 0x86, 0xe0, 0xf9, 0x10, 0xd2, 0x58, 0x76, 0xfb, 0x66, 0x49, 0x76, 0x3a, 0x90, 0xba, 0xb5, 0xcc, 0x99, 0xcd, 0x09, 0xc1, 0x9a, 0x74, 0x23, 0xdf, 0x0c, 0xfe, 0x99, 0x52, 0x80, 0xa3, 0x7c, 0x1c, 0x71, 0x5f, 0x2c, 0x49, 0x57, 0xf4, 0xf9,
/* (2^275)P */ 0x6d, 0xbf, 0x52, 0xe6, 0x25, 0x98, 0xed, 0xcf, 0xe3, 0xbc, 0x08, 0xa2, 0x1a, 0x90, 0xae, 0xa0, 0xbf, 0x07, 0x15, 0xad, 0x0a, 0x9f, 0x3e, 0x47, 0x44, 0xc2, 0x10, 0x46, 0xa6, 0x7a, 0x9e, 0x2f, 0x57, 0xbc, 0xe2, 0xf0, 0x1d, 0xd6, 0x9a, 0x06, 0xed, 0xfc, 0x54, 0x95, 0x92, 0x15, 0xa2, 0xf7, 0x8d, 0x6b, 0xef, 0xb2, 0x05, 0xed, 0x5c, 0x63,
/* (2^276)P */ 0xbc, 0x0b, 0x27, 0x3a, 0x3a, 0xf8, 0xe1, 0x48, 0x02, 0x7e, 0x27, 0xe6, 0x81, 0x62, 0x07, 0x73, 0x74, 0xe5, 0x52, 0xd7, 0xf8, 0x26, 0xca, 0x93, 0x4d, 0x3e, 0x9b, 0x55, 0x09, 0x8e, 0xe3, 0xd7, 0xa6, 0xe3, 0xb6, 0x2a, 0xa9, 0xb3, 0xb0, 0xa0, 0x8c, 0x01, 0xbb, 0x07, 0x90, 0x78, 0x6d, 0x6d, 0xe9, 0xf0, 0x7a, 0x90, 0xbd, 0xdc, 0x0c, 0x36,
/* (2^277)P */ 0x7f, 0x20, 0x12, 0x0f, 0x40, 0x00, 0x53, 0xd8, 0x0c, 0x27, 0x47, 0x47, 0x22, 0x80, 0xfb, 0x62, 0xe4, 0xa7, 0xf7, 0xbd, 0x42, 0xa5, 0xc3, 0x2b, 0xb2, 0x7f, 0x50, 0xcc, 0xe2, 0xfb, 0xd5, 0xc0, 0x63, 0xdd, 0x24, 0x5f, 0x7c, 0x08, 0x91, 0xbf, 0x6e, 0x47, 0x44, 0xd4, 0x6a, 0xc0, 0xc3, 0x09, 0x39, 0x27, 0xdd, 0xc7, 0xca, 0x06, 0x29, 0x55,
/* (2^278)P */ 0x76, 0x28, 0x58, 0xb0, 0xd2, 0xf3, 0x0f, 0x04, 0xe9, 0xc9, 0xab, 0x66, 0x5b, 0x75, 0x51, 0xdc, 0xe5, 0x8f, 0xe8, 0x1f, 0xdb, 0x03, 0x0f, 0xb0, 0x7d, 0xf9, 0x20, 0x64, 0x89, 0xe9, 0xdc, 0xe6, 0x24, 0xc3, 0xd5, 0xd2, 0x41, 0xa6, 0xe4, 0xe3, 0xc4, 0x79, 0x7c, 0x0f, 0xa1, 0x61, 0x2f, 0xda, 0xa4, 0xc9, 0xfd, 0xad, 0x5c, 0x65, 0x6a, 0xf3,
/* (2^279)P */ 0xd5, 0xab, 0x72, 0x7a, 0x3b, 0x59, 0xea, 0xcf, 0xd5, 0x17, 0xd2, 0xb2, 0x5f, 0x2d, 0xab, 0xad, 0x9e, 0x88, 0x64, 0x55, 0x96, 0x6e, 0xf3, 0x44, 0xa9, 0x11, 0xf5, 0xf8, 0x3a, 0xf1, 0xcd, 0x79, 0x4c, 0x99, 0x6d, 0x23, 0x6a, 0xa0, 0xc2, 0x1a, 0x19, 0x45, 0xb5, 0xd8, 0x95, 0x2f, 0x49, 0xe9, 0x46, 0x39, 0x26, 0x60, 0x04, 0x15, 0x8b, 0xcc,
/* (2^280)P */ 0x66, 0x0c, 0xf0, 0x54, 0x41, 0x02, 0x91, 0xab, 0xe5, 0x85, 0x8a, 0x44, 0xa6, 0x34, 0x96, 0x32, 0xc0, 0xdf, 0x6c, 0x41, 0x39, 0xd4, 0xc6, 0xe1, 0xe3, 0x81, 0xb0, 0x4c, 0x34, 0x4f, 0xe5, 0xf4, 0x35, 0x46, 0x1f, 0xeb, 0x75, 0xfd, 0x43, 0x37, 0x50, 0x99, 0xab, 0xad, 0xb7, 0x8c, 0xa1, 0x57, 0xcb, 0xe6, 0xce, 0x16, 0x2e, 0x85, 0xcc, 0xf9,
/* (2^281)P */ 0x63, 0xd1, 0x3f, 0x9e, 0xa2, 0x17, 0x2e, 0x1d, 0x3e, 0xce, 0x48, 0x2d, 0xbb, 0x8f, 0x69, 0xc9, 0xa6, 0x3d, 0x4e, 0xfe, 0x09, 0x56, 0xb3, 0x02, 0x5f, 0x99, 0x97, 0x0c, 0x54, 0xda, 0x32, 0x97, 0x9b, 0xf4, 0x95, 0xf1, 0xad, 0xe3, 0x2b, 0x04, 0xa7, 0x9b, 0x3f, 0xbb, 0xe7, 0x87, 0x2e, 0x1f, 0x8b, 0x4b, 0x7a, 0xa4, 0x43, 0x0c, 0x0f, 0x35,
/* (2^282)P */ 0x05, 0xdc, 0xe0, 0x2c, 0xa1, 0xc1, 0xd0, 0xf1, 0x1f, 0x4e, 0xc0, 0x6c, 0x35, 0x7b, 0xca, 0x8f, 0x8b, 0x02, 0xb1, 0xf7, 0xd6, 0x2e, 0xe7, 0x93, 0x80, 0x85, 0x18, 0x88, 0x19, 0xb9, 0xb4, 0x4a, 0xbc, 0xeb, 0x5a, 0x78, 0x38, 0xed, 0xc6, 0x27, 0x2a, 0x74, 0x76, 0xf0, 0x1b, 0x79, 0x92, 0x2f, 0xd2, 0x81, 0x98, 0xdf, 0xa9, 0x50, 0x19, 0xeb,
/* (2^283)P */ 0xb5, 0xe7, 0xb4, 0x11, 0x3a, 0x81, 0xb6, 0xb4, 0xf8, 0xa2, 0xb3, 0x6c, 0xfc, 0x9d, 0xe0, 0xc0, 0xe0, 0x59, 0x7f, 0x05, 0x37, 0xef, 0x2c, 0xa9, 0x3a, 0x24, 0xac, 0x7b, 0x25, 0xa0, 0x55, 0xd2, 0x44, 0x82, 0x82, 0x6e, 0x64, 0xa3, 0x58, 0xc8, 0x67, 0xae, 0x26, 0xa7, 0x0f, 0x42, 0x63, 0xe1, 0x93, 0x01, 0x52, 0x19, 0xaf, 0x49, 0x3e, 0x33,
/* (2^284)P */ 0x05, 0x85, 0xe6, 0x66, 0xaf, 0x5f, 0xdf, 0xbf, 0x9d, 0x24, 0x62, 0x60, 0x90, 0xe2, 0x4c, 0x7d, 0x4e, 0xc3, 0x74, 0x5d, 0x4f, 0x53, 0xf3, 0x63, 0x13, 0xf4, 0x74, 0x28, 0x6b, 0x7d, 0x57, 0x0c, 0x9d, 0x84, 0xa7, 0x1a, 0xff, 0xa0, 0x79, 0xdf, 0xfc, 0x65, 0x98, 0x8e, 0x22, 0x0d, 0x62, 0x7e, 0xf2, 0x34, 0x60, 0x83, 0x05, 0x14, 0xb1, 0xc1,
/* (2^285)P */ 0x64, 0x22, 0xcc, 0xdf, 0x5c, 0xbc, 0x88, 0x68, 0x4c, 0xd9, 0xbc, 0x0e, 0xc9, 0x8b, 0xb4, 0x23, 0x52, 0xad, 0xb0, 0xb3, 0xf1, 0x17, 0xd8, 0x15, 0x04, 0x6b, 0x99, 0xf0, 0xc4, 0x7d, 0x48, 0x22, 0x4a, 0xf8, 0x6f, 0xaa, 0x88, 0x0d, 0xc5, 0x5e, 0xa9, 0x1c, 0x61, 0x3d, 0x95, 0xa9, 0x7b, 0x6a, 0x79, 0x33, 0x0a, 0x2b, 0x99, 0xe3, 0x4e, 0x48,
/* (2^286)P */ 0x6b, 0x9b, 0x6a, 0x2a, 0xf1, 0x60, 0x31, 0xb4, 0x73, 0xd1, 0x87, 0x45, 0x9c, 0x15, 0x58, 0x4b, 0x91, 0x6d, 0x94, 0x1c, 0x41, 0x11, 0x4a, 0x83, 0xec, 0xaf, 0x65, 0xbc, 0x34, 0xaa, 0x26, 0xe2, 0xaf, 0xed, 0x46, 0x05, 0x4e, 0xdb, 0xc6, 0x4e, 0x10, 0x28, 0x4e, 0x72, 0xe5, 0x31, 0xa3, 0x20, 0xd7, 0xb1, 0x96, 0x64, 0xf6, 0xce, 0x08, 0x08,
/* (2^287)P */ 0x16, 0xa9, 0x5c, 0x9f, 0x9a, 0xb4, 0xb8, 0xc8, 0x32, 0x78, 0xc0, 0x3a, 0xd9, 0x5f, 0x94, 0xac, 0x3a, 0x42, 0x1f, 0x43, 0xd6, 0x80, 0x47, 0x2c, 0xdc, 0x76, 0x27, 0xfa, 0x50, 0xe5, 0xa1, 0xe4, 0xc3, 0xcb, 0x61, 0x31, 0xe1, 0x2e, 0xde, 0x81, 0x3b, 0x77, 0x1c, 0x39, 0x3c, 0xdb, 0xda, 0x87, 0x4b, 0x84, 0x12, 0xeb, 0xdd, 0x54, 0xbf, 0xe7,
/* (2^288)P */ 0xbf, 0xcb, 0x73, 0x21, 0x3d, 0x7e, 0x13, 0x8c, 0xa6, 0x34, 0x21, 0x2b, 0xa5, 0xe4, 0x9f, 0x8e, 0x9c, 0x01, 0x9c, 0x43, 0xd9, 0xc7, 0xb9, 0xf1, 0xbe, 0x7f, 0x45, 0x51, 0x97, 0xa1, 0x8e, 0x01, 0xf8, 0xbd, 0xd2, 0xbf, 0x81, 0x3a, 0x8b, 0xab, 0xe4, 0x89, 0xb7, 0xbd, 0xf2, 0xcd, 0xa9, 0x8a, 0x8a, 0xde, 0xfb, 0x8a, 0x55, 0x12, 0x7b, 0x17,
/* (2^289)P */ 0x1b, 0x95, 0x58, 0x4d, 0xe6, 0x51, 0x31, 0x52, 0x1c, 0xd8, 0x15, 0x84, 0xb1, 0x0d, 0x36, 0x25, 0x88, 0x91, 0x46, 0x71, 0x42, 0x56, 0xe2, 0x90, 0x08, 0x9e, 0x77, 0x1b, 0xee, 0x22, 0x3f, 0xec, 0xee, 0x8c, 0x7b, 0x2e, 0x79, 0xc4, 0x6c, 0x07, 0xa1, 0x7e, 0x52, 0xf5, 0x26, 0x5c, 0x84, 0x2a, 0x50, 0x6e, 0x82, 0xb3, 0x76, 0xda, 0x35, 0x16,
/* (2^290)P */ 0x0a, 0x6f, 0x99, 0x87, 0xc0, 0x7d, 0x8a, 0xb2, 0xca, 0xae, 0xe8, 0x65, 0x98, 0x0f, 0xb3, 0x44, 0xe1, 0xdc, 0x52, 0x79, 0x75, 0xec, 0x8f, 0x95, 0x87, 0x45, 0xd1, 0x32, 0x18, 0x55, 0x15, 0xce, 0x64, 0x9b, 0x08, 0x4f, 0x2c, 0xea, 0xba, 0x1c, 0x57, 0x06, 0x63, 0xc8, 0xb1, 0xfd, 0xc5, 0x67, 0xe7, 0x1f, 0x87, 0x9e, 0xde, 0x72, 0x7d, 0xec,
/* (2^291)P */ 0x36, 0x8b, 0x4d, 0x2c, 0xc2, 0x46, 0xe8, 0x96, 0xac, 0x0b, 0x8c, 0xc5, 0x09, 0x10, 0xfc, 0xf2, 0xda, 0xea, 0x22, 0xb2, 0xd3, 0x89, 0xeb, 0xb2, 0x85, 0x0f, 0xff, 0x59, 0x50, 0x2c, 0x99, 0x5a, 0x1f, 0xec, 0x2a, 0x6f, 0xec, 0xcf, 0xe9, 0xce, 0x12, 0x6b, 0x19, 0xd8, 0xde, 0x9b, 0xce, 0x0e, 0x6a, 0xaa, 0xe1, 0x32, 0xea, 0x4c, 0xfe, 0x92,
/* (2^292)P */ 0x5f, 0x17, 0x70, 0x53, 0x26, 0x03, 0x0b, 0xab, 0xd1, 0xc1, 0x42, 0x0b, 0xab, 0x2b, 0x3d, 0x31, 0xa4, 0xd5, 0x2b, 0x5e, 0x00, 0xd5, 0x9a, 0x22, 0x34, 0xe0, 0x53, 0x3f, 0x59, 0x7f, 0x2c, 0x6d, 0x72, 0x9a, 0xa4, 0xbe, 0x3d, 0x42, 0x05, 0x1b, 0xf2, 0x7f, 0x88, 0x56, 0xd1, 0x7c, 0x7d, 0x6b, 0x9f, 0x43, 0xfe, 0x65, 0x19, 0xae, 0x9c, 0x4c,
/* (2^293)P */ 0xf3, 0x7c, 0x20, 0xa9, 0xfc, 0xf2, 0xf2, 0x3b, 0x3c, 0x57, 0x41, 0x94, 0xe5, 0xcc, 0x6a, 0x37, 0x5d, 0x09, 0xf2, 0xab, 0xc2, 0xca, 0x60, 0x38, 0x6b, 0x7a, 0xe1, 0x78, 0x2b, 0xc1, 0x1d, 0xe8, 0xfd, 0xbc, 0x3d, 0x5c, 0xa2, 0xdb, 0x49, 0x20, 0x79, 0xe6, 0x1b, 0x9b, 0x65, 0xd9, 0x6d, 0xec, 0x57, 0x1d, 0xd2, 0xe9, 0x90, 0xeb, 0x43, 0x7b,
/* (2^294)P */ 0x2a, 0x8b, 0x2e, 0x19, 0x18, 0x10, 0xb8, 0x83, 0xe7, 0x7d, 0x2d, 0x9a, 0x3a, 0xe5, 0xd1, 0xe4, 0x7c, 0x38, 0xe5, 0x59, 0x2a, 0x6e, 0xd9, 0x01, 0x29, 0x3d, 0x23, 0xf7, 0x52, 0xba, 0x61, 0x04, 0x9a, 0xde, 0xc4, 0x31, 0x50, 0xeb, 0x1b, 0xaa, 0xde, 0x39, 0x58, 0xd8, 0x1b, 0x1e, 0xfc, 0x57, 0x9a, 0x28, 0x43, 0x9e, 0x97, 0x5e, 0xaa, 0xa3,
/* (2^295)P */ 0x97, 0x0a, 0x74, 0xc4, 0x39, 0x99, 0x6b, 0x40, 0xc7, 0x3e, 0x8c, 0xa7, 0xb1, 0x4e, 0x9a, 0x59, 0x6e, 0x1c, 0xfe, 0xfc, 0x2a, 0x5e, 0x73, 0x2b, 0x8c, 0xa9, 0x71, 0xf5, 0xda, 0x6b, 0x15, 0xab, 0xf7, 0xbe, 0x2a, 0x44, 0x5f, 0xba, 0xae, 0x67, 0x93, 0xc5, 0x86, 0xc1, 0xb8, 0xdf, 0xdc, 0xcb, 0xd7, 0xff, 0xb1, 0x71, 0x7c, 0x6f, 0x88, 0xf8,
/* (2^296)P */ 0x3f, 0x89, 0xb1, 0xbf, 0x24, 0x16, 0xac, 0x56, 0xfe, 0xdf, 0x94, 0x71, 0xbf, 0xd6, 0x57, 0x0c, 0xb4, 0x77, 0x37, 0xaa, 0x2a, 0x70, 0x76, 0x49, 0xaf, 0x0c, 0x97, 0x8e, 0x78, 0x2a, 0x67, 0xc9, 0x3b, 0x3d, 0x5b, 0x01, 0x2f, 0xda, 0xd5, 0xa8, 0xde, 0x02, 0xa9, 0xac, 0x76, 0x00, 0x0b, 0x46, 0xc6, 0x2d, 0xdc, 0x08, 0xf4, 0x10, 0x2c, 0xbe,
/* (2^297)P */ 0xcb, 0x07, 0xf9, 0x91, 0xc6, 0xd5, 0x3e, 0x54, 0x63, 0xae, 0xfc, 0x10, 0xbe, 0x3a, 0x20, 0x73, 0x4e, 0x65, 0x0e, 0x2d, 0x86, 0x77, 0x83, 0x9d, 0xe2, 0x0a, 0xe9, 0xac, 0x22, 0x52, 0x76, 0xd4, 0x6e, 0xfa, 0xe0, 0x09, 0xef, 0x78, 0x82, 0x9f, 0x26, 0xf9, 0x06, 0xb5, 0xe7, 0x05, 0x0e, 0xf2, 0x46, 0x72, 0x93, 0xd3, 0x24, 0xbd, 0x87, 0x60,
/* (2^298)P */ 0x14, 0x55, 0x84, 0x7b, 0x6c, 0x60, 0x80, 0x73, 0x8c, 0xbe, 0x2d, 0xd6, 0x69, 0xd6, 0x17, 0x26, 0x44, 0x9f, 0x88, 0xa2, 0x39, 0x7c, 0x89, 0xbc, 0x6d, 0x9e, 0x46, 0xb6, 0x68, 0x66, 0xea, 0xdc, 0x31, 0xd6, 0x21, 0x51, 0x9f, 0x28, 0x28, 0xaf, 0x9e, 0x47, 0x2c, 0x4c, 0x8f, 0xf3, 0xaf, 0x1f, 0xe4, 0xab, 0xac, 0xe9, 0x0c, 0x91, 0x3a, 0x61,
/* (2^299)P */ 0xb0, 0x37, 0x55, 0x4b, 0xe9, 0xc3, 0xb1, 0xce, 0x42, 0xe6, 0xc5, 0x11, 0x7f, 0x2c, 0x11, 0xfc, 0x4e, 0x71, 0x17, 0x00, 0x74, 0x7f, 0xbf, 0x07, 0x4d, 0xfd, 0x40, 0xb2, 0x87, 0xb0, 0xef, 0x1f, 0x35, 0x2c, 0x2d, 0xd7, 0xe1, 0xe4, 0xad, 0x0e, 0x7f, 0x63, 0x66, 0x62, 0x23, 0x41, 0xf6, 0xc1, 0x14, 0xa6, 0xd7, 0xa9, 0x11, 0x56, 0x9d, 0x1b,
/* (2^300)P */ 0x02, 0x82, 0x42, 0x18, 0x4f, 0x1b, 0xc9, 0x5d, 0x78, 0x5f, 0xee, 0xed, 0x01, 0x49, 0x8f, 0xf2, 0xa0, 0xe2, 0x6e, 0xbb, 0x6b, 0x04, 0x8d, 0xb2, 0x41, 0xae, 0xc8, 0x1b, 0x59, 0x34, 0xb8, 0x2a, 0xdb, 0x1f, 0xd2, 0x52, 0xdf, 0x3f, 0x35, 0x00, 0x8b, 0x61, 0xbc, 0x97, 0xa0, 0xc4, 0x77, 0xd1, 0xe4, 0x2c, 0x59, 0x68, 0xff, 0x30, 0xf2, 0xe2,
/* (2^301)P */ 0x79, 0x08, 0xb1, 0xdb, 0x55, 0xae, 0xd0, 0xed, 0xda, 0xa0, 0xec, 0x6c, 0xae, 0x68, 0xf2, 0x0b, 0x61, 0xb3, 0xf5, 0x21, 0x69, 0x87, 0x0b, 0x03, 0xea, 0x8a, 0x15, 0xd9, 0x7e, 0xca, 0xf7, 0xcd, 0xf3, 0x33, 0xb3, 0x4c, 0x5b, 0x23, 0x4e, 0x6f, 0x90, 0xad, 0x91, 0x4b, 0x4f, 0x46, 0x37, 0xe5, 0xe8, 0xb7, 0xeb, 0xd5, 0xca, 0x34, 0x4e, 0x23,
/* (2^302)P */ 0x09, 0x02, 0xdd, 0xfd, 0x70, 0xac, 0x56, 0x80, 0x36, 0x5e, 0x49, 0xd0, 0x3f, 0xc2, 0xe0, 0xba, 0x46, 0x7f, 0x5c, 0xf7, 0xc5, 0xbd, 0xd5, 0x55, 0x7d, 0x3f, 0xd5, 0x7d, 0x06, 0xdf, 0x27, 0x20, 0x4f, 0xe9, 0x30, 0xec, 0x1b, 0xa0, 0x0c, 0xd4, 0x2c, 0xe1, 0x2b, 0x65, 0x73, 0xea, 0x75, 0x35, 0xe8, 0xe6, 0x56, 0xd6, 0x07, 0x15, 0x99, 0xdf,
/* (2^303)P */ 0x4e, 0x10, 0xb7, 0xd0, 0x63, 0x8c, 0xcf, 0x16, 0x00, 0x7c, 0x58, 0xdf, 0x86, 0xdc, 0x4e, 0xca, 0x9c, 0x40, 0x5a, 0x42, 0xfd, 0xec, 0x98, 0xa4, 0x42, 0x53, 0xae, 0x16, 0x9d, 0xfd, 0x75, 0x5a, 0x12, 0x56, 0x1e, 0xc6, 0x57, 0xcc, 0x79, 0x27, 0x96, 0x00, 0xcf, 0x80, 0x4f, 0x8a, 0x36, 0x5c, 0xbb, 0xe9, 0x12, 0xdb, 0xb6, 0x2b, 0xad, 0x96,
/* (2^304)P */ 0x92, 0x32, 0x1f, 0xfd, 0xc6, 0x02, 0x94, 0x08, 0x1b, 0x60, 0x6a, 0x9f, 0x8b, 0xd6, 0xc8, 0xad, 0xd5, 0x1b, 0x27, 0x4e, 0xa4, 0x4d, 0x4a, 0x00, 0x10, 0x5f, 0x86, 0x11, 0xf5, 0xe3, 0x14, 0x32, 0x43, 0xee, 0xb9, 0xc7, 0xab, 0xf4, 0x6f, 0xe5, 0x66, 0x0c, 0x06, 0x0d, 0x96, 0x79, 0x28, 0xaf, 0x45, 0x2b, 0x56, 0xbe, 0xe4, 0x4a, 0x52, 0xd6,
/* (2^305)P */ 0x15, 0x16, 0x69, 0xef, 0x60, 0xca, 0x82, 0x25, 0x0f, 0xc6, 0x30, 0xa0, 0x0a, 0xd1, 0x83, 0x29, 0xcd, 0xb6, 0x89, 0x6c, 0xf5, 0xb2, 0x08, 0x38, 0xe6, 0xca, 0x6b, 0x19, 0x93, 0xc6, 0x5f, 0x75, 0x8e, 0x60, 0x34, 0x23, 0xc4, 0x13, 0x17, 0x69, 0x55, 0xcc, 0x72, 0x9c, 0x2b, 0x6c, 0x80, 0xf4, 0x4b, 0x8b, 0xb6, 0x97, 0x65, 0x07, 0xb6, 0xfb,
/* (2^306)P */ 0x01, 0x99, 0x74, 0x28, 0xa6, 0x67, 0xa3, 0xe5, 0x25, 0xfb, 0xdf, 0x82, 0x93, 0xe7, 0x35, 0x74, 0xce, 0xe3, 0x15, 0x1c, 0x1d, 0x79, 0x52, 0x84, 0x08, 0x04, 0x2f, 0x5c, 0xb8, 0xcd, 0x7f, 0x89, 0xb0, 0x39, 0x93, 0x63, 0xc9, 0x5d, 0x06, 0x01, 0x59, 0xf7, 0x7e, 0xf1, 0x4c, 0x3d, 0x12, 0x8d, 0x69, 0x1d, 0xb7, 0x21, 0x5e, 0x88, 0x82, 0xa2,
/* (2^307)P */ 0x8e, 0x69, 0xaf, 0x9a, 0x41, 0x0d, 0x9d, 0xcf, 0x8e, 0x8d, 0x5c, 0x51, 0x6e, 0xde, 0x0e, 0x48, 0x23, 0x89, 0xe5, 0x37, 0x80, 0xd6, 0x9d, 0x72, 0x32, 0x26, 0x38, 0x2d, 0x63, 0xa0, 0xfa, 0xd3, 0x40, 0xc0, 0x8c, 0x68, 0x6f, 0x2b, 0x1e, 0x9a, 0x39, 0x51, 0x78, 0x74, 0x9a, 0x7b, 0x4a, 0x8f, 0x0c, 0xa0, 0x88, 0x60, 0xa5, 0x21, 0xcd, 0xc7,
/* (2^308)P */ 0x3a, 0x7f, 0x73, 0x14, 0xbf, 0x89, 0x6a, 0x4c, 0x09, 0x5d, 0xf2, 0x93, 0x20, 0x2d, 0xc4, 0x29, 0x86, 0x06, 0x95, 0xab, 0x22, 0x76, 0x4c, 0x54, 0xe1, 0x7e, 0x80, 0x6d, 0xab, 0x29, 0x61, 0x87, 0x77, 0xf6, 0xc0, 0x3e, 0xda, 0xab, 0x65, 0x7e, 0x39, 0x12, 0xa1, 0x6b, 0x42, 0xf7, 0xc5, 0x97, 0x77, 0xec, 0x6f, 0x22, 0xbe, 0x44, 0xc7, 0x03,
/* (2^309)P */ 0xa5, 0x23, 0x90, 0x41, 0xa3, 0xc5, 0x3e, 0xe0, 0xa5, 0x32, 0x49, 0x1f, 0x39, 0x78, 0xb1, 0xd8, 0x24, 0xea, 0xd4, 0x87, 0x53, 0x42, 0x51, 0xf4, 0xd9, 0x46, 0x25, 0x2f, 0x62, 0xa9, 0x90, 0x9a, 0x4a, 0x25, 0x8a, 0xd2, 0x10, 0xe7, 0x3c, 0xbc, 0x58, 0x8d, 0x16, 0x14, 0x96, 0xa4, 0x6f, 0xf8, 0x12, 0x69, 0x91, 0x73, 0xe2, 0xfa, 0xf4, 0x57,
/* (2^310)P */ 0x51, 0x45, 0x3f, 0x96, 0xdc, 0x97, 0x38, 0xa6, 0x01, 0x63, 0x09, 0xea, 0xc2, 0x13, 0x30, 0xb0, 0x00, 0xb8, 0x0a, 0xce, 0xd1, 0x8f, 0x3e, 0x69, 0x62, 0x46, 0x33, 0x9c, 0xbf, 0x4b, 0xcb, 0x0c, 0x90, 0x1c, 0x45, 0xcf, 0x37, 0x5b, 0xf7, 0x4b, 0x5e, 0x95, 0xc3, 0x28, 0x9f, 0x08, 0x83, 0x53, 0x74, 0xab, 0x0c, 0xb4, 0xc0, 0xa1, 0xbc, 0x89,
/* (2^311)P */ 0x06, 0xb1, 0x51, 0x15, 0x65, 0x60, 0x21, 0x17, 0x7a, 0x20, 0x65, 0xee, 0x12, 0x35, 0x4d, 0x46, 0xf4, 0xf8, 0xd0, 0xb1, 0xca, 0x09, 0x30, 0x08, 0x89, 0x23, 0x3b, 0xe7, 0xab, 0x8b, 0x77, 0xa6, 0xad, 0x25, 0xdd, 0xea, 0x3c, 0x7d, 0xa5, 0x24, 0xb3, 0xe8, 0xfa, 0xfb, 0xc9, 0xf2, 0x71, 0xe9, 0xfa, 0xf2, 0xdc, 0x54, 0xdd, 0x55, 0x2e, 0x2f,
/* (2^312)P */ 0x7f, 0x96, 0x96, 0xfb, 0x52, 0x86, 0xcf, 0xea, 0x62, 0x18, 0xf1, 0x53, 0x1f, 0x61, 0x2a, 0x9f, 0x8c, 0x51, 0xca, 0x2c, 0xde, 0x6d, 0xce, 0xab, 0x58, 0x32, 0x0b, 0x33, 0x9b, 0x99, 0xb4, 0x5c, 0x88, 0x2a, 0x76, 0xcc, 0x3e, 0x54, 0x1e, 0x9d, 0xa2, 0x89, 0xe4, 0x19, 0xba, 0x80, 0xc8, 0x39, 0x32, 0x7f, 0x0f, 0xc7, 0x84, 0xbb, 0x43, 0x56,
/* (2^313)P */ 0x9b, 0x07, 0xb4, 0x42, 0xa9, 0xa0, 0x78, 0x4f, 0x28, 0x70, 0x2b, 0x7e, 0x61, 0xe0, 0xdd, 0x02, 0x98, 0xfc, 0xed, 0x31, 0x80, 0xf1, 0x15, 0x52, 0x89, 0x23, 0xcd, 0x5d, 0x2b, 0xc5, 0x19, 0x32, 0xfb, 0x70, 0x50, 0x7a, 0x97, 0x6b, 0x42, 0xdb, 0xca, 0xdb, 0xc4, 0x59, 0x99, 0xe0, 0x12, 0x1f, 0x17, 0xba, 0x8b, 0xf0, 0xc4, 0x38, 0x5d, 0x27,
/* (2^314)P */ 0x29, 0x1d, 0xdc, 0x2b, 0xf6, 0x5b, 0x04, 0x61, 0x36, 0x76, 0xa0, 0x56, 0x36, 0x6e, 0xd7, 0x24, 0x4d, 0xe7, 0xef, 0x44, 0xd2, 0xd5, 0x07, 0xcd, 0xc4, 0x9d, 0x80, 0x48, 0xc3, 0x38, 0xcf, 0xd8, 0xa3, 0xdd, 0xb2, 0x5e, 0xb5, 0x70, 0x15, 0xbb, 0x36, 0x85, 0x8a, 0xd7, 0xfb, 0x56, 0x94, 0x73, 0x9c, 0x81, 0xbe, 0xb1, 0x44, 0x28, 0xf1, 0x37,
/* (2^315)P */ 0xbf, 0xcf, 0x5c, 0xd2, 0xe2, 0xea, 0xc2, 0xcd, 0x70, 0x7a, 0x9d, 0xcb, 0x81, 0xc1, 0xe9, 0xf1, 0x56, 0x71, 0x52, 0xf7, 0x1b, 0x87, 0xc6, 0xd8, 0xcc, 0xb2, 0x69, 0xf3, 0xb0, 0xbd, 0xba, 0x83, 0x12, 0x26, 0xc4, 0xce, 0x72, 0xde, 0x3b, 0x21, 0x28, 0x9e, 0x5a, 0x94, 0xf5, 0x04, 0xa3, 0xc8, 0x0f, 0x5e, 0xbc, 0x71, 0xf9, 0x0d, 0xce, 0xf5,
/* (2^316)P */ 0x93, 0x97, 0x00, 0x85, 0xf4, 0xb4, 0x40, 0xec, 0xd9, 0x2b, 0x6c, 0xd6, 0x63, 0x9e, 0x93, 0x0a, 0x5a, 0xf4, 0xa7, 0x9a, 0xe3, 0x3c, 0xf0, 0x55, 0xd1, 0x96, 0x6c, 0xf5, 0x2a, 0xce, 0xd7, 0x95, 0x72, 0xbf, 0xc5, 0x0c, 0xce, 0x79, 0xa2, 0x0a, 0x78, 0xe0, 0x72, 0xd0, 0x66, 0x28, 0x05, 0x75, 0xd3, 0x23, 0x09, 0x91, 0xed, 0x7e, 0xc4, 0xbc,
/* (2^317)P */ 0x77, 0xc2, 0x9a, 0xf7, 0xa6, 0xe6, 0x18, 0xb4, 0xe7, 0xf6, 0xda, 0xec, 0x44, 0x6d, 0xfb, 0x08, 0xee, 0x65, 0xa8, 0x92, 0x85, 0x1f, 0xba, 0x38, 0x93, 0x20, 0x5c, 0x4d, 0xd2, 0x18, 0x0f, 0x24, 0xbe, 0x1a, 0x96, 0x44, 0x7d, 0xeb, 0xb3, 0xda, 0x95, 0xf4, 0xaf, 0x6c, 0x06, 0x0f, 0x47, 0x37, 0xc8, 0x77, 0x63, 0xe1, 0x29, 0xef, 0xff, 0xa5,
/* (2^318)P */ 0x16, 0x12, 0xd9, 0x47, 0x90, 0x22, 0x9b, 0x05, 0xf2, 0xa5, 0x9a, 0xae, 0x83, 0x98, 0xb5, 0xac, 0xab, 0x29, 0xaa, 0xdc, 0x5f, 0xde, 0xcd, 0xf7, 0x42, 0xad, 0x3b, 0x96, 0xd6, 0x3e, 0x6e, 0x52, 0x47, 0xb1, 0xab, 0x51, 0xde, 0x49, 0x7c, 0x87, 0x8d, 0x86, 0xe2, 0x70, 0x13, 0x21, 0x51, 0x1c, 0x0c, 0x25, 0xc1, 0xb0, 0xe6, 0x19, 0xcf, 0x12,
/* (2^319)P */ 0xf0, 0xbc, 0x97, 0x8f, 0x4b, 0x2f, 0xd1, 0x1f, 0x8c, 0x57, 0xed, 0x3c, 0xf4, 0x26, 0x19, 0xbb, 0x60, 0xca, 0x24, 0xc5, 0xd9, 0x97, 0xe2, 0x5f, 0x76, 0x49, 0x39, 0x7e, 0x2d, 0x12, 0x21, 0x98, 0xda, 0xe6, 0xdb, 0xd2, 0xd8, 0x9f, 0x18, 0xd8, 0x83, 0x6c, 0xba, 0x89, 0x8d, 0x29, 0xfa, 0x46, 0x33, 0x8c, 0x28, 0xdf, 0x6a, 0xb3, 0x69, 0x28,
/* (2^320)P */ 0x86, 0x17, 0xbc, 0xd6, 0x7c, 0xba, 0x1e, 0x83, 0xbb, 0x84, 0xb5, 0x8c, 0xad, 0xdf, 0xa1, 0x24, 0x81, 0x70, 0x40, 0x0f, 0xad, 0xad, 0x3b, 0x23, 0xd0, 0x93, 0xa0, 0x49, 0x5c, 0x4b, 0x51, 0xbe, 0x20, 0x49, 0x4e, 0xda, 0x2d, 0xd3, 0xad, 0x1b, 0x74, 0x08, 0x41, 0xf0, 0xef, 0x19, 0xe9, 0x45, 0x5d, 0x02, 0xae, 0x26, 0x25, 0xd9, 0xd1, 0xc2,
/* (2^321)P */ 0x48, 0x81, 0x3e, 0xb2, 0x83, 0xf8, 0x4d, 0xb3, 0xd0, 0x4c, 0x75, 0xb3, 0xa0, 0x52, 0x26, 0xf2, 0xaf, 0x5d, 0x36, 0x70, 0x72, 0xd6, 0xb7, 0x88, 0x08, 0x69, 0xbd, 0x15, 0x25, 0xb1, 0x45, 0x1b, 0xb7, 0x0b, 0x5f, 0x71, 0x5d, 0x83, 0x49, 0xb9, 0x84, 0x3b, 0x7c, 0xc1, 0x50, 0x93, 0x05, 0x53, 0xe0, 0x61, 0xea, 0xc1, 0xef, 0xdb, 0x82, 0x97,
/* (2^322)P */ 0x00, 0xd5, 0xc3, 0x3a, 0x4d, 0x8a, 0x23, 0x7a, 0xef, 0xff, 0x37, 0xef, 0xf3, 0xbc, 0xa9, 0xb6, 0xae, 0xd7, 0x3a, 0x7b, 0xfd, 0x3e, 0x8e, 0x9b, 0xab, 0x44, 0x54, 0x60, 0x28, 0x6c, 0xbf, 0x15, 0x24, 0x4a, 0x56, 0x60, 0x7f, 0xa9, 0x7a, 0x28, 0x59, 0x2c, 0x8a, 0xd1, 0x7d, 0x6b, 0x00, 0xfd, 0xa5, 0xad, 0xbc, 0x19, 0x3f, 0xcb, 0x73, 0xe0,
/* (2^323)P */ 0xcf, 0x9e, 0x66, 0x06, 0x4d, 0x2b, 0xf5, 0x9c, 0xc2, 0x9d, 0x9e, 0xed, 0x5a, 0x5c, 0x2d, 0x00, 0xbf, 0x29, 0x90, 0x88, 0xe4, 0x5d, 0xfd, 0xe2, 0xf0, 0x38, 0xec, 0x4d, 0x26, 0xea, 0x54, 0xf0, 0x3c, 0x84, 0x10, 0x6a, 0xf9, 0x66, 0x9c, 0xe7, 0x21, 0xfd, 0x0f, 0xc7, 0x13, 0x50, 0x81, 0xb6, 0x50, 0xf9, 0x04, 0x7f, 0xa4, 0x37, 0x85, 0x14,
/* (2^324)P */ 0xdb, 0x87, 0x49, 0xc7, 0xa8, 0x39, 0x0c, 0x32, 0x98, 0x0c, 0xb9, 0x1a, 0x1b, 0x4d, 0xe0, 0x8a, 0x9a, 0x8e, 0x8f, 0xab, 0x5a, 0x17, 0x3d, 0x04, 0x21, 0xce, 0x3e, 0x2c, 0xf9, 0xa3, 0x97, 0xe4, 0x77, 0x95, 0x0e, 0xb6, 0xa5, 0x15, 0xad, 0x3a, 0x1e, 0x46, 0x53, 0x17, 0x09, 0x83, 0x71, 0x4e, 0x86, 0x38, 0xd5, 0x23, 0x44, 0x16, 0x8d, 0xc8,
/* (2^325)P */ 0x05, 0x5e, 0x99, 0x08, 0xbb, 0xc3, 0xc0, 0xb7, 0x6c, 0x12, 0xf2, 0xf3, 0xf4, 0x7c, 0x6a, 0x4d, 0x9e, 0xeb, 0x3d, 0xb9, 0x63, 0x94, 0xce, 0x81, 0xd8, 0x11, 0xcb, 0x55, 0x69, 0x4a, 0x20, 0x0b, 0x4c, 0x2e, 0x14, 0xb8, 0xd4, 0x6a, 0x7c, 0xf0, 0xed, 0xfc, 0x8f, 0xef, 0xa0, 0xeb, 0x6c, 0x01, 0xe2, 0xdc, 0x10, 0x22, 0xa2, 0x01, 0x85, 0x64,
/* (2^326)P */ 0x58, 0xe1, 0x9c, 0x27, 0x55, 0xc6, 0x25, 0xa6, 0x7d, 0x67, 0x88, 0x65, 0x99, 0x6c, 0xcb, 0xdb, 0x27, 0x4f, 0x44, 0x29, 0xf5, 0x4a, 0x23, 0x10, 0xbc, 0x03, 0x3f, 0x36, 0x1e, 0xef, 0xb0, 0xba, 0x75, 0xe8, 0x74, 0x5f, 0x69, 0x3e, 0x26, 0x40, 0xb4, 0x2f, 0xdc, 0x43, 0xbf, 0xa1, 0x8b, 0xbd, 0xca, 0x6e, 0xc1, 0x6e, 0x21, 0x79, 0xa0, 0xd0,
/* (2^327)P */ 0x78, 0x93, 0x4a, 0x2d, 0x22, 0x6e, 0x6e, 0x7d, 0x74, 0xd2, 0x66, 0x58, 0xce, 0x7b, 0x1d, 0x97, 0xb1, 0xf2, 0xda, 0x1c, 0x79, 0xfb, 0xba, 0xd1, 0xc0, 0xc5, 0x6e, 0xc9, 0x11, 0x89, 0xd2, 0x41, 0x8d, 0x70, 0xb9, 0xcc, 0xea, 0x6a, 0xb3, 0x45, 0xb6, 0x05, 0x2e, 0xf2, 0x17, 0xf1, 0x27, 0xb8, 0xed, 0x06, 0x1f, 0xdb, 0x9d, 0x1f, 0x69, 0x28,
/* (2^328)P */ 0x93, 0x12, 0xa8, 0x11, 0xe1, 0x92, 0x30, 0x8d, 0xac, 0xe1, 0x1c, 0x60, 0x7c, 0xed, 0x2d, 0x2e, 0xd3, 0x03, 0x5c, 0x9c, 0xc5, 0xbd, 0x64, 0x4a, 0x8c, 0xba, 0x76, 0xfe, 0xc6, 0xc1, 0xea, 0xc2, 0x4f, 0xbe, 0x70, 0x3d, 0x64, 0xcf, 0x8e, 0x18, 0xcb, 0xcd, 0x57, 0xa7, 0xf7, 0x36, 0xa9, 0x6b, 0x3e, 0xb8, 0x69, 0xee, 0x47, 0xa2, 0x7e, 0xb2,
/* (2^329)P */ 0x96, 0xaf, 0x3a, 0xf5, 0xed, 0xcd, 0xaf, 0xf7, 0x82, 0xaf, 0x59, 0x62, 0x0b, 0x36, 0x85, 0xf9, 0xaf, 0xd6, 0x38, 0xff, 0x87, 0x2e, 0x1d, 0x6c, 0x8b, 0xaf, 0x3b, 0xdf, 0x28, 0xa2, 0xd6, 0x4d, 0x80, 0x92, 0xc3, 0x0f, 0x34, 0xa8, 0xae, 0x69, 0x5d, 0x7b, 0x9d, 0xbc, 0xf5, 0xfd, 0x1d, 0xb1, 0x96, 0x55, 0x86, 0xe1, 0x5c, 0xb6, 0xac, 0xb9,
/* (2^330)P */ 0x50, 0x9e, 0x37, 0x28, 0x7d, 0xa8, 0x33, 0x63, 0xda, 0x3f, 0x20, 0x98, 0x0e, 0x09, 0xa8, 0x77, 0x3b, 0x7a, 0xfc, 0x16, 0x85, 0x44, 0x64, 0x77, 0x65, 0x68, 0x92, 0x41, 0xc6, 0x1f, 0xdf, 0x27, 0xf9, 0xec, 0xa0, 0x61, 0x22, 0xea, 0x19, 0xe7, 0x75, 0x8b, 0x4e, 0xe5, 0x0f, 0xb7, 0xf7, 0xd2, 0x53, 0xf4, 0xdd, 0x4a, 0xaa, 0x78, 0x40, 0xb7,
/* (2^331)P */ 0xd4, 0x89, 0xe3, 0x79, 0xba, 0xb6, 0xc3, 0xda, 0xe6, 0x78, 0x65, 0x7d, 0x6e, 0x22, 0x62, 0xb1, 0x3d, 0xea, 0x90, 0x84, 0x30, 0x5e, 0xd4, 0x39, 0x84, 0x78, 0xd9, 0x75, 0xd6, 0xce, 0x2a, 0x11, 0x29, 0x69, 0xa4, 0x5e, 0xaa, 0x2a, 0x98, 0x5a, 0xe5, 0x91, 0x8f, 0xb2, 0xfb, 0xda, 0x97, 0xe8, 0x83, 0x6f, 0x04, 0xb9, 0x5d, 0xaf, 0xe1, 0x9b,
/* (2^332)P */ 0x8b, 0xe4, 0xe1, 0x48, 0x9c, 0xc4, 0x83, 0x89, 0xdf, 0x65, 0xd3, 0x35, 0x55, 0x13, 0xf4, 0x1f, 0x36, 0x92, 0x33, 0x38, 0xcb, 0xed, 0x15, 0xe6, 0x60, 0x2d, 0x25, 0xf5, 0x36, 0x60, 0x3a, 0x37, 0x9b, 0x71, 0x9d, 0x42, 0xb0, 0x14, 0xc8, 0xba, 0x62, 0xa3, 0x49, 0xb0, 0x88, 0xc1, 0x72, 0x73, 0xdd, 0x62, 0x40, 0xa9, 0x62, 0x88, 0x99, 0xca,
/* (2^333)P */ 0x47, 0x7b, 0xea, 0xda, 0x46, 0x2f, 0x45, 0xc6, 0xe3, 0xb4, 0x4d, 0x8d, 0xac, 0x0b, 0x54, 0x22, 0x06, 0x31, 0x16, 0x66, 0x3e, 0xe4, 0x38, 0x12, 0xcd, 0xf3, 0xe7, 0x99, 0x37, 0xd9, 0x62, 0x24, 0x4b, 0x05, 0xf2, 0x58, 0xe6, 0x29, 0x4b, 0x0d, 0xf6, 0xc1, 0xba, 0xa0, 0x1e, 0x0f, 0xcb, 0x1f, 0xc6, 0x2b, 0x19, 0xfc, 0x82, 0x01, 0xd0, 0x86,
/* (2^334)P */ 0xa2, 0xae, 0x77, 0x20, 0xfb, 0xa8, 0x18, 0xb4, 0x61, 0xef, 0xe8, 0x52, 0x79, 0xbb, 0x86, 0x90, 0x5d, 0x2e, 0x76, 0xed, 0x66, 0x60, 0x5d, 0x00, 0xb5, 0xa4, 0x00, 0x40, 0x89, 0xec, 0xd1, 0xd2, 0x0d, 0x26, 0xb9, 0x30, 0xb2, 0xd2, 0xb8, 0xe8, 0x0e, 0x56, 0xf9, 0x67, 0x94, 0x2e, 0x62, 0xe1, 0x79, 0x48, 0x2b, 0xa9, 0xfa, 0xea, 0xdb, 0x28,
/* (2^335)P */ 0x35, 0xf1, 0xb0, 0x43, 0xbd, 0x27, 0xef, 0x18, 0x44, 0xa2, 0x04, 0xb4, 0x69, 0xa1, 0x97, 0x1f, 0x8c, 0x04, 0x82, 0x9b, 0x00, 0x6d, 0xf8, 0xbf, 0x7d, 0xc1, 0x5b, 0xab, 0xe8, 0xb2, 0x34, 0xbd, 0xaf, 0x7f, 0xb2, 0x0d, 0xf3, 0xed, 0xfc, 0x5b, 0x50, 0xee, 0xe7, 0x4a, 0x20, 0xd9, 0xf5, 0xc6, 0x9a, 0x97, 0x6d, 0x07, 0x2f, 0xb9, 0x31, 0x02,
/* (2^336)P */ 0xf9, 0x54, 0x4a, 0xc5, 0x61, 0x7e, 0x1d, 0xa6, 0x0e, 0x1a, 0xa8, 0xd3, 0x8c, 0x36, 0x7d, 0xf1, 0x06, 0xb1, 0xac, 0x93, 0xcd, 0xe9, 0x8f, 0x61, 0x6c, 0x5d, 0x03, 0x23, 0xdf, 0x85, 0x53, 0x39, 0x63, 0x5e, 0xeb, 0xf3, 0xd3, 0xd3, 0x75, 0x97, 0x9b, 0x62, 0x9b, 0x01, 0xb3, 0x19, 0xd8, 0x2b, 0x36, 0xf2, 0x2c, 0x2c, 0x6f, 0x36, 0xc6, 0x3c,
/* (2^337)P */ 0x05, 0x74, 0x43, 0x10, 0xb6, 0xb0, 0xf8, 0xbf, 0x02, 0x46, 0x9a, 0xee, 0xc1, 0xaf, 0xc1, 0xe5, 0x5a, 0x2e, 0xbb, 0xe1, 0xdc, 0xc6, 0xce, 0x51, 0x29, 0x50, 0xbf, 0x1b, 0xde, 0xff, 0xba, 0x4d, 0x8d, 0x8b, 0x7e, 0xe7, 0xbd, 0x5b, 0x8f, 0xbe, 0xe3, 0x75, 0x71, 0xff, 0x37, 0x05, 0x5a, 0x10, 0xeb, 0x54, 0x7e, 0x44, 0x72, 0x2c, 0xd4, 0xfc,
/* (2^338)P */ 0x03, 0x12, 0x1c, 0xb2, 0x08, 0x90, 0xa1, 0x2d, 0x50, 0xa0, 0xad, 0x7f, 0x8d, 0xa6, 0x97, 0xc1, 0xbd, 0xdc, 0xc3, 0xa7, 0xad, 0x31, 0xdf, 0xb8, 0x03, 0x84, 0xc3, 0xb9, 0x29, 0x3d, 0x92, 0x2e, 0xc3, 0x90, 0x07, 0xe8, 0xa7, 0xc7, 0xbc, 0x61, 0xe9, 0x3e, 0xa0, 0x35, 0xda, 0x1d, 0xab, 0x48, 0xfe, 0x50, 0xc9, 0x25, 0x59, 0x23, 0x69, 0x3f,
/* (2^339)P */ 0x8e, 0x91, 0xab, 0x6b, 0x91, 0x4f, 0x89, 0x76, 0x67, 0xad, 0xb2, 0x65, 0x9d, 0xad, 0x02, 0x36, 0xdc, 0xac, 0x96, 0x93, 0x97, 0x21, 0x14, 0xd0, 0xe8, 0x11, 0x60, 0x1e, 0xeb, 0x96, 0x06, 0xf2, 0x53, 0xf2, 0x6d, 0xb7, 0x93, 0x6f, 0x26, 0x91, 0x23, 0xe3, 0x34, 0x04, 0x92, 0x91, 0x37, 0x08, 0x50, 0xd6, 0x28, 0x09, 0x27, 0xa1, 0x0c, 0x00,
/* (2^340)P */ 0x1f, 0xbb, 0x21, 0x26, 0x33, 0xcb, 0xa4, 0xd1, 0xee, 0x85, 0xf9, 0xd9, 0x3c, 0x90, 0xc3, 0xd1, 0x26, 0xa2, 0x25, 0x93, 0x43, 0x61, 0xed, 0x91, 0x6e, 0x54, 0x03, 0x2e, 0x42, 0x9d, 0xf7, 0xa6, 0x02, 0x0f, 0x2f, 0x9c, 0x7a, 0x8d, 0x12, 0xc2, 0x18, 0xfc, 0x41, 0xff, 0x85, 0x26, 0x1a, 0x44, 0x55, 0x0b, 0x89, 0xab, 0x6f, 0x62, 0x33, 0x8c,
/* (2^341)P */ 0xe0, 0x3c, 0x5d, 0x70, 0x64, 0x87, 0x81, 0x35, 0xf2, 0x37, 0xa6, 0x24, 0x3e, 0xe0, 0x62, 0xd5, 0x71, 0xe7, 0x93, 0xfb, 0xac, 0xc3, 0xe7, 0xc7, 0x04, 0xe2, 0x70, 0xd3, 0x29, 0x5b, 0x21, 0xbf, 0xf4, 0x26, 0x5d, 0xf3, 0x95, 0xb4, 0x2a, 0x6a, 0x07, 0x55, 0xa6, 0x4b, 0x3b, 0x15, 0xf2, 0x25, 0x8a, 0x95, 0x3f, 0x63, 0x2f, 0x7a, 0x23, 0x96,
/* (2^342)P */ 0x0d, 0x3d, 0xd9, 0x13, 0xa7, 0xb3, 0x5e, 0x67, 0xf7, 0x02, 0x23, 0xee, 0x84, 0xff, 0x99, 0xda, 0xb9, 0x53, 0xf8, 0xf0, 0x0e, 0x39, 0x2f, 0x3c, 0x64, 0x34, 0xe3, 0x09, 0xfd, 0x2b, 0x33, 0xc7, 0xfe, 0x62, 0x2b, 0x84, 0xdf, 0x2b, 0xd2, 0x7c, 0x26, 0x01, 0x70, 0x66, 0x5b, 0x85, 0xc2, 0xbe, 0x88, 0x37, 0xf1, 0x30, 0xac, 0xb8, 0x76, 0xa3,
/* (2^343)P */ 0x6e, 0x01, 0xf0, 0x55, 0x35, 0xe4, 0xbd, 0x43, 0x62, 0x9d, 0xd6, 0x11, 0xef, 0x6f, 0xb8, 0x8c, 0xaa, 0x98, 0x87, 0xc6, 0x6d, 0xc4, 0xcc, 0x74, 0x92, 0x53, 0x4a, 0xdf, 0xe4, 0x08, 0x89, 0x17, 0xd0, 0x0f, 0xf4, 0x00, 0x60, 0x78, 0x08, 0x44, 0xb5, 0xda, 0x18, 0xed, 0x98, 0xc8, 0x61, 0x3d, 0x39, 0xdb, 0xcf, 0x1d, 0x49, 0x40, 0x65, 0x75,
/* (2^344)P */ 0x8e, 0x10, 0xae, 0x5f, 0x06, 0xd2, 0x95, 0xfd, 0x20, 0x16, 0x49, 0x5b, 0x57, 0xbe, 0x22, 0x8b, 0x43, 0xfb, 0xe6, 0xcc, 0x26, 0xa5, 0x5d, 0xd3, 0x68, 0xc5, 0xf9, 0x5a, 0x86, 0x24, 0x87, 0x27, 0x05, 0xfd, 0xe2, 0xff, 0xb3, 0xa3, 0x7b, 0x37, 0x59, 0xc5, 0x4e, 0x14, 0x94, 0xf9, 0x3b, 0xcb, 0x7c, 0xed, 0xca, 0x1d, 0xb2, 0xac, 0x05, 0x4a,
/* (2^345)P */ 0xf4, 0xd1, 0x81, 0xeb, 0x89, 0xbf, 0xfe, 0x1e, 0x41, 0x92, 0x29, 0xee, 0xe1, 0x43, 0xf5, 0x86, 0x1d, 0x2f, 0xbb, 0x1e, 0x84, 0x5d, 0x7b, 0x8d, 0xd5, 0xda, 0xee, 0x1e, 0x8a, 0xd0, 0x27, 0xf2, 0x60, 0x51, 0x59, 0x82, 0xf4, 0x84, 0x2b, 0x5b, 0x14, 0x2d, 0x81, 0x82, 0x3e, 0x2b, 0xb4, 0x6d, 0x51, 0x4f, 0xc5, 0xcb, 0xbf, 0x74, 0xe3, 0xb4,
/* (2^346)P */ 0x19, 0x2f, 0x22, 0xb3, 0x04, 0x5f, 0x81, 0xca, 0x05, 0x60, 0xb9, 0xaa, 0xee, 0x0e, 0x2f, 0x48, 0x38, 0xf9, 0x91, 0xb4, 0x66, 0xe4, 0x57, 0x28, 0x54, 0x10, 0xe9, 0x61, 0x9d, 0xd4, 0x90, 0x75, 0xb1, 0x39, 0x23, 0xb6, 0xfc, 0x82, 0xe0, 0xfa, 0xbb, 0x5c, 0x6e, 0xc3, 0x44, 0x13, 0x00, 0x83, 0x55, 0x9e, 0x8e, 0x10, 0x61, 0x81, 0x91, 0x04,
/* (2^347)P */ 0x5f, 0x2a, 0xd7, 0x81, 0xd9, 0x9c, 0xbb, 0x79, 0xbc, 0x62, 0x56, 0x98, 0x03, 0x5a, 0x18, 0x85, 0x2a, 0x9c, 0xd0, 0xfb, 0xd2, 0xb1, 0xaf, 0xef, 0x0d, 0x24, 0xc5, 0xfa, 0x39, 0xbb, 0x6b, 0xed, 0xa4, 0xdf, 0xe4, 0x87, 0xcd, 0x41, 0xd3, 0x72, 0x32, 0xc6, 0x28, 0x21, 0xb1, 0xba, 0x8b, 0xa3, 0x91, 0x79, 0x76, 0x22, 0x25, 0x10, 0x61, 0xd1,
/* (2^348)P */ 0x73, 0xb5, 0x32, 0x97, 0xdd, 0xeb, 0xdd, 0x22, 0x22, 0xf1, 0x33, 0x3c, 0x77, 0x56, 0x7d, 0x6b, 0x48, 0x2b, 0x05, 0x81, 0x03, 0x03, 0x91, 0x9a, 0xe3, 0x5e, 0xd4, 0xee, 0x3f, 0xf8, 0xbb, 0x50, 0x21, 0x32, 0x4c, 0x4a, 0x58, 0x49, 0xde, 0x0c, 0xde, 0x30, 0x82, 0x3d, 0x92, 0xf0, 0x6c, 0xcc, 0x32, 0x3e, 0xd2, 0x78, 0x8a, 0x6e, 0x2c, 0xd0,
/* (2^349)P */ 0xf0, 0xf7, 0xa1, 0x0b, 0xc1, 0x74, 0x85, 0xa8, 0xe9, 0xdd, 0x48, 0xa1, 0xc0, 0x16, 0xd8, 0x2b, 0x61, 0x08, 0xc2, 0x2b, 0x30, 0x26, 0x79, 0xce, 0x9e, 0xfd, 0x39, 0xd7, 0x81, 0xa4, 0x63, 0x8c, 0xd5, 0x74, 0xa0, 0x88, 0xfa, 0x03, 0x30, 0xe9, 0x7f, 0x2b, 0xc6, 0x02, 0xc9, 0x5e, 0xe4, 0xd5, 0x4d, 0x92, 0xd0, 0xf6, 0xf2, 0x5b, 0x79, 0x08,
/* (2^350)P */ 0x34, 0x89, 0x81, 0x43, 0xd1, 0x94, 0x2c, 0x10, 0x54, 0x9b, 0xa0, 0xe5, 0x44, 0xe8, 0xc2, 0x2f, 0x3e, 0x0e, 0x74, 0xae, 0xba, 0xe2, 0xac, 0x85, 0x6b, 0xd3, 0x5c, 0x97, 0xf7, 0x90, 0xf1, 0x12, 0xc0, 0x03, 0xc8, 0x1f, 0x37, 0x72, 0x8c, 0x9b, 0x9c, 0x17, 0x96, 0x9d, 0xc7, 0xbf, 0xa3, 0x3f, 0x44, 0x3d, 0x87, 0x81, 0xbd, 0x81, 0xa6, 0x5f,
/* (2^351)P */ 0xe4, 0xff, 0x78, 0x62, 0x82, 0x5b, 0x76, 0x58, 0xf5, 0x5b, 0xa6, 0xc4, 0x53, 0x11, 0x3b, 0x7b, 0xaa, 0x67, 0xf8, 0xea, 0x3b, 0x5d, 0x9a, 0x2e, 0x04, 0xeb, 0x4a, 0x24, 0xfb, 0x56, 0xf0, 0xa8, 0xd4, 0x14, 0xed, 0x0f, 0xfd, 0xc5, 0x26, 0x17, 0x2a, 0xf0, 0xb9, 0x13, 0x8c, 0xbd, 0x65, 0x14, 0x24, 0x95, 0x27, 0x12, 0x63, 0x2a, 0x09, 0x18,
/* (2^352)P */ 0xe1, 0x5c, 0xe7, 0xe0, 0x00, 0x6a, 0x96, 0xf2, 0x49, 0x6a, 0x39, 0xa5, 0xe0, 0x17, 0x79, 0x4a, 0x63, 0x07, 0x62, 0x09, 0x61, 0x1b, 0x6e, 0xa9, 0xb5, 0x62, 0xb7, 0xde, 0xdf, 0x80, 0x4c, 0x5a, 0x99, 0x73, 0x59, 0x9d, 0xfb, 0xb1, 0x5e, 0xbe, 0xb8, 0xb7, 0x63, 0x93, 0xe8, 0xad, 0x5e, 0x1f, 0xae, 0x59, 0x1c, 0xcd, 0xb4, 0xc2, 0xb3, 0x8a,
/* (2^353)P */ 0x78, 0x53, 0xa1, 0x4c, 0x70, 0x9c, 0x63, 0x7e, 0xb3, 0x12, 0x40, 0x5f, 0xbb, 0x23, 0xa7, 0xf7, 0x77, 0x96, 0x5b, 0x4d, 0x91, 0x10, 0x52, 0x85, 0x9e, 0xa5, 0x38, 0x0b, 0xfd, 0x25, 0x01, 0x4b, 0xfa, 0x4d, 0xd3, 0x3f, 0x78, 0x74, 0x42, 0xff, 0x62, 0x2d, 0x27, 0xdc, 0x9d, 0xd1, 0x29, 0x76, 0x2e, 0x78, 0xb3, 0x35, 0xfa, 0x15, 0xd5, 0x38,
/* (2^354)P */ 0x8b, 0xc7, 0x43, 0xce, 0xf0, 0x5e, 0xf1, 0x0d, 0x02, 0x38, 0xe8, 0x82, 0xc9, 0x25, 0xad, 0x2d, 0x27, 0xa4, 0x54, 0x18, 0xb2, 0x30, 0x73, 0xa4, 0x41, 0x08, 0xe4, 0x86, 0xe6, 0x8c, 0xe9, 0x2a, 0x34, 0xb3, 0xd6, 0x61, 0x8f, 0x66, 0x26, 0x08, 0xb6, 0x06, 0x33, 0xaa, 0x12, 0xac, 0x72, 0xec, 0x2e, 0x52, 0xa3, 0x25, 0x3e, 0xd7, 0x62, 0xe8,
/* (2^355)P */ 0xc4, 0xbb, 0x89, 0xc8, 0x40, 0xcc, 0x84, 0xec, 0x4a, 0xd9, 0xc4, 0x55, 0x78, 0x00, 0xcf, 0xd8, 0xe9, 0x24, 0x59, 0xdc, 0x5e, 0xf0, 0x66, 0xa1, 0x83, 0xae, 0x97, 0x18, 0xc5, 0x54, 0x27, 0xa2, 0x21, 0x52, 0x03, 0x31, 0x5b, 0x11, 0x67, 0xf6, 0x12, 0x00, 0x87, 0x2f, 0xff, 0x59, 0x70, 0x8f, 0x6d, 0x71, 0xab, 0xab, 0x24, 0xb8, 0xba, 0x35,
/* (2^356)P */ 0x69, 0x43, 0xa7, 0x14, 0x06, 0x96, 0xe9, 0xc2, 0xe3, 0x2b, 0x45, 0x22, 0xc0, 0xd0, 0x2f, 0x34, 0xd1, 0x01, 0x99, 0xfc, 0x99, 0x38, 0xa1, 0x25, 0x2e, 0x59, 0x6c, 0x27, 0xc9, 0xeb, 0x7b, 0xdc, 0x4e, 0x26, 0x68, 0xba, 0xfa, 0xec, 0x02, 0x05, 0x64, 0x80, 0x30, 0x20, 0x5c, 0x26, 0x7f, 0xaf, 0x95, 0x17, 0x3d, 0x5c, 0x9e, 0x96, 0x96, 0xaf,
/* (2^357)P */ 0xa6, 0xba, 0x21, 0x29, 0x32, 0xe2, 0x98, 0xde, 0x9b, 0x6d, 0x0b, 0x44, 0x91, 0xa8, 0x3e, 0xd4, 0xb8, 0x04, 0x6c, 0xf6, 0x04, 0x39, 0xbd, 0x52, 0x05, 0x15, 0x27, 0x78, 0x8e, 0x55, 0xac, 0x79, 0xc5, 0xe6, 0x00, 0x7f, 0x90, 0xa2, 0xdd, 0x07, 0x13, 0xe0, 0x24, 0x70, 0x5c, 0x0f, 0x4d, 0xa9, 0xf9, 0xae, 0xcb, 0x34, 0x10, 0x9d, 0x89, 0x9d,
/* (2^358)P */ 0x12, 0xe0, 0xb3, 0x9f, 0xc4, 0x96, 0x1d, 0xcf, 0xed, 0x99, 0x64, 0x28, 0x8d, 0xc7, 0x31, 0x82, 0xee, 0x5e, 0x75, 0x48, 0xff, 0x3a, 0xf2, 0x09, 0x34, 0x03, 0x93, 0x52, 0x19, 0xb2, 0xc5, 0x81, 0x93, 0x45, 0x5e, 0x59, 0x21, 0x2b, 0xec, 0x89, 0xba, 0x36, 0x6e, 0xf9, 0x82, 0x75, 0x7e, 0x82, 0x3f, 0xaa, 0xe2, 0xe3, 0x3b, 0x94, 0xfd, 0x98,
/* (2^359)P */ 0x7c, 0xdb, 0x75, 0x31, 0x61, 0xfb, 0x15, 0x28, 0x94, 0xd7, 0xc3, 0x5a, 0xa9, 0xa1, 0x0a, 0x66, 0x0f, 0x2b, 0x13, 0x3e, 0x42, 0xb5, 0x28, 0x3a, 0xca, 0x83, 0xf3, 0x61, 0x22, 0xf4, 0x40, 0xc5, 0xdf, 0xe7, 0x31, 0x9f, 0x7e, 0x51, 0x75, 0x06, 0x9d, 0x51, 0xc8, 0xe7, 0x9f, 0xc3, 0x71, 0x4f, 0x3d, 0x5b, 0xfb, 0xe9, 0x8e, 0x08, 0x40, 0x8e,
/* (2^360)P */ 0xf7, 0x31, 0xad, 0x50, 0x5d, 0x25, 0x93, 0x73, 0x68, 0xf6, 0x7c, 0x89, 0x5a, 0x3d, 0x9f, 0x9b, 0x05, 0x82, 0xe7, 0x70, 0x4b, 0x19, 0xaa, 0xcf, 0xff, 0xde, 0x50, 0x8f, 0x2f, 0x69, 0xd3, 0xf0, 0x99, 0x51, 0x6b, 0x9d, 0xb6, 0x56, 0x6f, 0xf8, 0x4c, 0x74, 0x8b, 0x4c, 0x91, 0xf9, 0xa9, 0xb1, 0x3e, 0x07, 0xdf, 0x0b, 0x27, 0x8a, 0xb1, 0xed,
/* (2^361)P */ 0xfb, 0x67, 0xd9, 0x48, 0xd2, 0xe4, 0x44, 0x9b, 0x43, 0x15, 0x8a, 0xeb, 0x00, 0x53, 0xad, 0x25, 0xc7, 0x7e, 0x19, 0x30, 0x87, 0xb7, 0xd5, 0x5f, 0x04, 0xf8, 0xaa, 0xdd, 0x57, 0xae, 0x34, 0x75, 0xe2, 0x84, 0x4b, 0x54, 0x60, 0x37, 0x95, 0xe4, 0xd3, 0xec, 0xac, 0xef, 0x47, 0x31, 0xa3, 0xc8, 0x31, 0x22, 0xdb, 0x26, 0xe7, 0x6a, 0xb5, 0xad,
/* (2^362)P */ 0x44, 0x09, 0x5c, 0x95, 0xe4, 0x72, 0x3c, 0x1a, 0xd1, 0xac, 0x42, 0x51, 0x99, 0x6f, 0xfa, 0x1f, 0xf2, 0x22, 0xbe, 0xff, 0x7b, 0x66, 0xf5, 0x6c, 0xb3, 0x66, 0xc7, 0x4d, 0x78, 0x31, 0x83, 0x80, 0xf5, 0x41, 0xe9, 0x7f, 0xbe, 0xf7, 0x23, 0x49, 0x6b, 0x84, 0x4e, 0x7e, 0x47, 0x07, 0x6e, 0x74, 0xdf, 0xe5, 0x9d, 0x9e, 0x56, 0x2a, 0xc0, 0xbc,
/* (2^363)P */ 0xac, 0x10, 0x80, 0x8c, 0x7c, 0xfa, 0x83, 0xdf, 0xb3, 0xd0, 0xc4, 0xbe, 0xfb, 0x9f, 0xac, 0xc9, 0xc3, 0x40, 0x95, 0x0b, 0x09, 0x23, 0xda, 0x63, 0x67, 0xcf, 0xe7, 0x9f, 0x7d, 0x7b, 0x6b, 0xe2, 0xe6, 0x6d, 0xdb, 0x87, 0x9e, 0xa6, 0xff, 0x6d, 0xab, 0xbd, 0xfb, 0x54, 0x84, 0x68, 0xcf, 0x89, 0xf1, 0xd0, 0xe2, 0x85, 0x61, 0xdc, 0x22, 0xd1,
/* (2^364)P */ 0xa8, 0x48, 0xfb, 0x8c, 0x6a, 0x63, 0x01, 0x72, 0x43, 0x43, 0xeb, 0x21, 0xa3, 0x00, 0x8a, 0xc0, 0x87, 0x51, 0x9e, 0x86, 0x75, 0x16, 0x79, 0xf9, 0x6b, 0x11, 0x80, 0x62, 0xc2, 0x9d, 0xb8, 0x8c, 0x30, 0x8e, 0x8d, 0x03, 0x52, 0x7e, 0x31, 0x59, 0x38, 0xf9, 0x25, 0xc7, 0x0f, 0xc7, 0xa8, 0x2b, 0x5c, 0x80, 0xfa, 0x90, 0xa2, 0x63, 0xca, 0xe7,
/* (2^365)P */ 0xf1, 0x5d, 0xb5, 0xd9, 0x20, 0x10, 0x7d, 0x0f, 0xc5, 0x50, 0x46, 0x07, 0xff, 0x02, 0x75, 0x2b, 0x4a, 0xf3, 0x39, 0x91, 0x72, 0xb7, 0xd5, 0xcc, 0x38, 0xb8, 0xe7, 0x36, 0x26, 0x5e, 0x11, 0x97, 0x25, 0xfb, 0x49, 0x68, 0xdc, 0xb4, 0x46, 0x87, 0x5c, 0xc2, 0x7f, 0xaa, 0x7d, 0x36, 0x23, 0xa6, 0xc6, 0x53, 0xec, 0xbc, 0x57, 0x47, 0xc1, 0x2b,
/* (2^366)P */ 0x25, 0x5d, 0x7d, 0x95, 0xda, 0x0b, 0x8f, 0x78, 0x1e, 0x19, 0x09, 0xfa, 0x67, 0xe0, 0xa0, 0x17, 0x24, 0x76, 0x6c, 0x30, 0x1f, 0x62, 0x3d, 0xbe, 0x45, 0x70, 0xcc, 0xb6, 0x1e, 0x68, 0x06, 0x25, 0x68, 0x16, 0x1a, 0x33, 0x3f, 0x90, 0xc7, 0x78, 0x2d, 0x98, 0x3c, 0x2f, 0xb9, 0x2d, 0x94, 0x0b, 0xfb, 0x49, 0x56, 0x30, 0xd7, 0xc1, 0xe6, 0x48,
/* (2^367)P */ 0x7a, 0xd1, 0xe0, 0x8e, 0x67, 0xfc, 0x0b, 0x50, 0x1f, 0x84, 0x98, 0xfa, 0xaf, 0xae, 0x2e, 0x31, 0x27, 0xcf, 0x3f, 0xf2, 0x6e, 0x8d, 0x81, 0x8f, 0xd2, 0x5f, 0xde, 0xd3, 0x5e, 0xe9, 0xe7, 0x13, 0x48, 0x83, 0x5a, 0x4e, 0x84, 0xd1, 0x58, 0xcf, 0x6b, 0x84, 0xdf, 0x13, 0x1d, 0x91, 0x85, 0xe8, 0xcb, 0x29, 0x79, 0xd2, 0xca, 0xac, 0x6a, 0x93,
/* (2^368)P */ 0x53, 0x82, 0xce, 0x61, 0x96, 0x88, 0x6f, 0xe1, 0x4a, 0x4c, 0x1e, 0x30, 0x73, 0xe8, 0x74, 0xde, 0x40, 0x2b, 0xe0, 0xc4, 0xb5, 0xd8, 0x7c, 0x15, 0xe7, 0xe1, 0xb1, 0xe0, 0xd6, 0x88, 0xb1, 0x6a, 0x57, 0x19, 0x6a, 0x22, 0x66, 0x57, 0xf6, 0x8d, 0xfd, 0xc0, 0xf2, 0xa3, 0x03, 0x56, 0xfb, 0x2e, 0x75, 0x5e, 0xc7, 0x8e, 0x22, 0x96, 0x5c, 0x06,
/* (2^369)P */ 0x98, 0x7e, 0xbf, 0x3e, 0xbf, 0x24, 0x9d, 0x15, 0xd3, 0xf6, 0xd3, 0xd2, 0xf0, 0x11, 0xf2, 0xdb, 0x36, 0x23, 0x38, 0xf7, 0x1d, 0x71, 0x20, 0xd2, 0x54, 0x7f, 0x1e, 0x24, 0x8f, 0xe2, 0xaa, 0xf7, 0x3f, 0x6b, 0x41, 0x4e, 0xdc, 0x0e, 0xec, 0xe8, 0x35, 0x0a, 0x08, 0x6d, 0x89, 0x5b, 0x32, 0x91, 0x01, 0xb6, 0xe0, 0x2c, 0xc6, 0xa1, 0xbe, 0xb4,
/* (2^370)P */ 0x29, 0xf2, 0x1e, 0x1c, 0xdc, 0x68, 0x8a, 0x43, 0x87, 0x2c, 0x48, 0xb3, 0x9e, 0xed, 0xd2, 0x82, 0x46, 0xac, 0x2f, 0xef, 0x93, 0x34, 0x37, 0xca, 0x64, 0x8d, 0xc9, 0x06, 0x90, 0xbb, 0x78, 0x0a, 0x3c, 0x4c, 0xcf, 0x35, 0x7a, 0x0f, 0xf7, 0xa7, 0xf4, 0x2f, 0x45, 0x69, 0x3f, 0xa9, 0x5d, 0xce, 0x7b, 0x8a, 0x84, 0xc3, 0xae, 0xf4, 0xda, 0xd5,
/* (2^371)P */ 0xca, 0xba, 0x95, 0x43, 0x05, 0x7b, 0x06, 0xd9, 0x5c, 0x0a, 0x18, 0x5f, 0x6a, 0x6a, 0xce, 0xc0, 0x3d, 0x95, 0x51, 0x0e, 0x1a, 0xbe, 0x85, 0x7a, 0xf2, 0x69, 0xec, 0xc0, 0x8c, 0xca, 0xa3, 0x32, 0x0a, 0x76, 0x50, 0xc6, 0x76, 0x61, 0x00, 0x89, 0xbf, 0x6e, 0x0f, 0x48, 0x90, 0x31, 0x93, 0xec, 0x34, 0x70, 0xf0, 0xc3, 0x8d, 0xf0, 0x0f, 0xb5,
/* (2^372)P */ 0xbe, 0x23, 0xe2, 0x18, 0x99, 0xf1, 0xed, 0x8a, 0xf6, 0xc9, 0xac, 0xb8, 0x1e, 0x9a, 0x3c, 0x15, 0xae, 0xd7, 0x6d, 0xb3, 0x04, 0xee, 0x5b, 0x0d, 0x1e, 0x79, 0xb7, 0xf9, 0xf9, 0x8d, 0xad, 0xf9, 0x8f, 0x5a, 0x6a, 0x7b, 0xd7, 0x9b, 0xca, 0x62, 0xfe, 0x9c, 0xc0, 0x6f, 0x6d, 0x9d, 0x76, 0xa3, 0x69, 0xb9, 0x4c, 0xa1, 0xc4, 0x0c, 0x76, 0xaa,
/* (2^373)P */ 0x1c, 0x06, 0xfe, 0x3f, 0x45, 0x70, 0xcd, 0x97, 0xa9, 0xa2, 0xb1, 0xd3, 0xf2, 0xa5, 0x0c, 0x49, 0x2c, 0x75, 0x73, 0x1f, 0xcf, 0x00, 0xaf, 0xd5, 0x2e, 0xde, 0x0d, 0x8f, 0x8f, 0x7c, 0xc4, 0x58, 0xce, 0xd4, 0xf6, 0x24, 0x19, 0x2e, 0xd8, 0xc5, 0x1d, 0x1a, 0x3f, 0xb8, 0x4f, 0xbc, 0x7d, 0xbd, 0x68, 0xe3, 0x81, 0x98, 0x1b, 0xa8, 0xc9, 0xd9,
/* (2^374)P */ 0x39, 0x95, 0x78, 0x24, 0x6c, 0x38, 0xe4, 0xe7, 0xd0, 0x8d, 0xb9, 0x38, 0x71, 0x5e, 0xc1, 0x62, 0x80, 0xcc, 0xcb, 0x8c, 0x97, 0xca, 0xf8, 0xb9, 0xd9, 0x9c, 0xce, 0x72, 0x7b, 0x70, 0xee, 0x5f, 0xea, 0xa2, 0xdf, 0xa9, 0x14, 0x10, 0xf9, 0x6e, 0x59, 0x9f, 0x9c, 0xe0, 0x0c, 0xb2, 0x07, 0x97, 0xcd, 0xd2, 0x89, 0x16, 0xfd, 0x9c, 0xa8, 0xa5,
/* (2^375)P */ 0x5a, 0x61, 0xf1, 0x59, 0x7c, 0x38, 0xda, 0xe2, 0x85, 0x99, 0x68, 0xe9, 0xc9, 0xf7, 0x32, 0x7e, 0xc4, 0xca, 0xb7, 0x11, 0x08, 0x69, 0x2b, 0x66, 0x02, 0xf7, 0x2e, 0x18, 0xc3, 0x8e, 0xe1, 0xf9, 0xc5, 0x19, 0x9a, 0x0a, 0x9c, 0x07, 0xba, 0xc7, 0x9c, 0x03, 0x34, 0x89, 0x99, 0x67, 0x0b, 0x16, 0x4b, 0x07, 0x36, 0x16, 0x36, 0x2c, 0xe2, 0xa1,
/* (2^376)P */ 0x70, 0x10, 0x91, 0x27, 0xa8, 0x24, 0x8e, 0x29, 0x04, 0x6f, 0x79, 0x1f, 0xd3, 0xa5, 0x68, 0xd3, 0x0b, 0x7d, 0x56, 0x4d, 0x14, 0x57, 0x7b, 0x2e, 0x00, 0x9f, 0x9a, 0xfd, 0x6c, 0x63, 0x18, 0x81, 0xdb, 0x9d, 0xb7, 0xd7, 0xa4, 0x1e, 0xe8, 0x40, 0xf1, 0x4c, 0xa3, 0x01, 0xd5, 0x4b, 0x75, 0xea, 0xdd, 0x97, 0xfd, 0x5b, 0xb2, 0x66, 0x6a, 0x24,
/* (2^377)P */ 0x72, 0x11, 0xfe, 0x73, 0x1b, 0xd3, 0xea, 0x7f, 0x93, 0x15, 0x15, 0x05, 0xfe, 0x40, 0xe8, 0x28, 0xd8, 0x50, 0x47, 0x66, 0xfa, 0xb7, 0xb5, 0x04, 0xba, 0x35, 0x1e, 0x32, 0x9f, 0x5f, 0x32, 0xba, 0x3d, 0xd1, 0xed, 0x9a, 0x76, 0xca, 0xa3, 0x3e, 0x77, 0xd8, 0xd8, 0x7c, 0x5f, 0x68, 0x42, 0xb5, 0x86, 0x7f, 0x3b, 0xc9, 0xc1, 0x89, 0x64, 0xda,
/* (2^378)P */ 0xd5, 0xd4, 0x17, 0x31, 0xfc, 0x6a, 0xfd, 0xb8, 0xe8, 0xe5, 0x3e, 0x39, 0x06, 0xe4, 0xd1, 0x90, 0x2a, 0xca, 0xf6, 0x54, 0x6c, 0x1b, 0x2f, 0x49, 0x97, 0xb1, 0x2a, 0x82, 0x43, 0x3d, 0x1f, 0x8b, 0xe2, 0x47, 0xc5, 0x24, 0xa8, 0xd5, 0x53, 0x29, 0x7d, 0xc6, 0x87, 0xa6, 0x25, 0x3a, 0x64, 0xdd, 0x71, 0x08, 0x9e, 0xcd, 0xe9, 0x45, 0xc7, 0xba,
/* (2^379)P */ 0x37, 0x72, 0x6d, 0x13, 0x7a, 0x8d, 0x04, 0x31, 0xe6, 0xe3, 0x9e, 0x36, 0x71, 0x3e, 0xc0, 0x1e, 0xe3, 0x71, 0xd3, 0x49, 0x4e, 0x4a, 0x36, 0x42, 0x68, 0x68, 0x61, 0xc7, 0x3c, 0xdb, 0x81, 0x49, 0xf7, 0x91, 0x4d, 0xea, 0x4c, 0x4f, 0x98, 0xc6, 0x7e, 0x60, 0x84, 0x4b, 0x6a, 0x37, 0xbb, 0x52, 0xf7, 0xce, 0x02, 0xe4, 0xad, 0xd1, 0x3c, 0xa7,
/* (2^380)P */ 0x51, 0x06, 0x2d, 0xf8, 0x08, 0xe8, 0xf1, 0x0c, 0xe5, 0xa9, 0xac, 0x29, 0x73, 0x3b, 0xed, 0x98, 0x5f, 0x55, 0x08, 0x38, 0x51, 0x44, 0x36, 0x5d, 0xea, 0xc3, 0xb8, 0x0e, 0xa0, 0x4f, 0xd2, 0x79, 0xe9, 0x98, 0xc3, 0xf5, 0x00, 0xb9, 0x26, 0x27, 0x42, 0xa8, 0x07, 0xc1, 0x12, 0x31, 0xc1, 0xc3, 0x3c, 0x3b, 0x7a, 0x72, 0x97, 0xc2, 0x70, 0x3a,
/* (2^381)P */ 0xf4, 0xb2, 0xba, 0x32, 0xbc, 0xa9, 0x2f, 0x87, 0xc7, 0x3c, 0x45, 0xcd, 0xae, 0xe2, 0x13, 0x6d, 0x3a, 0xf2, 0xf5, 0x66, 0x97, 0x29, 0xaf, 0x53, 0x9f, 0xda, 0xea, 0x14, 0xdf, 0x04, 0x98, 0x19, 0x95, 0x9e, 0x2a, 0x00, 0x5c, 0x9d, 0x1d, 0xf0, 0x39, 0x23, 0xff, 0xfc, 0xca, 0x36, 0xb7, 0xde, 0xdf, 0x37, 0x78, 0x52, 0x21, 0xfa, 0x19, 0x10,
/* (2^382)P */ 0x50, 0x20, 0x73, 0x74, 0x62, 0x21, 0xf2, 0xf7, 0x9b, 0x66, 0x85, 0x34, 0x74, 0xd4, 0x9d, 0x60, 0xd7, 0xbc, 0xc8, 0x46, 0x3b, 0xb8, 0x80, 0x42, 0x15, 0x0a, 0x6c, 0x35, 0x1a, 0x69, 0xf0, 0x1d, 0x4b, 0x29, 0x54, 0x5a, 0x9a, 0x48, 0xec, 0x9f, 0x37, 0x74, 0x91, 0xd0, 0xd1, 0x9e, 0x00, 0xc2, 0x76, 0x56, 0xd6, 0xa0, 0x15, 0x14, 0x83, 0x59,
/* (2^383)P */ 0xc2, 0xf8, 0x22, 0x20, 0x23, 0x07, 0xbd, 0x1d, 0x6f, 0x1e, 0x8c, 0x56, 0x06, 0x6a, 0x4b, 0x9f, 0xe2, 0xa9, 0x92, 0x46, 0x4b, 0x46, 0x59, 0xd7, 0xe1, 0xda, 0x14, 0x98, 0x07, 0x65, 0x7e, 0x28, 0x20, 0xf2, 0x9d, 0x4f, 0x36, 0x5c, 0x92, 0xe0, 0x9d, 0xfe, 0x3e, 0xda, 0xe4, 0x47, 0x19, 0x3c, 0x00, 0x7f, 0x22, 0xf2, 0x9e, 0x51, 0xae, 0x4d,
/* (2^384)P */ 0xbe, 0x8c, 0x1b, 0x10, 0xb6, 0xad, 0xcc, 0xcc, 0xd8, 0x5e, 0x21, 0xa6, 0xfb, 0xf1, 0xf6, 0xbd, 0x0a, 0x24, 0x67, 0xb4, 0x57, 0x7a, 0xbc, 0xe8, 0xe9, 0xff, 0xee, 0x0a, 0x1f, 0xee, 0xbd, 0xc8, 0x44, 0xed, 0x2b, 0xbb, 0x55, 0x1f, 0xdd, 0x7c, 0xb3, 0xeb, 0x3f, 0x63, 0xa1, 0x28, 0x91, 0x21, 0xab, 0x71, 0xc6, 0x4c, 0xd0, 0xe9, 0xb0, 0x21,
/* (2^385)P */ 0xad, 0xc9, 0x77, 0x2b, 0xee, 0x89, 0xa4, 0x7b, 0xfd, 0xf9, 0xf6, 0x14, 0xe4, 0xed, 0x1a, 0x16, 0x9b, 0x78, 0x41, 0x43, 0xa8, 0x83, 0x72, 0x06, 0x2e, 0x7c, 0xdf, 0xeb, 0x7e, 0xdd, 0xd7, 0x8b, 0xea, 0x9a, 0x2b, 0x03, 0xba, 0x57, 0xf3, 0xf1, 0xd9, 0xe5, 0x09, 0xc5, 0x98, 0x61, 0x1c, 0x51, 0x6d, 0x5d, 0x6e, 0xfb, 0x5e, 0x95, 0x9f, 0xb5,
/* (2^386)P */ 0x23, 0xe2, 0x1e, 0x95, 0xa3, 0x5e, 0x42, 0x10, 0xc7, 0xc3, 0x70, 0xbf, 0x4b, 0x6b, 0x83, 0x36, 0x93, 0xb7, 0x68, 0x47, 0x88, 0x3a, 0x10, 0x88, 0x48, 0x7f, 0x8c, 0xae, 0x54, 0x10, 0x02, 0xa4, 0x52, 0x8f, 0x8d, 0xf7, 0x26, 0x4f, 0x50, 0xc3, 0x6a, 0xe2, 0x4e, 0x3b, 0x4c, 0xb9, 0x8a, 0x14, 0x15, 0x6d, 0x21, 0x29, 0xb3, 0x6e, 0x4e, 0xd0,
/* (2^387)P */ 0x4c, 0x8a, 0x18, 0x3f, 0xb7, 0x20, 0xfd, 0x3e, 0x54, 0xca, 0x68, 0x3c, 0xea, 0x6f, 0xf4, 0x6b, 0xa2, 0xbd, 0x01, 0xbd, 0xfe, 0x08, 0xa8, 0xd8, 0xc2, 0x20, 0x36, 0x05, 0xcd, 0xe9, 0xf3, 0x9e, 0xfa, 0x85, 0x66, 0x8f, 0x4b, 0x1d, 0x8c, 0x64, 0x4f, 0xb8, 0xc6, 0x0f, 0x5b, 0x57, 0xd8, 0x24, 0x19, 0x5a, 0x14, 0x4b, 0x92, 0xd3, 0x96, 0xbc,
/* (2^388)P */ 0xa9, 0x3f, 0xc9, 0x6c, 0xca, 0x64, 0x1e, 0x6f, 0xdf, 0x65, 0x7f, 0x9a, 0x47, 0x6b, 0x8a, 0x60, 0x31, 0xa6, 0x06, 0xac, 0x69, 0x30, 0xe6, 0xea, 0x63, 0x42, 0x26, 0x5f, 0xdb, 0xd0, 0xf2, 0x8e, 0x34, 0x0a, 0x3a, 0xeb, 0xf3, 0x79, 0xc8, 0xb7, 0x60, 0x56, 0x5c, 0x37, 0x95, 0x71, 0xf8, 0x7f, 0x49, 0x3e, 0x9e, 0x01, 0x26, 0x1e, 0x80, 0x9f,
/* (2^389)P */ 0xf8, 0x16, 0x9a, 0xaa, 0xb0, 0x28, 0xb5, 0x8e, 0xd0, 0x60, 0xe5, 0x26, 0xa9, 0x47, 0xc4, 0x5c, 0xa9, 0x39, 0xfe, 0x0a, 0xd8, 0x07, 0x2b, 0xb3, 0xce, 0xf1, 0xea, 0x1a, 0xf4, 0x7b, 0x98, 0x31, 0x3d, 0x13, 0x29, 0x80, 0xe8, 0x0d, 0xcf, 0x56, 0x39, 0x86, 0x50, 0x0c, 0xb3, 0x18, 0xf4, 0xc5, 0xca, 0xf2, 0x6f, 0xcd, 0x8d, 0xd5, 0x02, 0xb0,
/* (2^390)P */ 0xbf, 0x39, 0x3f, 0xac, 0x6d, 0x1a, 0x6a, 0xe4, 0x42, 0x24, 0xd6, 0x41, 0x9d, 0xb9, 0x5b, 0x46, 0x73, 0x93, 0x76, 0xaa, 0xb7, 0x37, 0x36, 0xa6, 0x09, 0xe5, 0x04, 0x3b, 0x66, 0xc4, 0x29, 0x3e, 0x41, 0xc2, 0xcb, 0xe5, 0x17, 0xd7, 0x34, 0x67, 0x1d, 0x2c, 0x12, 0xec, 0x24, 0x7a, 0x40, 0xa2, 0x45, 0x41, 0xf0, 0x75, 0xed, 0x43, 0x30, 0xc9,
/* (2^391)P */ 0x80, 0xf6, 0x47, 0x5b, 0xad, 0x54, 0x02, 0xbc, 0xdd, 0xa4, 0xb2, 0xd7, 0x42, 0x95, 0xf2, 0x0d, 0x1b, 0xef, 0x37, 0xa7, 0xb4, 0x34, 0x04, 0x08, 0x71, 0x1b, 0xd3, 0xdf, 0xa1, 0xf0, 0x2b, 0xfa, 0xc0, 0x1f, 0xf3, 0x44, 0xb5, 0xc6, 0x47, 0x3d, 0x65, 0x67, 0x45, 0x4d, 0x2f, 0xde, 0x52, 0x73, 0xfc, 0x30, 0x01, 0x6b, 0xc1, 0x03, 0xd8, 0xd7,
/* (2^392)P */ 0x1c, 0x67, 0x55, 0x3e, 0x01, 0x17, 0x0f, 0x3e, 0xe5, 0x34, 0x58, 0xfc, 0xcb, 0x71, 0x24, 0x74, 0x5d, 0x36, 0x1e, 0x89, 0x2a, 0x63, 0xf8, 0xf8, 0x9f, 0x50, 0x9f, 0x32, 0x92, 0x29, 0xd8, 0x1a, 0xec, 0x76, 0x57, 0x6c, 0x67, 0x12, 0x6a, 0x6e, 0xef, 0x97, 0x1f, 0xc3, 0x77, 0x60, 0x3c, 0x22, 0xcb, 0xc7, 0x04, 0x1a, 0x89, 0x2d, 0x10, 0xa6,
/* (2^393)P */ 0x12, 0xf5, 0xa9, 0x26, 0x16, 0xd9, 0x3c, 0x65, 0x5d, 0x83, 0xab, 0xd1, 0x70, 0x6b, 0x1c, 0xdb, 0xe7, 0x86, 0x0d, 0xfb, 0xe7, 0xf8, 0x2a, 0x58, 0x6e, 0x7a, 0x66, 0x13, 0x53, 0x3a, 0x6f, 0x8d, 0x43, 0x5f, 0x14, 0x23, 0x14, 0xff, 0x3d, 0x52, 0x7f, 0xee, 0xbd, 0x7a, 0x34, 0x8b, 0x35, 0x24, 0xc3, 0x7a, 0xdb, 0xcf, 0x22, 0x74, 0x9a, 0x8f,
/* (2^394)P */ 0xdb, 0x20, 0xfc, 0xe5, 0x39, 0x4e, 0x7d, 0x78, 0xee, 0x0b, 0xbf, 0x1d, 0x80, 0xd4, 0x05, 0x4f, 0xb9, 0xd7, 0x4e, 0x94, 0x88, 0x9a, 0x50, 0x78, 0x1a, 0x70, 0x8c, 0xcc, 0x25, 0xb6, 0x61, 0x09, 0xdc, 0x7b, 0xea, 0x3f, 0x7f, 0xea, 0x2a, 0x0d, 0x47, 0x1c, 0x8e, 0xa6, 0x5b, 0xd2, 0xa3, 0x61, 0x93, 0x3c, 0x68, 0x9f, 0x8b, 0xea, 0xb0, 0xcb,
/* (2^395)P */ 0xff, 0x54, 0x02, 0x19, 0xae, 0x8b, 0x4c, 0x2c, 0x3a, 0xe0, 0xe4, 0xac, 0x87, 0xf7, 0x51, 0x45, 0x41, 0x43, 0xdc, 0xaa, 0xcd, 0xcb, 0xdc, 0x40, 0xe3, 0x44, 0x3b, 0x1d, 0x9e, 0x3d, 0xb9, 0x82, 0xcc, 0x7a, 0xc5, 0x12, 0xf8, 0x1e, 0xdd, 0xdb, 0x8d, 0xb0, 0x2a, 0xe8, 0xe6, 0x6c, 0x94, 0x3b, 0xb7, 0x2d, 0xba, 0x79, 0x3b, 0xb5, 0x86, 0xfb,
/* (2^396)P */ 0x82, 0x88, 0x13, 0xdd, 0x6c, 0xcd, 0x85, 0x2b, 0x90, 0x86, 0xb7, 0xac, 0x16, 0xa6, 0x6e, 0x6a, 0x94, 0xd8, 0x1e, 0x4e, 0x41, 0x0f, 0xce, 0x81, 0x6a, 0xa8, 0x26, 0x56, 0x43, 0x52, 0x52, 0xe6, 0xff, 0x88, 0xcf, 0x47, 0x05, 0x1d, 0xff, 0xf3, 0xa0, 0x10, 0xb2, 0x97, 0x87, 0xeb, 0x47, 0xbb, 0xfa, 0x1f, 0xe8, 0x4c, 0xce, 0xc4, 0xcd, 0x93,
/* (2^397)P */ 0xf4, 0x11, 0xf5, 0x8d, 0x89, 0x29, 0x79, 0xb3, 0x59, 0x0b, 0x29, 0x7d, 0x9c, 0x12, 0x4a, 0x65, 0x72, 0x3a, 0xf9, 0xec, 0x37, 0x18, 0x86, 0xef, 0x44, 0x07, 0x25, 0x74, 0x76, 0x53, 0xed, 0x51, 0x01, 0xc6, 0x28, 0xc5, 0xc3, 0x4a, 0x0f, 0x99, 0xec, 0xc8, 0x40, 0x5a, 0x83, 0x30, 0x79, 0xa2, 0x3e, 0x63, 0x09, 0x2d, 0x6f, 0x23, 0x54, 0x1c,
/* (2^398)P */ 0x5c, 0x6f, 0x3b, 0x1c, 0x30, 0x77, 0x7e, 0x87, 0x66, 0x83, 0x2e, 0x7e, 0x85, 0x50, 0xfd, 0xa0, 0x7a, 0xc2, 0xf5, 0x0f, 0xc1, 0x64, 0xe7, 0x0b, 0xbd, 0x59, 0xa7, 0xe7, 0x65, 0x53, 0xc3, 0xf5, 0x55, 0x5b, 0xe1, 0x82, 0x30, 0x5a, 0x61, 0xcd, 0xa0, 0x89, 0x32, 0xdb, 0x87, 0xfc, 0x21, 0x8a, 0xab, 0x6d, 0x82, 0xa8, 0x42, 0x81, 0x4f, 0xf2,
/* (2^399)P */ 0xb3, 0xeb, 0x88, 0x18, 0xf6, 0x56, 0x96, 0xbf, 0xba, 0x5d, 0x71, 0xa1, 0x5a, 0xd1, 0x04, 0x7b, 0xd5, 0x46, 0x01, 0x74, 0xfe, 0x15, 0x25, 0xb7, 0xff, 0x0c, 0x24, 0x47, 0xac, 0xfd, 0xab, 0x47, 0x32, 0xe1, 0x6a, 0x4e, 0xca, 0xcf, 0x7f, 0xdd, 0xf8, 0xd2, 0x4b, 0x3b, 0xf5, 0x17, 0xba, 0xba, 0x8b, 0xa1, 0xec, 0x28, 0x3f, 0x97, 0xab, 0x2a,
/* (2^400)P */ 0x51, 0x38, 0xc9, 0x5e, 0xc6, 0xb3, 0x64, 0xf2, 0x24, 0x4d, 0x04, 0x7d, 0xc8, 0x39, 0x0c, 0x4a, 0xc9, 0x73, 0x74, 0x1b, 0x5c, 0xb2, 0xc5, 0x41, 0x62, 0xa0, 0x4c, 0x6d, 0x8d, 0x91, 0x9a, 0x7b, 0x88, 0xab, 0x9c, 0x7e, 0x23, 0xdb, 0x6f, 0xb5, 0x72, 0xd6, 0x47, 0x40, 0xef, 0x22, 0x58, 0x62, 0x19, 0x6c, 0x38, 0xba, 0x5b, 0x00, 0x30, 0x9f,
/* (2^401)P */ 0x65, 0xbb, 0x3b, 0x9b, 0xe9, 0xae, 0xbf, 0xbe, 0xe4, 0x13, 0x95, 0xf3, 0xe3, 0x77, 0xcb, 0xe4, 0x9a, 0x22, 0xb5, 0x4a, 0x08, 0x9d, 0xb3, 0x9e, 0x27, 0xe0, 0x15, 0x6c, 0x9f, 0x7e, 0x9a, 0x5e, 0x15, 0x45, 0x25, 0x8d, 0x01, 0x0a, 0xd2, 0x2b, 0xbd, 0x48, 0x06, 0x0d, 0x18, 0x97, 0x4b, 0xdc, 0xbc, 0xf0, 0xcd, 0xb2, 0x52, 0x3c, 0xac, 0xf5,
/* (2^402)P */ 0x3e, 0xed, 0x47, 0x6b, 0x5c, 0xf6, 0x76, 0xd0, 0xe9, 0x15, 0xa3, 0xcb, 0x36, 0x00, 0x21, 0xa3, 0x79, 0x20, 0xa5, 0x3e, 0x88, 0x03, 0xcb, 0x7e, 0x63, 0xbb, 0xed, 0xa9, 0x13, 0x35, 0x16, 0xaf, 0x2e, 0xb4, 0x70, 0x14, 0x93, 0xfb, 0xc4, 0x9b, 0xd8, 0xb1, 0xbe, 0x43, 0xd1, 0x85, 0xb8, 0x97, 0xef, 0xea, 0x88, 0xa1, 0x25, 0x52, 0x62, 0x75,
/* (2^403)P */ 0x8e, 0x4f, 0xaa, 0x23, 0x62, 0x7e, 0x2b, 0x37, 0x89, 0x00, 0x11, 0x30, 0xc5, 0x33, 0x4a, 0x89, 0x8a, 0xe2, 0xfc, 0x5c, 0x6a, 0x75, 0xe5, 0xf7, 0x02, 0x4a, 0x9b, 0xf7, 0xb5, 0x6a, 0x85, 0x31, 0xd3, 0x5a, 0xcf, 0xc3, 0xf8, 0xde, 0x2f, 0xcf, 0xb5, 0x24, 0xf4, 0xe3, 0xa1, 0xad, 0x42, 0xae, 0x09, 0xb9, 0x2e, 0x04, 0x2d, 0x01, 0x22, 0x3f,
/* (2^404)P */ 0x41, 0x16, 0xfb, 0x7d, 0x50, 0xfd, 0xb5, 0xba, 0x88, 0x24, 0xba, 0xfd, 0x3d, 0xb2, 0x90, 0x15, 0xb7, 0xfa, 0xa2, 0xe1, 0x4c, 0x7d, 0xb9, 0xc6, 0xff, 0x81, 0x57, 0xb6, 0xc2, 0x9e, 0xcb, 0xc4, 0x35, 0xbd, 0x01, 0xb7, 0xaa, 0xce, 0xd0, 0xe9, 0xb5, 0xd6, 0x72, 0xbf, 0xd2, 0xee, 0xc7, 0xac, 0x94, 0xff, 0x29, 0x57, 0x02, 0x49, 0x09, 0xad,
/* (2^405)P */ 0x27, 0xa5, 0x78, 0x1b, 0xbf, 0x6b, 0xaf, 0x0b, 0x8c, 0xd9, 0xa8, 0x37, 0xb0, 0x67, 0x18, 0xb6, 0xc7, 0x05, 0x8a, 0x67, 0x03, 0x30, 0x62, 0x6e, 0x56, 0x82, 0xa9, 0x54, 0x3e, 0x0c, 0x4e, 0x07, 0xe1, 0x5a, 0x38, 0xed, 0xfa, 0xc8, 0x55, 0x6b, 0x08, 0xa3, 0x6b, 0x64, 0x2a, 0x15, 0xd6, 0x39, 0x6f, 0x47, 0x99, 0x42, 0x3f, 0x33, 0x84, 0x8f,
/* (2^406)P */ 0xbc, 0x45, 0x29, 0x81, 0x0e, 0xa4, 0xc5, 0x72, 0x3a, 0x10, 0xe1, 0xc4, 0x1e, 0xda, 0xc3, 0xfe, 0xb0, 0xce, 0xd2, 0x13, 0x34, 0x67, 0x21, 0xc6, 0x7e, 0xf9, 0x8c, 0xff, 0x39, 0x50, 0xae, 0x92, 0x60, 0x35, 0x2f, 0x8b, 0x6e, 0xc9, 0xc1, 0x27, 0x3a, 0x94, 0x66, 0x3e, 0x26, 0x84, 0x93, 0xc8, 0x6c, 0xcf, 0xd2, 0x03, 0xa1, 0x10, 0xcf, 0xb7,
/* (2^407)P */ 0x64, 0xda, 0x19, 0xf6, 0xc5, 0x73, 0x17, 0x44, 0x88, 0x81, 0x07, 0x0d, 0x34, 0xb2, 0x75, 0xf9, 0xd9, 0xe2, 0xe0, 0x8b, 0x71, 0xcf, 0x72, 0x34, 0x83, 0xb4, 0xce, 0xfc, 0xd7, 0x29, 0x09, 0x5a, 0x98, 0xbf, 0x14, 0xac, 0x77, 0x55, 0x38, 0x47, 0x5b, 0x0f, 0x40, 0x24, 0xe5, 0xa5, 0xa6, 0xac, 0x2d, 0xa6, 0xff, 0x9c, 0x73, 0xfe, 0x5c, 0x7e,
/* (2^408)P */ 0x1e, 0x33, 0xcc, 0x68, 0xb2, 0xbc, 0x8c, 0x93, 0xaf, 0xcc, 0x38, 0xf8, 0xd9, 0x16, 0x72, 0x50, 0xac, 0xd9, 0xb5, 0x0b, 0x9a, 0xbe, 0x46, 0x7a, 0xf1, 0xee, 0xf1, 0xad, 0xec, 0x5b, 0x59, 0x27, 0x9c, 0x05, 0xa3, 0x87, 0xe0, 0x37, 0x2c, 0x83, 0xce, 0xb3, 0x65, 0x09, 0x8e, 0xc3, 0x9c, 0xbf, 0x6a, 0xa2, 0x00, 0xcc, 0x12, 0x36, 0xc5, 0x95,
/* (2^409)P */ 0x36, 0x11, 0x02, 0x14, 0x9c, 0x3c, 0xeb, 0x2f, 0x23, 0x5b, 0x6b, 0x2b, 0x08, 0x54, 0x53, 0xac, 0xb2, 0xa3, 0xe0, 0x26, 0x62, 0x3c, 0xe4, 0xe1, 0x81, 0xee, 0x13, 0x3e, 0xa4, 0x97, 0xef, 0xf9, 0x92, 0x27, 0x01, 0xce, 0x54, 0x8b, 0x3e, 0x31, 0xbe, 0xa7, 0x88, 0xcf, 0x47, 0x99, 0x3c, 0x10, 0x6f, 0x60, 0xb3, 0x06, 0x4e, 0xee, 0x1b, 0xf0,
/* (2^410)P */ 0x59, 0x49, 0x66, 0xcf, 0x22, 0xe6, 0xf6, 0x73, 0xfe, 0xa3, 0x1c, 0x09, 0xfa, 0x5f, 0x65, 0xa8, 0xf0, 0x82, 0xc2, 0xef, 0x16, 0x63, 0x6e, 0x79, 0x69, 0x51, 0x39, 0x07, 0x65, 0xc4, 0x81, 0xec, 0x73, 0x0f, 0x15, 0x93, 0xe1, 0x30, 0x33, 0xe9, 0x37, 0x86, 0x42, 0x4c, 0x1f, 0x9b, 0xad, 0xee, 0x3f, 0xf1, 0x2a, 0x8e, 0x6a, 0xa3, 0xc8, 0x35,
/* (2^411)P */ 0x1e, 0x49, 0xf1, 0xdd, 0xd2, 0x9c, 0x8e, 0x78, 0xb2, 0x06, 0xe4, 0x6a, 0xab, 0x3a, 0xdc, 0xcd, 0xf4, 0xeb, 0xe1, 0xe7, 0x2f, 0xaa, 0xeb, 0x40, 0x31, 0x9f, 0xb9, 0xab, 0x13, 0xa9, 0x78, 0xbf, 0x38, 0x89, 0x0e, 0x85, 0x14, 0x8b, 0x46, 0x76, 0x14, 0xda, 0xcf, 0x33, 0xc8, 0x79, 0xd3, 0xd5, 0xa3, 0x6a, 0x69, 0x45, 0x70, 0x34, 0xc3, 0xe9,
/* (2^412)P */ 0x5e, 0xe7, 0x78, 0xe9, 0x24, 0xcc, 0xe9, 0xf4, 0xc8, 0x6b, 0xe0, 0xfb, 0x3a, 0xbe, 0xcc, 0x42, 0x4a, 0x00, 0x22, 0xf8, 0xe6, 0x32, 0xbe, 0x6d, 0x18, 0x55, 0x60, 0xe9, 0x72, 0x69, 0x50, 0x56, 0xca, 0x04, 0x18, 0x38, 0xa1, 0xee, 0xd8, 0x38, 0x3c, 0xa7, 0x70, 0xe2, 0xb9, 0x4c, 0xa0, 0xc8, 0x89, 0x72, 0xcf, 0x49, 0x7f, 0xdf, 0xbc, 0x67,
/* (2^413)P */ 0x1d, 0x17, 0xcb, 0x0b, 0xbd, 0xb2, 0x36, 0xe3, 0xa8, 0x99, 0x31, 0xb6, 0x26, 0x9c, 0x0c, 0x74, 0xaf, 0x4d, 0x24, 0x61, 0xcf, 0x31, 0x7b, 0xed, 0xdd, 0xc3, 0xf6, 0x32, 0x70, 0xfe, 0x17, 0xf6, 0x51, 0x37, 0x65, 0xce, 0x5d, 0xaf, 0xa5, 0x2f, 0x2a, 0xfe, 0x00, 0x71, 0x7c, 0x50, 0xbe, 0x21, 0xc7, 0xed, 0xc6, 0xfc, 0x67, 0xcf, 0x9c, 0xdd,
/* (2^414)P */ 0x26, 0x3e, 0xf8, 0xbb, 0xd0, 0xb1, 0x01, 0xd8, 0xeb, 0x0b, 0x62, 0x87, 0x35, 0x4c, 0xde, 0xca, 0x99, 0x9c, 0x6d, 0xf7, 0xb6, 0xf0, 0x57, 0x0a, 0x52, 0x29, 0x6a, 0x3f, 0x26, 0x31, 0x04, 0x07, 0x2a, 0xc9, 0xfa, 0x9b, 0x0e, 0x62, 0x8e, 0x72, 0xf2, 0xad, 0xce, 0xb6, 0x35, 0x7a, 0xc1, 0xae, 0x35, 0xc7, 0xa3, 0x14, 0xcf, 0x0c, 0x28, 0xb7,
/* (2^415)P */ 0xa6, 0xf1, 0x32, 0x3a, 0x20, 0xd2, 0x24, 0x97, 0xcf, 0x5d, 0x37, 0x99, 0xaf, 0x33, 0x7a, 0x5b, 0x7a, 0xcc, 0x4e, 0x41, 0x38, 0xb1, 0x4e, 0xad, 0xc9, 0xd9, 0x71, 0x7e, 0xb2, 0xf5, 0xd5, 0x01, 0x6c, 0x4d, 0xfd, 0xa1, 0xda, 0x03, 0x38, 0x9b, 0x3d, 0x92, 0x92, 0xf2, 0xca, 0xbf, 0x1f, 0x24, 0xa4, 0xbb, 0x30, 0x6a, 0x74, 0x56, 0xc8, 0xce,
/* (2^416)P */ 0x27, 0xf4, 0xed, 0xc9, 0xc3, 0xb1, 0x79, 0x85, 0xbe, 0xf6, 0xeb, 0xf3, 0x55, 0xc7, 0xaa, 0xa6, 0xe9, 0x07, 0x5d, 0xf4, 0xeb, 0xa6, 0x81, 0xe3, 0x0e, 0xcf, 0xa3, 0xc1, 0xef, 0xe7, 0x34, 0xb2, 0x03, 0x73, 0x8a, 0x91, 0xf1, 0xad, 0x05, 0xc7, 0x0b, 0x43, 0x99, 0x12, 0x31, 0xc8, 0xc7, 0xc5, 0xa4, 0x3d, 0xcd, 0xe5, 0x4e, 0x6d, 0x24, 0xdd,
/* (2^417)P */ 0x61, 0x54, 0xd0, 0x95, 0x2c, 0x45, 0x75, 0xac, 0xb5, 0x1a, 0x9d, 0x11, 0xeb, 0xed, 0x6b, 0x57, 0xa3, 0xe6, 0xcd, 0x77, 0xd4, 0x83, 0x8e, 0x39, 0xf1, 0x0f, 0x98, 0xcb, 0x40, 0x02, 0x6e, 0x10, 0x82, 0x9e, 0xb4, 0x93, 0x76, 0xd7, 0x97, 0xa3, 0x53, 0x12, 0x86, 0xc6, 0x15, 0x78, 0x73, 0x93, 0xe7, 0x7f, 0xcf, 0x1f, 0xbf, 0xcd, 0xd2, 0x7a,
/* (2^418)P */ 0xc2, 0x21, 0xdc, 0xd5, 0x69, 0xff, 0xca, 0x49, 0x3a, 0xe1, 0xc3, 0x69, 0x41, 0x56, 0xc1, 0x76, 0x63, 0x24, 0xbd, 0x64, 0x1b, 0x3d, 0x92, 0xf9, 0x13, 0x04, 0x25, 0xeb, 0x27, 0xa6, 0xef, 0x39, 0x3a, 0x80, 0xe0, 0xf8, 0x27, 0xee, 0xc9, 0x49, 0x77, 0xef, 0x3f, 0x29, 0x3d, 0x5e, 0xe6, 0x66, 0x83, 0xd1, 0xf6, 0xfe, 0x9d, 0xbc, 0xf1, 0x96,
/* (2^419)P */ 0x6b, 0xc6, 0x99, 0x26, 0x3c, 0xf3, 0x63, 0xf9, 0xc7, 0x29, 0x8c, 0x52, 0x62, 0x2d, 0xdc, 0x8a, 0x66, 0xce, 0x2c, 0xa7, 0xe4, 0xf0, 0xd7, 0x37, 0x17, 0x1e, 0xe4, 0xa3, 0x53, 0x7b, 0x29, 0x8e, 0x60, 0x99, 0xf9, 0x0c, 0x7c, 0x6f, 0xa2, 0xcc, 0x9f, 0x80, 0xdd, 0x5e, 0x46, 0xaa, 0x0d, 0x6c, 0xc9, 0x6c, 0xf7, 0x78, 0x5b, 0x38, 0xe3, 0x24,
/* (2^420)P */ 0x4b, 0x75, 0x6a, 0x2f, 0x08, 0xe1, 0x72, 0x76, 0xab, 0x82, 0x96, 0xdf, 0x3b, 0x1f, 0x9b, 0xd8, 0xed, 0xdb, 0xcd, 0x15, 0x09, 0x5a, 0x1e, 0xb7, 0xc5, 0x26, 0x72, 0x07, 0x0c, 0x50, 0xcd, 0x3b, 0x4d, 0x3f, 0xa2, 0x67, 0xc2, 0x02, 0x61, 0x2e, 0x68, 0xe9, 0x6f, 0xf0, 0x21, 0x2a, 0xa7, 0x3b, 0x88, 0x04, 0x11, 0x64, 0x49, 0x0d, 0xb4, 0x46,
/* (2^421)P */ 0x63, 0x85, 0xf3, 0xc5, 0x2b, 0x5a, 0x9f, 0xf0, 0x17, 0xcb, 0x45, 0x0a, 0xf3, 0x6e, 0x7e, 0xb0, 0x7c, 0xbc, 0xf0, 0x4f, 0x3a, 0xb0, 0xbc, 0x36, 0x36, 0x52, 0x51, 0xcb, 0xfe, 0x9a, 0xcb, 0xe8, 0x7e, 0x4b, 0x06, 0x7f, 0xaa, 0x35, 0xc8, 0x0e, 0x7a, 0x30, 0xa3, 0xb1, 0x09, 0xbb, 0x86, 0x4c, 0xbe, 0xb8, 0xbd, 0xe0, 0x32, 0xa5, 0xd4, 0xf7,
/* (2^422)P */ 0x7d, 0x50, 0x37, 0x68, 0x4e, 0x22, 0xb2, 0x2c, 0xd5, 0x0f, 0x2b, 0x6d, 0xb1, 0x51, 0xf2, 0x82, 0xe9, 0x98, 0x7c, 0x50, 0xc7, 0x96, 0x7e, 0x0e, 0xdc, 0xb1, 0x0e, 0xb2, 0x63, 0x8c, 0x30, 0x37, 0x72, 0x21, 0x9c, 0x61, 0xc2, 0xa7, 0x33, 0xd9, 0xb2, 0x63, 0x93, 0xd1, 0x6b, 0x6a, 0x73, 0xa5, 0x58, 0x80, 0xff, 0x04, 0xc7, 0x83, 0x21, 0x29,
/* (2^423)P */ 0x29, 0x04, 0xbc, 0x99, 0x39, 0xc9, 0x58, 0xc9, 0x6b, 0x17, 0xe8, 0x90, 0xb3, 0xe6, 0xa9, 0xb6, 0x28, 0x9b, 0xcb, 0x3b, 0x28, 0x90, 0x68, 0x71, 0xff, 0xcf, 0x08, 0x78, 0xc9, 0x8d, 0xa8, 0x4e, 0x43, 0xd1, 0x1c, 0x9e, 0xa4, 0xe3, 0xdf, 0xbf, 0x92, 0xf4, 0xf9, 0x41, 0xba, 0x4d, 0x1c, 0xf9, 0xdd, 0x74, 0x76, 0x1c, 0x6e, 0x3e, 0x94, 0x87,
/* (2^424)P */ 0xe4, 0xda, 0xc5, 0xd7, 0xfb, 0x87, 0xc5, 0x4d, 0x6b, 0x19, 0xaa, 0xb9, 0xbc, 0x8c, 0xf2, 0x8a, 0xd8, 0x5d, 0xdb, 0x4d, 0xef, 0xa6, 0xf2, 0x65, 0xf1, 0x22, 0x9c, 0xf1, 0x46, 0x30, 0x71, 0x7c, 0xe4, 0x53, 0x8e, 0x55, 0x2e, 0x9c, 0x9a, 0x31, 0x2a, 0xc3, 0xab, 0x0f, 0xde, 0xe4, 0xbe, 0xd8, 0x96, 0x50, 0x6e, 0x0c, 0x54, 0x49, 0xe6, 0xec,
/* (2^425)P */ 0x3c, 0x1d, 0x5a, 0xa5, 0xda, 0xad, 0xdd, 0xc2, 0xae, 0xac, 0x6f, 0x86, 0x75, 0x31, 0x91, 0x64, 0x45, 0x9d, 0xa4, 0xf0, 0x81, 0xf1, 0x0e, 0xba, 0x74, 0xaf, 0x7b, 0xcd, 0x6f, 0xfe, 0xac, 0x4e, 0xdb, 0x4e, 0x45, 0x35, 0x36, 0xc5, 0xc0, 0x6c, 0x3d, 0x64, 0xf4, 0xd8, 0x07, 0x62, 0xd1, 0xec, 0xf3, 0xfc, 0x93, 0xc9, 0x28, 0x0c, 0x2c, 0xf3,
/* (2^426)P */ 0x0c, 0x69, 0x2b, 0x5c, 0xb6, 0x41, 0x69, 0xf1, 0xa4, 0xf1, 0x5b, 0x75, 0x4c, 0x42, 0x8b, 0x47, 0xeb, 0x69, 0xfb, 0xa8, 0xe6, 0xf9, 0x7b, 0x48, 0x50, 0xaf, 0xd3, 0xda, 0xb2, 0x35, 0x10, 0xb5, 0x5b, 0x40, 0x90, 0x39, 0xc9, 0x07, 0x06, 0x73, 0x26, 0x20, 0x95, 0x01, 0xa4, 0x2d, 0xf0, 0xe7, 0x2e, 0x00, 0x7d, 0x41, 0x09, 0x68, 0x13, 0xc4,
/* (2^427)P */ 0xbe, 0x38, 0x78, 0xcf, 0xc9, 0x4f, 0x36, 0xca, 0x09, 0x61, 0x31, 0x3c, 0x57, 0x2e, 0xec, 0x17, 0xa4, 0x7d, 0x19, 0x2b, 0x9b, 0x5b, 0xbe, 0x8f, 0xd6, 0xc5, 0x2f, 0x86, 0xf2, 0x64, 0x76, 0x17, 0x00, 0x6e, 0x1a, 0x8c, 0x67, 0x1b, 0x68, 0xeb, 0x15, 0xa2, 0xd6, 0x09, 0x91, 0xdd, 0x23, 0x0d, 0x98, 0xb2, 0x10, 0x19, 0x55, 0x9b, 0x63, 0xf2,
/* (2^428)P */ 0x51, 0x1f, 0x93, 0xea, 0x2a, 0x3a, 0xfa, 0x41, 0xc0, 0x57, 0xfb, 0x74, 0xa6, 0x65, 0x09, 0x56, 0x14, 0xb6, 0x12, 0xaa, 0xb3, 0x1a, 0x8d, 0x3b, 0x76, 0x91, 0x7a, 0x23, 0x56, 0x9c, 0x6a, 0xc0, 0xe0, 0x3c, 0x3f, 0xb5, 0x1a, 0xf4, 0x57, 0x71, 0x93, 0x2b, 0xb1, 0xa7, 0x70, 0x57, 0x22, 0x80, 0xf5, 0xb8, 0x07, 0x77, 0x87, 0x0c, 0xbe, 0x83,
/* (2^429)P */ 0x07, 0x9b, 0x0e, 0x52, 0x38, 0x63, 0x13, 0x86, 0x6a, 0xa6, 0xb4, 0xd2, 0x60, 0x68, 0x9a, 0x99, 0x82, 0x0a, 0x04, 0x5f, 0x89, 0x7a, 0x1a, 0x2a, 0xae, 0x2d, 0x35, 0x0c, 0x1e, 0xad, 0xef, 0x4f, 0x9a, 0xfc, 0xc8, 0xd9, 0xcf, 0x9d, 0x48, 0x71, 0xa5, 0x55, 0x79, 0x73, 0x39, 0x1b, 0xd8, 0x73, 0xec, 0x9b, 0x03, 0x16, 0xd8, 0x82, 0xf7, 0x67,
/* (2^430)P */ 0x52, 0x67, 0x42, 0x21, 0xc9, 0x40, 0x78, 0x82, 0x2b, 0x95, 0x2d, 0x20, 0x92, 0xd1, 0xe2, 0x61, 0x25, 0xb0, 0xc6, 0x9c, 0x20, 0x59, 0x8e, 0x28, 0x6f, 0xf3, 0xfd, 0xd3, 0xc1, 0x32, 0x43, 0xc9, 0xa6, 0x08, 0x7a, 0x77, 0x9c, 0x4c, 0x8c, 0x33, 0x71, 0x13, 0x69, 0xe3, 0x52, 0x30, 0xa7, 0xf5, 0x07, 0x67, 0xac, 0xad, 0x46, 0x8a, 0x26, 0x25,
/* (2^431)P */ 0xda, 0x86, 0xc4, 0xa2, 0x71, 0x56, 0xdd, 0xd2, 0x48, 0xd3, 0xde, 0x42, 0x63, 0x01, 0xa7, 0x2c, 0x92, 0x83, 0x6f, 0x2e, 0xd8, 0x1e, 0x3f, 0xc1, 0xc5, 0x42, 0x4e, 0x34, 0x19, 0x54, 0x6e, 0x35, 0x2c, 0x51, 0x2e, 0xfd, 0x0f, 0x9a, 0x45, 0x66, 0x5e, 0x4a, 0x83, 0xda, 0x0a, 0x53, 0x68, 0x63, 0xfa, 0xce, 0x47, 0x20, 0xd3, 0x34, 0xba, 0x0d,
/* (2^432)P */ 0xd0, 0xe9, 0x64, 0xa4, 0x61, 0x4b, 0x86, 0xe5, 0x93, 0x6f, 0xda, 0x0e, 0x31, 0x7e, 0x6e, 0xe3, 0xc6, 0x73, 0xd8, 0xa3, 0x08, 0x57, 0x52, 0xcd, 0x51, 0x63, 0x1d, 0x9f, 0x93, 0x00, 0x62, 0x91, 0x26, 0x21, 0xa7, 0xdd, 0x25, 0x0f, 0x09, 0x0d, 0x35, 0xad, 0xcf, 0x11, 0x8e, 0x6e, 0xe8, 0xae, 0x1d, 0x95, 0xcb, 0x88, 0xf8, 0x70, 0x7b, 0x91,
/* (2^433)P */ 0x0c, 0x19, 0x5c, 0xd9, 0x8d, 0xda, 0x9d, 0x2c, 0x90, 0x54, 0x65, 0xe8, 0xb6, 0x35, 0x50, 0xae, 0xea, 0xae, 0x43, 0xb7, 0x1e, 0x99, 0x8b, 0x4c, 0x36, 0x4e, 0xe4, 0x1e, 0xc4, 0x64, 0x43, 0xb6, 0xeb, 0xd4, 0xe9, 0x60, 0x22, 0xee, 0xcf, 0xb8, 0x52, 0x1b, 0xf0, 0x04, 0xce, 0xbc, 0x2b, 0xf0, 0xbe, 0xcd, 0x44, 0x74, 0x1e, 0x1f, 0x63, 0xf9,
/* (2^434)P */ 0xe1, 0x3f, 0x95, 0x94, 0xb2, 0xb6, 0x31, 0xa9, 0x1b, 0xdb, 0xfd, 0x0e, 0xdb, 0xdd, 0x1a, 0x22, 0x78, 0x60, 0x9f, 0x75, 0x5f, 0x93, 0x06, 0x0c, 0xd8, 0xbb, 0xa2, 0x85, 0x2b, 0x5e, 0xc0, 0x9b, 0xa8, 0x5d, 0xaf, 0x93, 0x91, 0x91, 0x47, 0x41, 0x1a, 0xfc, 0xb4, 0x51, 0x85, 0xad, 0x69, 0x4d, 0x73, 0x69, 0xd5, 0x4e, 0x82, 0xfb, 0x66, 0xcb,
/* (2^435)P */ 0x7c, 0xbe, 0xc7, 0x51, 0xc4, 0x74, 0x6e, 0xab, 0xfd, 0x41, 0x4f, 0x76, 0x4f, 0x24, 0x03, 0xd6, 0x2a, 0xb7, 0x42, 0xb4, 0xda, 0x41, 0x2c, 0x82, 0x48, 0x4c, 0x7f, 0x6f, 0x25, 0x5d, 0x36, 0xd4, 0x69, 0xf5, 0xef, 0x02, 0x81, 0xea, 0x6f, 0x19, 0x69, 0xe8, 0x6f, 0x5b, 0x2f, 0x14, 0x0e, 0x6f, 0x89, 0xb4, 0xb5, 0xd8, 0xae, 0xef, 0x7b, 0x87,
/* (2^436)P */ 0xe9, 0x91, 0xa0, 0x8b, 0xc9, 0xe0, 0x01, 0x90, 0x37, 0xc1, 0x6f, 0xdc, 0x5e, 0xf7, 0xbf, 0x43, 0x00, 0xaa, 0x10, 0x76, 0x76, 0x18, 0x6e, 0x19, 0x1e, 0x94, 0x50, 0x11, 0x0a, 0xd1, 0xe2, 0xdb, 0x08, 0x21, 0xa0, 0x1f, 0xdb, 0x54, 0xfe, 0xea, 0x6e, 0xa3, 0x68, 0x56, 0x87, 0x0b, 0x22, 0x4e, 0x66, 0xf3, 0x82, 0x82, 0x00, 0xcd, 0xd4, 0x12,
/* (2^437)P */ 0x25, 0x8e, 0x24, 0x77, 0x64, 0x4c, 0xe0, 0xf8, 0x18, 0xc0, 0xdc, 0xc7, 0x1b, 0x35, 0x65, 0xde, 0x67, 0x41, 0x5e, 0x6f, 0x90, 0x82, 0xa7, 0x2e, 0x6d, 0xf1, 0x47, 0xb4, 0x92, 0x9c, 0xfd, 0x6a, 0x9a, 0x41, 0x36, 0x20, 0x24, 0x58, 0xc3, 0x59, 0x07, 0x9a, 0xfa, 0x9f, 0x03, 0xcb, 0xc7, 0x69, 0x37, 0x60, 0xe1, 0xab, 0x13, 0x72, 0xee, 0xa2,
/* (2^438)P */ 0x74, 0x78, 0xfb, 0x13, 0xcb, 0x8e, 0x37, 0x1a, 0xf6, 0x1d, 0x17, 0x83, 0x06, 0xd4, 0x27, 0x06, 0x21, 0xe8, 0xda, 0xdf, 0x6b, 0xf3, 0x83, 0x6b, 0x34, 0x8a, 0x8c, 0xee, 0x01, 0x05, 0x5b, 0xed, 0xd3, 0x1b, 0xc9, 0x64, 0x83, 0xc9, 0x49, 0xc2, 0x57, 0x1b, 0xdd, 0xcf, 0xf1, 0x9d, 0x63, 0xee, 0x1c, 0x0d, 0xa0, 0x0a, 0x73, 0x1f, 0x5b, 0x32,
/* (2^439)P */ 0x29, 0xce, 0x1e, 0xc0, 0x6a, 0xf5, 0xeb, 0x99, 0x5a, 0x39, 0x23, 0xe9, 0xdd, 0xac, 0x44, 0x88, 0xbc, 0x80, 0x22, 0xde, 0x2c, 0xcb, 0xa8, 0x3b, 0xff, 0xf7, 0x6f, 0xc7, 0x71, 0x72, 0xa8, 0xa3, 0xf6, 0x4d, 0xc6, 0x75, 0xda, 0x80, 0xdc, 0xd9, 0x30, 0xd9, 0x07, 0x50, 0x5a, 0x54, 0x7d, 0xda, 0x39, 0x6f, 0x78, 0x94, 0xbf, 0x25, 0x98, 0xdc,
/* (2^440)P */ 0x01, 0x26, 0x62, 0x44, 0xfb, 0x0f, 0x11, 0x72, 0x73, 0x0a, 0x16, 0xc7, 0x16, 0x9c, 0x9b, 0x37, 0xd8, 0xff, 0x4f, 0xfe, 0x57, 0xdb, 0xae, 0xef, 0x7d, 0x94, 0x30, 0x04, 0x70, 0x83, 0xde, 0x3c, 0xd4, 0xb5, 0x70, 0xda, 0xa7, 0x55, 0xc8, 0x19, 0xe1, 0x36, 0x15, 0x61, 0xe7, 0x3b, 0x7d, 0x85, 0xbb, 0xf3, 0x42, 0x5a, 0x94, 0xf4, 0x53, 0x2a,
/* (2^441)P */ 0x14, 0x60, 0xa6, 0x0b, 0x83, 0xe1, 0x23, 0x77, 0xc0, 0xce, 0x50, 0xed, 0x35, 0x8d, 0x98, 0x99, 0x7d, 0xf5, 0x8d, 0xce, 0x94, 0x25, 0xc8, 0x0f, 0x6d, 0xfa, 0x4a, 0xa4, 0x3a, 0x1f, 0x66, 0xfb, 0x5a, 0x64, 0xaf, 0x8b, 0x54, 0x54, 0x44, 0x3f, 0x5b, 0x88, 0x61, 0xe4, 0x48, 0x45, 0x26, 0x20, 0xbe, 0x0d, 0x06, 0xbb, 0x65, 0x59, 0xe1, 0x36,
/* (2^442)P */ 0xb7, 0x98, 0xce, 0xa3, 0xe3, 0xee, 0x11, 0x1b, 0x9e, 0x24, 0x59, 0x75, 0x31, 0x37, 0x44, 0x6f, 0x6b, 0x9e, 0xec, 0xb7, 0x44, 0x01, 0x7e, 0xab, 0xbb, 0x69, 0x5d, 0x11, 0xb0, 0x30, 0x64, 0xea, 0x91, 0xb4, 0x7a, 0x8c, 0x02, 0x4c, 0xb9, 0x10, 0xa7, 0xc7, 0x79, 0xe6, 0xdc, 0x77, 0xe3, 0xc8, 0xef, 0x3e, 0xf9, 0x38, 0x81, 0xce, 0x9a, 0xb2,
/* (2^443)P */ 0x91, 0x12, 0x76, 0xd0, 0x10, 0xb4, 0xaf, 0xe1, 0x89, 0x3a, 0x93, 0x6b, 0x5c, 0x19, 0x5f, 0x24, 0xed, 0x04, 0x92, 0xc7, 0xf0, 0x00, 0x08, 0xc1, 0x92, 0xff, 0x90, 0xdb, 0xb2, 0xbf, 0xdf, 0x49, 0xcd, 0xbd, 0x5c, 0x6e, 0xbf, 0x16, 0xbb, 0x61, 0xf9, 0x20, 0x33, 0x35, 0x93, 0x11, 0xbc, 0x59, 0x69, 0xce, 0x18, 0x9f, 0xf8, 0x7b, 0xa1, 0x6e,
/* (2^444)P */ 0xa1, 0xf4, 0xaf, 0xad, 0xf8, 0xe6, 0x99, 0xd2, 0xa1, 0x4d, 0xde, 0x56, 0xc9, 0x7b, 0x0b, 0x11, 0x3e, 0xbf, 0x89, 0x1a, 0x9a, 0x90, 0xe5, 0xe2, 0xa6, 0x37, 0x88, 0xa1, 0x68, 0x59, 0xae, 0x8c, 0xec, 0x02, 0x14, 0x8d, 0xb7, 0x2e, 0x25, 0x75, 0x7f, 0x76, 0x1a, 0xd3, 0x4d, 0xad, 0x8a, 0x00, 0x6c, 0x96, 0x49, 0xa4, 0xc3, 0x2e, 0x5c, 0x7b,
/* (2^445)P */ 0x26, 0x53, 0xf7, 0xda, 0xa8, 0x01, 0x14, 0xb1, 0x63, 0xe3, 0xc3, 0x89, 0x88, 0xb0, 0x85, 0x40, 0x2b, 0x26, 0x9a, 0x10, 0x1a, 0x70, 0x33, 0xf4, 0x50, 0x9d, 0x4d, 0xd8, 0x64, 0xc6, 0x0f, 0xe1, 0x17, 0xc8, 0x10, 0x4b, 0xfc, 0xa0, 0xc9, 0xba, 0x2c, 0x98, 0x09, 0xf5, 0x84, 0xb6, 0x7c, 0x4e, 0xa3, 0xe3, 0x81, 0x1b, 0x32, 0x60, 0x02, 0xdd,
/* (2^446)P */ 0xa3, 0xe5, 0x86, 0xd4, 0x43, 0xa8, 0xd1, 0x98, 0x9d, 0x9d, 0xdb, 0x04, 0xcf, 0x6e, 0x35, 0x05, 0x30, 0x53, 0x3b, 0xbc, 0x90, 0x00, 0x4a, 0xc5, 0x40, 0x2a, 0x0f, 0xde, 0x1a, 0xd7, 0x36, 0x27, 0x44, 0x62, 0xa6, 0xac, 0x9d, 0xd2, 0x70, 0x69, 0x14, 0x39, 0x9b, 0xd1, 0xc3, 0x0a, 0x3a, 0x82, 0x0e, 0xf1, 0x94, 0xd7, 0x42, 0x94, 0xd5, 0x7d,
/* (2^447)P */ 0x04, 0xc0, 0x6e, 0x12, 0x90, 0x70, 0xf9, 0xdf, 0xf7, 0xc9, 0x86, 0xc0, 0xe6, 0x92, 0x8b, 0x0a, 0xa1, 0xc1, 0x3b, 0xcc, 0x33, 0xb7, 0xf0, 0xeb, 0x51, 0x50, 0x80, 0x20, 0x69, 0x1c, 0x4f, 0x89, 0x05, 0x1e, 0xe4, 0x7a, 0x0a, 0xc2, 0xf0, 0xf5, 0x78, 0x91, 0x76, 0x34, 0x45, 0xdc, 0x24, 0x53, 0x24, 0x98, 0xe2, 0x73, 0x6f, 0xe6, 0x46, 0x67,
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/constants.go
================================================
package goldilocks
import fp "github.com/cloudflare/circl/math/fp448"
var (
// genX is the x-coordinate of the generator of Goldilocks curve.
genX = fp.Elt{
0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26,
0x8e, 0x93, 0x00, 0x8b, 0xe1, 0x80, 0x3b, 0x43,
0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea,
0x67, 0x17, 0x0f, 0x47, 0x70, 0x65, 0x14, 0x9e,
0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f,
}
// genY is the y-coordinate of the generator of Goldilocks curve.
genY = fp.Elt{
0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98,
0xad, 0xc8, 0xd7, 0x4e, 0x2c, 0x13, 0xbd, 0xfd,
0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87,
0x40, 0x98, 0xa3, 0x6c, 0x73, 0x73, 0xea, 0x4b,
0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69,
}
// paramD is -39081 in Fp.
paramD = fp.Elt{
0x56, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
// order is 2^446-0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d,
// which is the number of points in the prime subgroup.
order = Scalar{
0xf3, 0x44, 0x58, 0xab, 0x92, 0xc2, 0x78, 0x23,
0x55, 0x8f, 0xc5, 0x8d, 0x72, 0xc2, 0x6c, 0x21,
0x90, 0x36, 0xd6, 0xae, 0x49, 0xdb, 0x4e, 0xc4,
0xe9, 0x23, 0xca, 0x7c, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f,
}
// residue448 is 2^448 mod order.
residue448 = [4]uint64{
0x721cf5b5529eec34, 0x7a4cf635c8e9c2ab, 0xeec492d944a725bf, 0x20cd77058,
}
// invFour is 1/4 mod order.
invFour = Scalar{
0x3d, 0x11, 0xd6, 0xaa, 0xa4, 0x30, 0xde, 0x48,
0xd5, 0x63, 0x71, 0xa3, 0x9c, 0x30, 0x5b, 0x08,
0xa4, 0x8d, 0xb5, 0x6b, 0xd2, 0xb6, 0x13, 0x71,
0xfa, 0x88, 0x32, 0xdf, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
}
// paramDTwist is -39082 in Fp. The D parameter of the twist curve.
paramDTwist = fp.Elt{
0x55, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
)
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/curve.go
================================================
// Package goldilocks provides elliptic curve operations over the goldilocks curve.
package goldilocks
import fp "github.com/cloudflare/circl/math/fp448"
// Curve is the Goldilocks curve x^2+y^2=z^2-39081x^2y^2.
type Curve struct{}
// Identity returns the identity point.
func (Curve) Identity() *Point {
return &Point{
y: fp.One(),
z: fp.One(),
}
}
// IsOnCurve returns true if the point lies on the curve.
func (Curve) IsOnCurve(P *Point) bool {
x2, y2, t, t2, z2 := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}
rhs, lhs := &fp.Elt{}, &fp.Elt{}
fp.Mul(t, &P.ta, &P.tb) // t = ta*tb
fp.Sqr(x2, &P.x) // x^2
fp.Sqr(y2, &P.y) // y^2
fp.Sqr(z2, &P.z) // z^2
fp.Sqr(t2, t) // t^2
fp.Add(lhs, x2, y2) // x^2 + y^2
fp.Mul(rhs, t2, ¶mD) // dt^2
fp.Add(rhs, rhs, z2) // z^2 + dt^2
fp.Sub(lhs, lhs, rhs) // x^2 + y^2 - (z^2 + dt^2)
eq0 := fp.IsZero(lhs)
fp.Mul(lhs, &P.x, &P.y) // xy
fp.Mul(rhs, t, &P.z) // tz
fp.Sub(lhs, lhs, rhs) // xy - tz
eq1 := fp.IsZero(lhs)
return eq0 && eq1
}
// Generator returns the generator point.
func (Curve) Generator() *Point {
return &Point{
x: genX,
y: genY,
z: fp.One(),
ta: genX,
tb: genY,
}
}
// Order returns the number of points in the prime subgroup.
func (Curve) Order() Scalar { return order }
// Double returns 2P.
func (Curve) Double(P *Point) *Point { R := *P; R.Double(); return &R }
// Add returns P+Q.
func (Curve) Add(P, Q *Point) *Point { R := *P; R.Add(Q); return &R }
// ScalarMult returns kP. This function runs in constant time.
func (e Curve) ScalarMult(k *Scalar, P *Point) *Point {
k4 := &Scalar{}
k4.divBy4(k)
return e.pull(twistCurve{}.ScalarMult(k4, e.push(P)))
}
// ScalarBaseMult returns kG where G is the generator point. This function runs in constant time.
func (e Curve) ScalarBaseMult(k *Scalar) *Point {
k4 := &Scalar{}
k4.divBy4(k)
return e.pull(twistCurve{}.ScalarBaseMult(k4))
}
// CombinedMult returns mG+nP, where G is the generator point. This function is non-constant time.
func (e Curve) CombinedMult(m, n *Scalar, P *Point) *Point {
m4 := &Scalar{}
n4 := &Scalar{}
m4.divBy4(m)
n4.divBy4(n)
return e.pull(twistCurve{}.CombinedMult(m4, n4, twistCurve{}.pull(P)))
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/isogeny.go
================================================
package goldilocks
import fp "github.com/cloudflare/circl/math/fp448"
func (Curve) pull(P *twistPoint) *Point { return twistCurve{}.push(P) }
func (twistCurve) pull(P *Point) *twistPoint { return Curve{}.push(P) }
// push sends a point on the Goldilocks curve to a point on the twist curve.
func (Curve) push(P *Point) *twistPoint {
Q := &twistPoint{}
Px, Py, Pz := &P.x, &P.y, &P.z
a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb
fp.Add(e, Px, Py) // x+y
fp.Sqr(a, Px) // A = x^2
fp.Sqr(b, Py) // B = y^2
fp.Sqr(c, Pz) // z^2
fp.Add(c, c, c) // C = 2*z^2
*d = *a // D = A
fp.Sqr(e, e) // (x+y)^2
fp.Sub(e, e, a) // (x+y)^2-A
fp.Sub(e, e, b) // E = (x+y)^2-A-B
fp.Add(h, b, d) // H = B+D
fp.Sub(g, b, d) // G = B-D
fp.Sub(f, c, h) // F = C-H
fp.Mul(&Q.z, f, g) // Z = F * G
fp.Mul(&Q.x, e, f) // X = E * F
fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H
return Q
}
// push sends a point on the twist curve to a point on the Goldilocks curve.
func (twistCurve) push(P *twistPoint) *Point {
Q := &Point{}
Px, Py, Pz := &P.x, &P.y, &P.z
a, b, c, d, e, f, g, h := &Q.x, &Q.y, &Q.z, &fp.Elt{}, &Q.ta, &Q.x, &Q.y, &Q.tb
fp.Add(e, Px, Py) // x+y
fp.Sqr(a, Px) // A = x^2
fp.Sqr(b, Py) // B = y^2
fp.Sqr(c, Pz) // z^2
fp.Add(c, c, c) // C = 2*z^2
fp.Neg(d, a) // D = -A
fp.Sqr(e, e) // (x+y)^2
fp.Sub(e, e, a) // (x+y)^2-A
fp.Sub(e, e, b) // E = (x+y)^2-A-B
fp.Add(h, b, d) // H = B+D
fp.Sub(g, b, d) // G = B-D
fp.Sub(f, c, h) // F = C-H
fp.Mul(&Q.z, f, g) // Z = F * G
fp.Mul(&Q.x, e, f) // X = E * F
fp.Mul(&Q.y, g, h) // Y = G * H, // T = E * H
return Q
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/point.go
================================================
package goldilocks
import (
"errors"
"fmt"
fp "github.com/cloudflare/circl/math/fp448"
)
// Point is a point on the Goldilocks Curve.
type Point struct{ x, y, z, ta, tb fp.Elt }
func (P Point) String() string {
return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb)
}
// FromAffine creates a point from affine coordinates.
func FromAffine(x, y *fp.Elt) (*Point, error) {
P := &Point{
x: *x,
y: *y,
z: fp.One(),
ta: *x,
tb: *y,
}
if !(Curve{}).IsOnCurve(P) {
return P, errors.New("point not on curve")
}
return P, nil
}
// isLessThan returns true if 0 <= x < y, and assumes that slices are of the
// same length and are interpreted in little-endian order.
func isLessThan(x, y []byte) bool {
i := len(x) - 1
for i > 0 && x[i] == y[i] {
i--
}
return x[i] < y[i]
}
// FromBytes returns a point from the input buffer.
func FromBytes(in []byte) (*Point, error) {
if len(in) < fp.Size+1 {
return nil, errors.New("wrong input length")
}
err := errors.New("invalid decoding")
P := &Point{}
signX := in[fp.Size] >> 7
copy(P.y[:], in[:fp.Size])
p := fp.P()
if !isLessThan(P.y[:], p[:]) {
return nil, err
}
u, v := &fp.Elt{}, &fp.Elt{}
one := fp.One()
fp.Sqr(u, &P.y) // u = y^2
fp.Mul(v, u, ¶mD) // v = dy^2
fp.Sub(u, u, &one) // u = y^2-1
fp.Sub(v, v, &one) // v = dy^2-1
isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v)
if !isQR {
return nil, err
}
fp.Modp(&P.x) // x = x mod p
if fp.IsZero(&P.x) && signX == 1 {
return nil, err
}
if signX != (P.x[0] & 1) {
fp.Neg(&P.x, &P.x)
}
P.ta = P.x
P.tb = P.y
P.z = fp.One()
return P, nil
}
// IsIdentity returns true is P is the identity Point.
func (P *Point) IsIdentity() bool {
return fp.IsZero(&P.x) && !fp.IsZero(&P.y) && !fp.IsZero(&P.z) && P.y == P.z
}
// IsEqual returns true if P is equivalent to Q.
func (P *Point) IsEqual(Q *Point) bool {
l, r := &fp.Elt{}, &fp.Elt{}
fp.Mul(l, &P.x, &Q.z)
fp.Mul(r, &Q.x, &P.z)
fp.Sub(l, l, r)
b := fp.IsZero(l)
fp.Mul(l, &P.y, &Q.z)
fp.Mul(r, &Q.y, &P.z)
fp.Sub(l, l, r)
b = b && fp.IsZero(l)
fp.Mul(l, &P.ta, &P.tb)
fp.Mul(l, l, &Q.z)
fp.Mul(r, &Q.ta, &Q.tb)
fp.Mul(r, r, &P.z)
fp.Sub(l, l, r)
b = b && fp.IsZero(l)
return b
}
// Neg obtains the inverse of the Point.
func (P *Point) Neg() { fp.Neg(&P.x, &P.x); fp.Neg(&P.ta, &P.ta) }
// ToAffine returns the x,y affine coordinates of P.
func (P *Point) ToAffine() (x, y fp.Elt) {
fp.Inv(&P.z, &P.z) // 1/z
fp.Mul(&P.x, &P.x, &P.z) // x/z
fp.Mul(&P.y, &P.y, &P.z) // y/z
fp.Modp(&P.x)
fp.Modp(&P.y)
fp.SetOne(&P.z)
P.ta = P.x
P.tb = P.y
return P.x, P.y
}
// ToBytes stores P into a slice of bytes.
func (P *Point) ToBytes(out []byte) error {
if len(out) < fp.Size+1 {
return errors.New("invalid decoding")
}
x, y := P.ToAffine()
out[fp.Size] = (x[0] & 1) << 7
return fp.ToBytes(out[:fp.Size], &y)
}
// MarshalBinary encodes the receiver into a binary form and returns the result.
func (P *Point) MarshalBinary() (data []byte, err error) {
data = make([]byte, fp.Size+1)
err = P.ToBytes(data[:fp.Size+1])
return data, err
}
// UnmarshalBinary must be able to decode the form generated by MarshalBinary.
func (P *Point) UnmarshalBinary(data []byte) error { Q, err := FromBytes(data); *P = *Q; return err }
// Double sets P = 2Q.
func (P *Point) Double() { P.Add(P) }
// Add sets P =P+Q..
func (P *Point) Add(Q *Point) {
// This is formula (5) from "Twisted Edwards Curves Revisited" by
// Hisil H., Wong K.KH., Carter G., Dawson E. (2008)
// https://doi.org/10.1007/978-3-540-89255-7_20
x1, y1, z1, ta1, tb1 := &P.x, &P.y, &P.z, &P.ta, &P.tb
x2, y2, z2, ta2, tb2 := &Q.x, &Q.y, &Q.z, &Q.ta, &Q.tb
x3, y3, z3, E, H := &P.x, &P.y, &P.z, &P.ta, &P.tb
A, B, C, D := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}, &fp.Elt{}
t1, t2, F, G := C, D, &fp.Elt{}, &fp.Elt{}
fp.Mul(t1, ta1, tb1) // t1 = ta1*tb1
fp.Mul(t2, ta2, tb2) // t2 = ta2*tb2
fp.Mul(A, x1, x2) // A = x1*x2
fp.Mul(B, y1, y2) // B = y1*y2
fp.Mul(C, t1, t2) // t1*t2
fp.Mul(C, C, ¶mD) // C = d*t1*t2
fp.Mul(D, z1, z2) // D = z1*z2
fp.Add(F, x1, y1) // x1+y1
fp.Add(E, x2, y2) // x2+y2
fp.Mul(E, E, F) // (x1+y1)*(x2+y2)
fp.Sub(E, E, A) // (x1+y1)*(x2+y2)-A
fp.Sub(E, E, B) // E = (x1+y1)*(x2+y2)-A-B
fp.Sub(F, D, C) // F = D-C
fp.Add(G, D, C) // G = D+C
fp.Sub(H, B, A) // H = B-A
fp.Mul(z3, F, G) // Z = F * G
fp.Mul(x3, E, F) // X = E * F
fp.Mul(y3, G, H) // Y = G * H, T = E * H
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/scalar.go
================================================
package goldilocks
import (
"encoding/binary"
"math/bits"
)
// ScalarSize is the size (in bytes) of scalars.
const ScalarSize = 56 // 448 / 8
// _N is the number of 64-bit words to store scalars.
const _N = 7 // 448 / 64
// Scalar represents a positive integer stored in little-endian order.
type Scalar [ScalarSize]byte
type scalar64 [_N]uint64
func (z *scalar64) fromScalar(x *Scalar) {
z[0] = binary.LittleEndian.Uint64(x[0*8 : 1*8])
z[1] = binary.LittleEndian.Uint64(x[1*8 : 2*8])
z[2] = binary.LittleEndian.Uint64(x[2*8 : 3*8])
z[3] = binary.LittleEndian.Uint64(x[3*8 : 4*8])
z[4] = binary.LittleEndian.Uint64(x[4*8 : 5*8])
z[5] = binary.LittleEndian.Uint64(x[5*8 : 6*8])
z[6] = binary.LittleEndian.Uint64(x[6*8 : 7*8])
}
func (z *scalar64) toScalar(x *Scalar) {
binary.LittleEndian.PutUint64(x[0*8:1*8], z[0])
binary.LittleEndian.PutUint64(x[1*8:2*8], z[1])
binary.LittleEndian.PutUint64(x[2*8:3*8], z[2])
binary.LittleEndian.PutUint64(x[3*8:4*8], z[3])
binary.LittleEndian.PutUint64(x[4*8:5*8], z[4])
binary.LittleEndian.PutUint64(x[5*8:6*8], z[5])
binary.LittleEndian.PutUint64(x[6*8:7*8], z[6])
}
// add calculates z = x + y. Assumes len(z) > max(len(x),len(y)).
func add(z, x, y []uint64) uint64 {
l, L, zz := len(x), len(y), y
if l > L {
l, L, zz = L, l, x
}
c := uint64(0)
for i := 0; i < l; i++ {
z[i], c = bits.Add64(x[i], y[i], c)
}
for i := l; i < L; i++ {
z[i], c = bits.Add64(zz[i], 0, c)
}
return c
}
// sub calculates z = x - y. Assumes len(z) > max(len(x),len(y)).
func sub(z, x, y []uint64) uint64 {
l, L, zz := len(x), len(y), y
if l > L {
l, L, zz = L, l, x
}
c := uint64(0)
for i := 0; i < l; i++ {
z[i], c = bits.Sub64(x[i], y[i], c)
}
for i := l; i < L; i++ {
z[i], c = bits.Sub64(zz[i], 0, c)
}
return c
}
// mulWord calculates z = x * y. Assumes len(z) >= len(x)+1.
func mulWord(z, x []uint64, y uint64) {
for i := range z {
z[i] = 0
}
carry := uint64(0)
for i := range x {
hi, lo := bits.Mul64(x[i], y)
lo, cc := bits.Add64(lo, z[i], 0)
hi, _ = bits.Add64(hi, 0, cc)
z[i], cc = bits.Add64(lo, carry, 0)
carry, _ = bits.Add64(hi, 0, cc)
}
z[len(x)] = carry
}
// Cmov moves x into z if b=1.
func (z *scalar64) Cmov(b uint64, x *scalar64) {
m := uint64(0) - b
for i := range z {
z[i] = (z[i] &^ m) | (x[i] & m)
}
}
// leftShift shifts to the left the words of z returning the more significant word.
func (z *scalar64) leftShift(low uint64) uint64 {
high := z[_N-1]
for i := _N - 1; i > 0; i-- {
z[i] = z[i-1]
}
z[0] = low
return high
}
// reduceOneWord calculates z = z + 2^448*x such that the result fits in a Scalar.
func (z *scalar64) reduceOneWord(x uint64) {
prod := (&scalar64{})[:]
mulWord(prod, residue448[:], x)
cc := add(z[:], z[:], prod)
mulWord(prod, residue448[:], cc)
add(z[:], z[:], prod)
}
// modOrder reduces z mod order.
func (z *scalar64) modOrder() {
var o64, x scalar64
o64.fromScalar(&order)
// Performs: while (z >= order) { z = z-order }
// At most 8 (eight) iterations reduce 3 bits by subtracting.
for i := 0; i < 8; i++ {
c := sub(x[:], z[:], o64[:]) // (c || x) = z-order
z.Cmov(1-c, &x) // if c != 0 { z = x }
}
}
// FromBytes stores z = x mod order, where x is a number stored in little-endian order.
func (z *Scalar) FromBytes(x []byte) {
n := len(x)
nCeil := (n + 7) >> 3
for i := range z {
z[i] = 0
}
if nCeil < _N {
copy(z[:], x)
return
}
copy(z[:], x[8*(nCeil-_N):])
var z64 scalar64
z64.fromScalar(z)
for i := nCeil - _N - 1; i >= 0; i-- {
low := binary.LittleEndian.Uint64(x[8*i:])
high := z64.leftShift(low)
z64.reduceOneWord(high)
}
z64.modOrder()
z64.toScalar(z)
}
// divBy4 calculates z = x/4 mod order.
func (z *Scalar) divBy4(x *Scalar) { z.Mul(x, &invFour) }
// Red reduces z mod order.
func (z *Scalar) Red() { var t scalar64; t.fromScalar(z); t.modOrder(); t.toScalar(z) }
// Neg calculates z = -z mod order.
func (z *Scalar) Neg() { z.Sub(&order, z) }
// Add calculates z = x+y mod order.
func (z *Scalar) Add(x, y *Scalar) {
var z64, x64, y64, t scalar64
x64.fromScalar(x)
y64.fromScalar(y)
c := add(z64[:], x64[:], y64[:])
add(t[:], z64[:], residue448[:])
z64.Cmov(c, &t)
z64.modOrder()
z64.toScalar(z)
}
// Sub calculates z = x-y mod order.
func (z *Scalar) Sub(x, y *Scalar) {
var z64, x64, y64, t scalar64
x64.fromScalar(x)
y64.fromScalar(y)
c := sub(z64[:], x64[:], y64[:])
sub(t[:], z64[:], residue448[:])
z64.Cmov(c, &t)
z64.modOrder()
z64.toScalar(z)
}
// Mul calculates z = x*y mod order.
func (z *Scalar) Mul(x, y *Scalar) {
var z64, x64, y64 scalar64
prod := (&[_N + 1]uint64{})[:]
x64.fromScalar(x)
y64.fromScalar(y)
mulWord(prod, x64[:], y64[_N-1])
copy(z64[:], prod[:_N])
z64.reduceOneWord(prod[_N])
for i := _N - 2; i >= 0; i-- {
h := z64.leftShift(0)
z64.reduceOneWord(h)
mulWord(prod, x64[:], y64[i])
c := add(z64[:], z64[:], prod[:_N])
z64.reduceOneWord(prod[_N] + c)
}
z64.modOrder()
z64.toScalar(z)
}
// IsZero returns true if z=0.
func (z *Scalar) IsZero() bool { z.Red(); return *z == Scalar{} }
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/twist.go
================================================
package goldilocks
import (
"crypto/subtle"
"math/bits"
"github.com/cloudflare/circl/internal/conv"
"github.com/cloudflare/circl/math"
fp "github.com/cloudflare/circl/math/fp448"
)
// twistCurve is -x^2+y^2=1-39082x^2y^2 and is 4-isogenous to Goldilocks.
type twistCurve struct{}
// Identity returns the identity point.
func (twistCurve) Identity() *twistPoint {
return &twistPoint{
y: fp.One(),
z: fp.One(),
}
}
// subYDiv16 update x = (x - y) / 16.
func subYDiv16(x *scalar64, y int64) {
s := uint64(y >> 63)
x0, b0 := bits.Sub64((*x)[0], uint64(y), 0)
x1, b1 := bits.Sub64((*x)[1], s, b0)
x2, b2 := bits.Sub64((*x)[2], s, b1)
x3, b3 := bits.Sub64((*x)[3], s, b2)
x4, b4 := bits.Sub64((*x)[4], s, b3)
x5, b5 := bits.Sub64((*x)[5], s, b4)
x6, _ := bits.Sub64((*x)[6], s, b5)
x[0] = (x0 >> 4) | (x1 << 60)
x[1] = (x1 >> 4) | (x2 << 60)
x[2] = (x2 >> 4) | (x3 << 60)
x[3] = (x3 >> 4) | (x4 << 60)
x[4] = (x4 >> 4) | (x5 << 60)
x[5] = (x5 >> 4) | (x6 << 60)
x[6] = (x6 >> 4)
}
func recodeScalar(d *[113]int8, k *Scalar) {
var k64 scalar64
k64.fromScalar(k)
for i := 0; i < 112; i++ {
d[i] = int8((k64[0] & 0x1f) - 16)
subYDiv16(&k64, int64(d[i]))
}
d[112] = int8(k64[0])
}
// ScalarMult returns kP.
func (e twistCurve) ScalarMult(k *Scalar, P *twistPoint) *twistPoint {
var TabP [8]preTwistPointProy
var S preTwistPointProy
var d [113]int8
var isZero int
if k.IsZero() {
isZero = 1
}
subtle.ConstantTimeCopy(isZero, k[:], order[:])
minusK := *k
isEven := 1 - int(k[0]&0x1)
minusK.Neg()
subtle.ConstantTimeCopy(isEven, k[:], minusK[:])
recodeScalar(&d, k)
P.oddMultiples(TabP[:])
Q := e.Identity()
for i := 112; i >= 0; i-- {
Q.Double()
Q.Double()
Q.Double()
Q.Double()
mask := d[i] >> 7
absDi := (d[i] + mask) ^ mask
inx := int32((absDi - 1) >> 1)
sig := int((d[i] >> 7) & 0x1)
for j := range TabP {
S.cmov(&TabP[j], uint(subtle.ConstantTimeEq(inx, int32(j))))
}
S.cneg(sig)
Q.mixAdd(&S)
}
Q.cneg(uint(isEven))
return Q
}
const (
omegaFix = 7
omegaVar = 5
)
// CombinedMult returns mG+nP.
func (e twistCurve) CombinedMult(m, n *Scalar, P *twistPoint) *twistPoint {
nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m[:]), omegaFix)
nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n[:]), omegaVar)
if len(nafFix) > len(nafVar) {
nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...)
} else if len(nafFix) < len(nafVar) {
nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...)
}
var TabQ [1 << (omegaVar - 2)]preTwistPointProy
P.oddMultiples(TabQ[:])
Q := e.Identity()
for i := len(nafFix) - 1; i >= 0; i-- {
Q.Double()
// Generator point
if nafFix[i] != 0 {
idxM := absolute(nafFix[i]) >> 1
R := tabVerif[idxM]
if nafFix[i] < 0 {
R.neg()
}
Q.mixAddZ1(&R)
}
// Variable input point
if nafVar[i] != 0 {
idxN := absolute(nafVar[i]) >> 1
S := TabQ[idxN]
if nafVar[i] < 0 {
S.neg()
}
Q.mixAdd(&S)
}
}
return Q
}
// absolute returns always a positive value.
func absolute(x int32) int32 {
mask := x >> 31
return (x + mask) ^ mask
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/twistPoint.go
================================================
package goldilocks
import (
"fmt"
fp "github.com/cloudflare/circl/math/fp448"
)
type twistPoint struct{ x, y, z, ta, tb fp.Elt }
type preTwistPointAffine struct{ addYX, subYX, dt2 fp.Elt }
type preTwistPointProy struct {
preTwistPointAffine
z2 fp.Elt
}
func (P *twistPoint) String() string {
return fmt.Sprintf("x: %v\ny: %v\nz: %v\nta: %v\ntb: %v", P.x, P.y, P.z, P.ta, P.tb)
}
// cneg conditionally negates the point if b=1.
func (P *twistPoint) cneg(b uint) {
t := &fp.Elt{}
fp.Neg(t, &P.x)
fp.Cmov(&P.x, t, b)
fp.Neg(t, &P.ta)
fp.Cmov(&P.ta, t, b)
}
// Double updates P with 2P.
func (P *twistPoint) Double() {
// This is formula (7) from "Twisted Edwards Curves Revisited" by
// Hisil H., Wong K.KH., Carter G., Dawson E. (2008)
// https://doi.org/10.1007/978-3-540-89255-7_20
Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb
a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb
fp.Add(e, Px, Py) // x+y
fp.Sqr(a, Px) // A = x^2
fp.Sqr(b, Py) // B = y^2
fp.Sqr(c, Pz) // z^2
fp.Add(c, c, c) // C = 2*z^2
fp.Add(h, a, b) // H = A+B
fp.Sqr(e, e) // (x+y)^2
fp.Sub(e, e, h) // E = (x+y)^2-A-B
fp.Sub(g, b, a) // G = B-A
fp.Sub(f, c, g) // F = C-G
fp.Mul(Pz, f, g) // Z = F * G
fp.Mul(Px, e, f) // X = E * F
fp.Mul(Py, g, h) // Y = G * H, T = E * H
}
// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q = 1.
func (P *twistPoint) mixAddZ1(Q *preTwistPointAffine) {
fp.Add(&P.z, &P.z, &P.z) // D = 2*z1 (z2=1)
P.coreAddition(Q)
}
// coreAddition calculates P=P+Q for curves with A=-1.
func (P *twistPoint) coreAddition(Q *preTwistPointAffine) {
// This is the formula following (5) from "Twisted Edwards Curves Revisited" by
// Hisil H., Wong K.KH., Carter G., Dawson E. (2008)
// https://doi.org/10.1007/978-3-540-89255-7_20
Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb
addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2
a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb
fp.Mul(c, Pta, Ptb) // t1 = ta*tb
fp.Sub(h, Py, Px) // y1-x1
fp.Add(b, Py, Px) // y1+x1
fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2)
fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2)
fp.Mul(c, c, dt2) // C = 2*D*t1*t2
fp.Sub(e, b, a) // E = B-A
fp.Add(h, b, a) // H = B+A
fp.Sub(f, d, c) // F = D-C
fp.Add(g, d, c) // G = D+C
fp.Mul(Pz, f, g) // Z = F * G
fp.Mul(Px, e, f) // X = E * F
fp.Mul(Py, g, h) // Y = G * H, T = E * H
}
func (P *preTwistPointAffine) neg() {
P.addYX, P.subYX = P.subYX, P.addYX
fp.Neg(&P.dt2, &P.dt2)
}
func (P *preTwistPointAffine) cneg(b int) {
t := &fp.Elt{}
fp.Cswap(&P.addYX, &P.subYX, uint(b))
fp.Neg(t, &P.dt2)
fp.Cmov(&P.dt2, t, uint(b))
}
func (P *preTwistPointAffine) cmov(Q *preTwistPointAffine, b uint) {
fp.Cmov(&P.addYX, &Q.addYX, b)
fp.Cmov(&P.subYX, &Q.subYX, b)
fp.Cmov(&P.dt2, &Q.dt2, b)
}
// mixAdd calculates P= P+Q, where Q is a precomputed point with Z_Q != 1.
func (P *twistPoint) mixAdd(Q *preTwistPointProy) {
fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2
P.coreAddition(&Q.preTwistPointAffine)
}
// oddMultiples calculates T[i] = (2*i-1)P for 0 < i < len(T).
func (P *twistPoint) oddMultiples(T []preTwistPointProy) {
if n := len(T); n > 0 {
T[0].FromTwistPoint(P)
_2P := *P
_2P.Double()
R := &preTwistPointProy{}
R.FromTwistPoint(&_2P)
for i := 1; i < n; i++ {
P.mixAdd(R)
T[i].FromTwistPoint(P)
}
}
}
// cmov conditionally moves Q into P if b=1.
func (P *preTwistPointProy) cmov(Q *preTwistPointProy, b uint) {
P.preTwistPointAffine.cmov(&Q.preTwistPointAffine, b)
fp.Cmov(&P.z2, &Q.z2, b)
}
// FromTwistPoint precomputes some coordinates of Q for missed addition.
func (P *preTwistPointProy) FromTwistPoint(Q *twistPoint) {
fp.Add(&P.addYX, &Q.y, &Q.x) // addYX = X + Y
fp.Sub(&P.subYX, &Q.y, &Q.x) // subYX = Y - X
fp.Mul(&P.dt2, &Q.ta, &Q.tb) // T = ta*tb
fp.Mul(&P.dt2, &P.dt2, ¶mDTwist) // D*T
fp.Add(&P.dt2, &P.dt2, &P.dt2) // dt2 = 2*D*T
fp.Add(&P.z2, &Q.z, &Q.z) // z2 = 2*Z
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/twistTables.go
================================================
package goldilocks
import fp "github.com/cloudflare/circl/math/fp448"
var tabFixMult = [fxV][fx2w1]preTwistPointAffine{
{
{
addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05},
subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05},
dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55},
},
{
addYX: fp.Elt{0xca, 0xd8, 0x7d, 0x86, 0x1a, 0xef, 0xad, 0x11, 0xe3, 0x27, 0x41, 0x7e, 0x7f, 0x3e, 0xa9, 0xd2, 0xb5, 0x4e, 0x50, 0xe0, 0x77, 0x91, 0xc2, 0x13, 0x52, 0x73, 0x41, 0x09, 0xa6, 0x57, 0x9a, 0xc8, 0xa8, 0x90, 0x9d, 0x26, 0x14, 0xbb, 0xa1, 0x2a, 0xf7, 0x45, 0x43, 0x4e, 0xea, 0x35, 0x62, 0xe1, 0x08, 0x85, 0x46, 0xb8, 0x24, 0x05, 0x2d, 0xab},
subYX: fp.Elt{0x9b, 0xe6, 0xd3, 0xe5, 0xfe, 0x50, 0x36, 0x3c, 0x3c, 0x6d, 0x74, 0x1d, 0x74, 0xc0, 0xde, 0x5b, 0x45, 0x27, 0xe5, 0x12, 0xee, 0x63, 0x35, 0x6b, 0x13, 0xe2, 0x41, 0x6b, 0x3a, 0x05, 0x2b, 0xb1, 0x89, 0x26, 0xb6, 0xc6, 0xd1, 0x84, 0xff, 0x0e, 0x9b, 0xa3, 0xfb, 0x21, 0x36, 0x6b, 0x01, 0xf7, 0x9f, 0x7c, 0xeb, 0xf5, 0x18, 0x7a, 0x2a, 0x70},
dt2: fp.Elt{0x09, 0xad, 0x99, 0x1a, 0x38, 0xd3, 0xdf, 0x22, 0x37, 0x32, 0x61, 0x8b, 0xf3, 0x19, 0x48, 0x08, 0xe8, 0x49, 0xb6, 0x4a, 0xa7, 0xed, 0xa4, 0xa2, 0xee, 0x86, 0xd7, 0x31, 0x5e, 0xce, 0x95, 0x76, 0x86, 0x42, 0x1c, 0x9d, 0x07, 0x14, 0x8c, 0x34, 0x18, 0x9c, 0x6d, 0x3a, 0xdf, 0xa9, 0xe8, 0x36, 0x7e, 0xe4, 0x95, 0xbe, 0xb5, 0x09, 0xf8, 0x9c},
},
{
addYX: fp.Elt{0x51, 0xdb, 0x49, 0xa8, 0x9f, 0xe3, 0xd7, 0xec, 0x0d, 0x0f, 0x49, 0xe8, 0xb6, 0xc5, 0x0f, 0x5a, 0x1c, 0xce, 0x54, 0x0d, 0xb1, 0x8d, 0x5b, 0xbf, 0xf4, 0xaa, 0x34, 0x77, 0xc4, 0x5d, 0x59, 0xb6, 0xc5, 0x0e, 0x5a, 0xd8, 0x5b, 0x30, 0xc2, 0x1d, 0xec, 0x85, 0x1c, 0x42, 0xbe, 0x24, 0x2e, 0x50, 0x55, 0x44, 0xb2, 0x3a, 0x01, 0xaa, 0x98, 0xfb},
subYX: fp.Elt{0xe7, 0x29, 0xb7, 0xd0, 0xaa, 0x4f, 0x32, 0x53, 0x56, 0xde, 0xbc, 0xd1, 0x92, 0x5d, 0x19, 0xbe, 0xa3, 0xe3, 0x75, 0x48, 0xe0, 0x7a, 0x1b, 0x54, 0x7a, 0xb7, 0x41, 0x77, 0x84, 0x38, 0xdd, 0x14, 0x9f, 0xca, 0x3f, 0xa3, 0xc8, 0xa7, 0x04, 0x70, 0xf1, 0x4d, 0x3d, 0xb3, 0x84, 0x79, 0xcb, 0xdb, 0xe4, 0xc5, 0x42, 0x9b, 0x57, 0x19, 0xf1, 0x2d},
dt2: fp.Elt{0x20, 0xb4, 0x94, 0x9e, 0xdf, 0x31, 0x44, 0x0b, 0xc9, 0x7b, 0x75, 0x40, 0x9d, 0xd1, 0x96, 0x39, 0x70, 0x71, 0x15, 0xc8, 0x93, 0xd5, 0xc5, 0xe5, 0xba, 0xfe, 0xee, 0x08, 0x6a, 0x98, 0x0a, 0x1b, 0xb2, 0xaa, 0x3a, 0xf4, 0xa4, 0x79, 0xf9, 0x8e, 0x4d, 0x65, 0x10, 0x9b, 0x3a, 0x6e, 0x7c, 0x87, 0x94, 0x92, 0x11, 0x65, 0xbf, 0x1a, 0x09, 0xde},
},
{
addYX: fp.Elt{0xf3, 0x84, 0x76, 0x77, 0xa5, 0x6b, 0x27, 0x3b, 0x83, 0x3d, 0xdf, 0xa0, 0xeb, 0x32, 0x6d, 0x58, 0x81, 0x57, 0x64, 0xc2, 0x21, 0x7c, 0x9b, 0xea, 0xe6, 0xb0, 0x93, 0xf9, 0xe7, 0xc3, 0xed, 0x5a, 0x8e, 0xe2, 0xb4, 0x72, 0x76, 0x66, 0x0f, 0x22, 0x29, 0x94, 0x3e, 0x63, 0x48, 0x5e, 0x80, 0xcb, 0xac, 0xfa, 0x95, 0xb6, 0x4b, 0xc4, 0x95, 0x33},
subYX: fp.Elt{0x0c, 0x55, 0xd1, 0x5e, 0x5f, 0xbf, 0xbf, 0xe2, 0x4c, 0xfc, 0x37, 0x4a, 0xc4, 0xb1, 0xf4, 0x83, 0x61, 0x93, 0x60, 0x8e, 0x9f, 0x31, 0xf0, 0xa0, 0x41, 0xff, 0x1d, 0xe2, 0x7f, 0xca, 0x40, 0xd6, 0x88, 0xe8, 0x91, 0x61, 0xe2, 0x11, 0x18, 0x83, 0xf3, 0x25, 0x2f, 0x3f, 0x49, 0x40, 0xd4, 0x83, 0xe2, 0xd7, 0x74, 0x6a, 0x16, 0x86, 0x4e, 0xab},
dt2: fp.Elt{0xdd, 0x58, 0x65, 0xd8, 0x9f, 0xdd, 0x70, 0x7f, 0x0f, 0xec, 0xbd, 0x5c, 0x5c, 0x9b, 0x7e, 0x1b, 0x9f, 0x79, 0x36, 0x1f, 0xfd, 0x79, 0x10, 0x1c, 0x52, 0xf3, 0x22, 0xa4, 0x1f, 0x71, 0x6e, 0x63, 0x14, 0xf4, 0xa7, 0x3e, 0xbe, 0xad, 0x43, 0x30, 0x38, 0x8c, 0x29, 0xc6, 0xcf, 0x50, 0x75, 0x21, 0xe5, 0x78, 0xfd, 0xb0, 0x9a, 0xc4, 0x6d, 0xd4},
},
},
{
{
addYX: fp.Elt{0x7a, 0xa1, 0x38, 0xa6, 0xfd, 0x0e, 0x96, 0xd5, 0x26, 0x76, 0x86, 0x70, 0x80, 0x30, 0xa6, 0x67, 0xeb, 0xf4, 0x39, 0xdb, 0x22, 0xf5, 0x9f, 0x98, 0xe4, 0xb5, 0x3a, 0x0c, 0x59, 0xbf, 0x85, 0xc6, 0xf0, 0x0b, 0x1c, 0x41, 0x38, 0x09, 0x01, 0xdb, 0xd6, 0x3c, 0xb7, 0xf1, 0x08, 0x6b, 0x4b, 0x9e, 0x63, 0x53, 0x83, 0xd3, 0xab, 0xa3, 0x72, 0x0d},
subYX: fp.Elt{0x84, 0x68, 0x25, 0xe8, 0xe9, 0x8f, 0x91, 0xbf, 0xf7, 0xa4, 0x30, 0xae, 0xea, 0x9f, 0xdd, 0x56, 0x64, 0x09, 0xc9, 0x54, 0x68, 0x4e, 0x33, 0xc5, 0x6f, 0x7b, 0x2d, 0x52, 0x2e, 0x42, 0xbe, 0xbe, 0xf5, 0x64, 0xbf, 0x77, 0x54, 0xdf, 0xb0, 0x10, 0xd2, 0x16, 0x5d, 0xce, 0xaf, 0x9f, 0xfb, 0xa3, 0x63, 0x50, 0xcb, 0xc0, 0xd0, 0x88, 0x44, 0xa3},
dt2: fp.Elt{0xc3, 0x8b, 0xa5, 0xf1, 0x44, 0xe4, 0x41, 0xcd, 0x75, 0xe3, 0x17, 0x69, 0x5b, 0xb9, 0xbb, 0xee, 0x82, 0xbb, 0xce, 0x57, 0xdf, 0x2a, 0x9c, 0x12, 0xab, 0x66, 0x08, 0x68, 0x05, 0x1b, 0x87, 0xee, 0x5d, 0x1e, 0x18, 0x14, 0x22, 0x4b, 0x99, 0x61, 0x75, 0x28, 0xe7, 0x65, 0x1c, 0x36, 0xb6, 0x18, 0x09, 0xa8, 0xdf, 0xef, 0x30, 0x35, 0xbc, 0x58},
},
{
addYX: fp.Elt{0xc5, 0xd3, 0x0e, 0x6f, 0xaf, 0x06, 0x69, 0xc4, 0x07, 0x9e, 0x58, 0x6e, 0x3f, 0x49, 0xd9, 0x0a, 0x3c, 0x2c, 0x37, 0xcd, 0x27, 0x4d, 0x87, 0x91, 0x7a, 0xb0, 0x28, 0xad, 0x2f, 0x68, 0x92, 0x05, 0x97, 0xf1, 0x30, 0x5f, 0x4c, 0x10, 0x20, 0x30, 0xd3, 0x08, 0x3f, 0xc1, 0xc6, 0xb7, 0xb5, 0xd1, 0x71, 0x7b, 0xa8, 0x0a, 0xd8, 0xf5, 0x17, 0xcf},
subYX: fp.Elt{0x64, 0xd4, 0x8f, 0x91, 0x40, 0xab, 0x6e, 0x1a, 0x62, 0x83, 0xdc, 0xd7, 0x30, 0x1a, 0x4a, 0x2a, 0x4c, 0x54, 0x86, 0x19, 0x81, 0x5d, 0x04, 0x52, 0xa3, 0xca, 0x82, 0x38, 0xdc, 0x1e, 0xf0, 0x7a, 0x78, 0x76, 0x49, 0x4f, 0x71, 0xc4, 0x74, 0x2f, 0xf0, 0x5b, 0x2e, 0x5e, 0xac, 0xef, 0x17, 0xe4, 0x8e, 0x6e, 0xed, 0x43, 0x23, 0x61, 0x99, 0x49},
dt2: fp.Elt{0x64, 0x90, 0x72, 0x76, 0xf8, 0x2c, 0x7d, 0x57, 0xf9, 0x30, 0x5e, 0x7a, 0x10, 0x74, 0x19, 0x39, 0xd9, 0xaf, 0x0a, 0xf1, 0x43, 0xed, 0x88, 0x9c, 0x8b, 0xdc, 0x9b, 0x1c, 0x90, 0xe7, 0xf7, 0xa3, 0xa5, 0x0d, 0xc6, 0xbc, 0x30, 0xfb, 0x91, 0x1a, 0x51, 0xba, 0x2d, 0xbe, 0x89, 0xdf, 0x1d, 0xdc, 0x53, 0xa8, 0x82, 0x8a, 0xd3, 0x8d, 0x16, 0x68},
},
{
addYX: fp.Elt{0xef, 0x5c, 0xe3, 0x74, 0xbf, 0x13, 0x4a, 0xbf, 0x66, 0x73, 0x64, 0xb7, 0xd4, 0xce, 0x98, 0x82, 0x05, 0xfa, 0x98, 0x0c, 0x0a, 0xae, 0xe5, 0x6b, 0x9f, 0xac, 0xbb, 0x6e, 0x1f, 0xcf, 0xff, 0xa6, 0x71, 0x9a, 0xa8, 0x7a, 0x9e, 0x64, 0x1f, 0x20, 0x4a, 0x61, 0xa2, 0xd6, 0x50, 0xe3, 0xba, 0x81, 0x0c, 0x50, 0x59, 0x69, 0x59, 0x15, 0x55, 0xdb},
subYX: fp.Elt{0xe8, 0x77, 0x4d, 0xe8, 0x66, 0x3d, 0xc1, 0x00, 0x3c, 0xf2, 0x25, 0x00, 0xdc, 0xb2, 0xe5, 0x9b, 0x12, 0x89, 0xf3, 0xd6, 0xea, 0x85, 0x60, 0xfe, 0x67, 0x91, 0xfd, 0x04, 0x7c, 0xe0, 0xf1, 0x86, 0x06, 0x11, 0x66, 0xee, 0xd4, 0xd5, 0xbe, 0x3b, 0x0f, 0xe3, 0x59, 0xb3, 0x4f, 0x00, 0xb6, 0xce, 0x80, 0xc1, 0x61, 0xf7, 0xaf, 0x04, 0x6a, 0x3c},
dt2: fp.Elt{0x00, 0xd7, 0x32, 0x93, 0x67, 0x70, 0x6f, 0xd7, 0x69, 0xab, 0xb1, 0xd3, 0xdc, 0xd6, 0xa8, 0xdd, 0x35, 0x25, 0xca, 0xd3, 0x8a, 0x6d, 0xce, 0xfb, 0xfd, 0x2b, 0x83, 0xf0, 0xd4, 0xac, 0x66, 0xfb, 0x72, 0x87, 0x7e, 0x55, 0xb7, 0x91, 0x58, 0x10, 0xc3, 0x11, 0x7e, 0x15, 0xfe, 0x7c, 0x55, 0x90, 0xa3, 0x9e, 0xed, 0x9a, 0x7f, 0xa7, 0xb7, 0xeb},
},
{
addYX: fp.Elt{0x25, 0x0f, 0xc2, 0x09, 0x9c, 0x10, 0xc8, 0x7c, 0x93, 0xa7, 0xbe, 0xe9, 0x26, 0x25, 0x7c, 0x21, 0xfe, 0xe7, 0x5f, 0x3c, 0x02, 0x83, 0xa7, 0x9e, 0xdf, 0xc0, 0x94, 0x2b, 0x7d, 0x1a, 0xd0, 0x1d, 0xcc, 0x2e, 0x7d, 0xd4, 0x85, 0xe7, 0xc1, 0x15, 0x66, 0xd6, 0xd6, 0x32, 0xb8, 0xf7, 0x63, 0xaa, 0x3b, 0xa5, 0xea, 0x49, 0xad, 0x88, 0x9b, 0x66},
subYX: fp.Elt{0x09, 0x97, 0x79, 0x36, 0x41, 0x56, 0x9b, 0xdf, 0x15, 0xd8, 0x43, 0x28, 0x17, 0x5b, 0x96, 0xc9, 0xcf, 0x39, 0x1f, 0x13, 0xf7, 0x4d, 0x1d, 0x1f, 0xda, 0x51, 0x56, 0xe7, 0x0a, 0x5a, 0x65, 0xb6, 0x2a, 0x87, 0x49, 0x86, 0xc2, 0x2b, 0xcd, 0xfe, 0x07, 0xf6, 0x4c, 0xe2, 0x1d, 0x9b, 0xd8, 0x82, 0x09, 0x5b, 0x11, 0x10, 0x62, 0x56, 0x89, 0xbd},
dt2: fp.Elt{0xd9, 0x15, 0x73, 0xf2, 0x96, 0x35, 0x53, 0xb0, 0xe7, 0xa8, 0x0b, 0x93, 0x35, 0x0b, 0x3a, 0x00, 0xf5, 0x18, 0xb1, 0xc3, 0x12, 0x3f, 0x91, 0x17, 0xc1, 0x4c, 0x15, 0x5a, 0x86, 0x92, 0x11, 0xbd, 0x44, 0x40, 0x5a, 0x7b, 0x15, 0x89, 0xba, 0xc1, 0xc1, 0xbc, 0x43, 0x45, 0xe6, 0x52, 0x02, 0x73, 0x0a, 0xd0, 0x2a, 0x19, 0xda, 0x47, 0xa8, 0xff},
},
},
}
// tabVerif contains the odd multiples of P. The entry T[i] = (2i+1)P, where
// P = phi(G) and G is the generator of the Goldilocks curve, and phi is a
// 4-degree isogeny.
var tabVerif = [1 << (omegaFix - 2)]preTwistPointAffine{
{ /* 1P*/
addYX: fp.Elt{0x65, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2b, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05},
subYX: fp.Elt{0x64, 0x4a, 0xdd, 0xdf, 0xb4, 0x79, 0x60, 0xc8, 0xa1, 0x70, 0xb4, 0x3a, 0x1e, 0x0c, 0x9b, 0x19, 0xe5, 0x48, 0x3f, 0xd7, 0x44, 0x18, 0x18, 0x14, 0x14, 0x27, 0x45, 0xd0, 0x2d, 0x24, 0xd5, 0x93, 0xc3, 0x74, 0x4c, 0x50, 0x70, 0x43, 0x26, 0x05, 0x08, 0x24, 0xca, 0x78, 0x30, 0xc1, 0x06, 0x8d, 0xd4, 0x86, 0x42, 0xf0, 0x14, 0xde, 0x08, 0x05},
dt2: fp.Elt{0x1a, 0x33, 0xea, 0x64, 0x45, 0x1c, 0xdf, 0x17, 0x1d, 0x16, 0x34, 0x28, 0xd6, 0x61, 0x19, 0x67, 0x79, 0xb4, 0x13, 0xcf, 0x3e, 0x7c, 0x0e, 0x72, 0xda, 0xf1, 0x5f, 0xda, 0xe6, 0xcf, 0x42, 0xd3, 0xb6, 0x17, 0xc2, 0x68, 0x13, 0x2d, 0xd9, 0x60, 0x3e, 0xae, 0xf0, 0x5b, 0x96, 0xf0, 0xcd, 0xaf, 0xea, 0xb7, 0x0d, 0x59, 0x16, 0xa7, 0xff, 0x55},
},
{ /* 3P*/
addYX: fp.Elt{0xd1, 0xe9, 0xa8, 0x33, 0x20, 0x76, 0x18, 0x08, 0x45, 0x2a, 0xc9, 0x67, 0x2a, 0xc3, 0x15, 0x24, 0xf9, 0x74, 0x21, 0x30, 0x99, 0x59, 0x8b, 0xb2, 0xf0, 0xa4, 0x07, 0xe2, 0x6a, 0x36, 0x8d, 0xd9, 0xd2, 0x4a, 0x7f, 0x73, 0x50, 0x39, 0x3d, 0xaa, 0xa7, 0x51, 0x73, 0x0d, 0x2b, 0x8b, 0x96, 0x47, 0xac, 0x3c, 0x5d, 0xaa, 0x39, 0x9c, 0xcf, 0xd5},
subYX: fp.Elt{0x6b, 0x11, 0x5d, 0x1a, 0xf9, 0x41, 0x9d, 0xc5, 0x30, 0x3e, 0xad, 0x25, 0x2c, 0x04, 0x45, 0xea, 0xcc, 0x67, 0x07, 0x85, 0xe9, 0xda, 0x0e, 0xb5, 0x40, 0xb7, 0x32, 0xb4, 0x49, 0xdd, 0xff, 0xaa, 0xfc, 0xbb, 0x19, 0xca, 0x8b, 0x79, 0x2b, 0x8f, 0x8d, 0x00, 0x33, 0xc2, 0xad, 0xe9, 0xd3, 0x12, 0xa8, 0xaa, 0x87, 0x62, 0xad, 0x2d, 0xff, 0xa4},
dt2: fp.Elt{0xb0, 0xaf, 0x3b, 0xea, 0xf0, 0x42, 0x0b, 0x5e, 0x88, 0xd3, 0x98, 0x08, 0x87, 0x59, 0x72, 0x0a, 0xc2, 0xdf, 0xcb, 0x7f, 0x59, 0xb5, 0x4c, 0x63, 0x68, 0xe8, 0x41, 0x38, 0x67, 0x4f, 0xe9, 0xc6, 0xb2, 0x6b, 0x08, 0xa7, 0xf7, 0x0e, 0xcd, 0xea, 0xca, 0x3d, 0xaf, 0x8e, 0xda, 0x4b, 0x2e, 0xd2, 0x88, 0x64, 0x8d, 0xc5, 0x5f, 0x76, 0x0f, 0x3d},
},
{ /* 5P*/
addYX: fp.Elt{0xe5, 0x65, 0xc9, 0xe2, 0x75, 0xf0, 0x7d, 0x1a, 0xba, 0xa4, 0x40, 0x4b, 0x93, 0x12, 0xa2, 0x80, 0x95, 0x0d, 0x03, 0x93, 0xe8, 0xa5, 0x4d, 0xe2, 0x3d, 0x81, 0xf5, 0xce, 0xd4, 0x2d, 0x25, 0x59, 0x16, 0x5c, 0xe7, 0xda, 0xc7, 0x45, 0xd2, 0x7e, 0x2c, 0x38, 0xd4, 0x37, 0x64, 0xb2, 0xc2, 0x28, 0xc5, 0x72, 0x16, 0x32, 0x45, 0x36, 0x6f, 0x9f},
subYX: fp.Elt{0x09, 0xf4, 0x7e, 0xbd, 0x89, 0xdb, 0x19, 0x58, 0xe1, 0x08, 0x00, 0x8a, 0xf4, 0x5f, 0x2a, 0x32, 0x40, 0xf0, 0x2c, 0x3f, 0x5d, 0xe4, 0xfc, 0x89, 0x11, 0x24, 0xb4, 0x2f, 0x97, 0xad, 0xac, 0x8f, 0x19, 0xab, 0xfa, 0x12, 0xe5, 0xf9, 0x50, 0x4e, 0x50, 0x6f, 0x32, 0x30, 0x88, 0xa6, 0xe5, 0x48, 0x28, 0xa2, 0x1b, 0x9f, 0xcd, 0xe2, 0x43, 0x38},
dt2: fp.Elt{0xa9, 0xcc, 0x53, 0x39, 0x86, 0x02, 0x60, 0x75, 0x34, 0x99, 0x57, 0xbd, 0xfc, 0x5a, 0x8e, 0xce, 0x5e, 0x98, 0x22, 0xd0, 0xa5, 0x24, 0xff, 0x90, 0x28, 0x9f, 0x58, 0xf3, 0x39, 0xe9, 0xba, 0x36, 0x23, 0xfb, 0x7f, 0x41, 0xcc, 0x2b, 0x5a, 0x25, 0x3f, 0x4c, 0x2a, 0xf1, 0x52, 0x6f, 0x2f, 0x07, 0xe3, 0x88, 0x81, 0x77, 0xdd, 0x7c, 0x88, 0x82},
},
{ /* 7P*/
addYX: fp.Elt{0xf7, 0xee, 0x88, 0xfd, 0x3a, 0xbf, 0x7e, 0x28, 0x39, 0x23, 0x79, 0xe6, 0x5c, 0x56, 0xcb, 0xb5, 0x48, 0x6a, 0x80, 0x6d, 0x37, 0x60, 0x6c, 0x10, 0x35, 0x49, 0x4b, 0x46, 0x60, 0xd4, 0x79, 0xd4, 0x53, 0xd3, 0x67, 0x88, 0xd0, 0x41, 0xd5, 0x43, 0x85, 0xc8, 0x71, 0xe3, 0x1c, 0xb6, 0xda, 0x22, 0x64, 0x8f, 0x80, 0xac, 0xad, 0x7d, 0xd5, 0x82},
subYX: fp.Elt{0x92, 0x40, 0xc1, 0x83, 0x21, 0x9b, 0xd5, 0x7d, 0x3f, 0x29, 0xb6, 0x26, 0xef, 0x12, 0xb9, 0x27, 0x39, 0x42, 0x37, 0x97, 0x09, 0x9a, 0x08, 0xe1, 0x68, 0xb6, 0x7a, 0x3f, 0x9f, 0x45, 0xf8, 0x37, 0x19, 0x83, 0x97, 0xe6, 0x73, 0x30, 0x32, 0x35, 0xcf, 0xae, 0x5c, 0x12, 0x68, 0xdf, 0x6e, 0x2b, 0xde, 0x83, 0xa0, 0x44, 0x74, 0x2e, 0x4a, 0xe9},
dt2: fp.Elt{0xcb, 0x22, 0x0a, 0xda, 0x6b, 0xc1, 0x8a, 0x29, 0xa1, 0xac, 0x8b, 0x5b, 0x8b, 0x32, 0x20, 0xf2, 0x21, 0xae, 0x0c, 0x43, 0xc4, 0xd7, 0x19, 0x37, 0x3d, 0x79, 0x25, 0x98, 0x6c, 0x9c, 0x22, 0x31, 0x2a, 0x55, 0x9f, 0xda, 0x5e, 0xa8, 0x13, 0xdb, 0x8e, 0x2e, 0x16, 0x39, 0xf4, 0x91, 0x6f, 0xec, 0x71, 0x71, 0xc9, 0x10, 0xf2, 0xa4, 0x8f, 0x11},
},
{ /* 9P*/
addYX: fp.Elt{0x85, 0xdd, 0x37, 0x62, 0x74, 0x8e, 0x33, 0x5b, 0x25, 0x12, 0x1b, 0xe7, 0xdf, 0x47, 0xe5, 0x12, 0xfd, 0x3a, 0x3a, 0xf5, 0x5d, 0x4c, 0xa2, 0x29, 0x3c, 0x5c, 0x2f, 0xee, 0x18, 0x19, 0x0a, 0x2b, 0xef, 0x67, 0x50, 0x7a, 0x0d, 0x29, 0xae, 0x55, 0x82, 0xcd, 0xd6, 0x41, 0x90, 0xb4, 0x13, 0x31, 0x5d, 0x11, 0xb8, 0xaa, 0x12, 0x86, 0x08, 0xac},
subYX: fp.Elt{0xcc, 0x37, 0x8d, 0x83, 0x5f, 0xfd, 0xde, 0xd5, 0xf7, 0xf1, 0xae, 0x0a, 0xa7, 0x0b, 0xeb, 0x6d, 0x19, 0x8a, 0xb6, 0x1a, 0x59, 0xd8, 0xff, 0x3c, 0xbc, 0xbc, 0xef, 0x9c, 0xda, 0x7b, 0x75, 0x12, 0xaf, 0x80, 0x8f, 0x2c, 0x3c, 0xaa, 0x0b, 0x17, 0x86, 0x36, 0x78, 0x18, 0xc8, 0x8a, 0xf6, 0xb8, 0x2c, 0x2f, 0x57, 0x2c, 0x62, 0x57, 0xf6, 0x90},
dt2: fp.Elt{0x83, 0xbc, 0xa2, 0x07, 0xa5, 0x38, 0x96, 0xea, 0xfe, 0x11, 0x46, 0x1d, 0x3b, 0xcd, 0x42, 0xc5, 0xee, 0x67, 0x04, 0x72, 0x08, 0xd8, 0xd9, 0x96, 0x07, 0xf7, 0xac, 0xc3, 0x64, 0xf1, 0x98, 0x2c, 0x55, 0xd7, 0x7d, 0xc8, 0x6c, 0xbd, 0x2c, 0xff, 0x15, 0xd6, 0x6e, 0xb8, 0x17, 0x8e, 0xa8, 0x27, 0x66, 0xb1, 0x73, 0x79, 0x96, 0xff, 0x29, 0x10},
},
{ /* 11P*/
addYX: fp.Elt{0x76, 0xcb, 0x9b, 0x0c, 0x5b, 0xfe, 0xe1, 0x2a, 0xdd, 0x6f, 0x6c, 0xdd, 0x6f, 0xb4, 0xc0, 0xc2, 0x1b, 0x4b, 0x38, 0xe8, 0x66, 0x8c, 0x1e, 0x31, 0x63, 0xb9, 0x94, 0xcd, 0xc3, 0x8c, 0x44, 0x25, 0x7b, 0xd5, 0x39, 0x80, 0xfc, 0x01, 0xaa, 0xf7, 0x2a, 0x61, 0x8a, 0x25, 0xd2, 0x5f, 0xc5, 0x66, 0x38, 0xa4, 0x17, 0xcf, 0x3e, 0x11, 0x0f, 0xa3},
subYX: fp.Elt{0xe0, 0xb6, 0xd1, 0x9c, 0x71, 0x49, 0x2e, 0x7b, 0xde, 0x00, 0xda, 0x6b, 0xf1, 0xec, 0xe6, 0x7a, 0x15, 0x38, 0x71, 0xe9, 0x7b, 0xdb, 0xf8, 0x98, 0xc0, 0x91, 0x2e, 0x53, 0xee, 0x92, 0x87, 0x25, 0xc9, 0xb0, 0xbb, 0x33, 0x15, 0x46, 0x7f, 0xfd, 0x4f, 0x8b, 0x77, 0x05, 0x96, 0xb6, 0xe2, 0x08, 0xdb, 0x0d, 0x09, 0xee, 0x5b, 0xd1, 0x2a, 0x63},
dt2: fp.Elt{0x8f, 0x7b, 0x57, 0x8c, 0xbf, 0x06, 0x0d, 0x43, 0x21, 0x92, 0x94, 0x2d, 0x6a, 0x38, 0x07, 0x0f, 0xa0, 0xf1, 0xe3, 0xd8, 0x2a, 0xbf, 0x46, 0xc6, 0x9e, 0x1f, 0x8f, 0x2b, 0x46, 0x84, 0x0b, 0x74, 0xed, 0xff, 0xf8, 0xa5, 0x94, 0xae, 0xf1, 0x67, 0xb1, 0x9b, 0xdd, 0x4a, 0xd0, 0xdb, 0xc2, 0xb5, 0x58, 0x49, 0x0c, 0xa9, 0x1d, 0x7d, 0xa9, 0xd3},
},
{ /* 13P*/
addYX: fp.Elt{0x73, 0x84, 0x2e, 0x31, 0x1f, 0xdc, 0xed, 0x9f, 0x74, 0xfa, 0xe0, 0x35, 0xb1, 0x85, 0x6a, 0x8d, 0x86, 0xd0, 0xff, 0xd6, 0x08, 0x43, 0x73, 0x1a, 0xd5, 0xf8, 0x43, 0xd4, 0xb3, 0xe5, 0x3f, 0xa8, 0x84, 0x17, 0x59, 0x65, 0x4e, 0xe6, 0xee, 0x54, 0x9c, 0xda, 0x5e, 0x7e, 0x98, 0x29, 0x6d, 0x73, 0x34, 0x1f, 0x99, 0x80, 0x54, 0x54, 0x81, 0x0b},
subYX: fp.Elt{0xb1, 0xe5, 0xbb, 0x80, 0x22, 0x9c, 0x81, 0x6d, 0xaf, 0x27, 0x65, 0x6f, 0x7e, 0x9c, 0xb6, 0x8d, 0x35, 0x5c, 0x2e, 0x20, 0x48, 0x7a, 0x28, 0xf0, 0x97, 0xfe, 0xb7, 0x71, 0xce, 0xd6, 0xad, 0x3a, 0x81, 0xf6, 0x74, 0x5e, 0xf3, 0xfd, 0x1b, 0xd4, 0x1e, 0x7c, 0xc2, 0xb7, 0xc8, 0xa6, 0xc9, 0x89, 0x03, 0x47, 0xec, 0x24, 0xd6, 0x0e, 0xec, 0x9c},
dt2: fp.Elt{0x91, 0x0a, 0x43, 0x34, 0x20, 0xc2, 0x64, 0xf7, 0x4e, 0x48, 0xc8, 0xd2, 0x95, 0x83, 0xd1, 0xa4, 0xfb, 0x4e, 0x41, 0x3b, 0x0d, 0xd5, 0x07, 0xd9, 0xf1, 0x13, 0x16, 0x78, 0x54, 0x57, 0xd0, 0xf1, 0x4f, 0x20, 0xac, 0xcf, 0x9c, 0x3b, 0x33, 0x0b, 0x99, 0x54, 0xc3, 0x7f, 0x3e, 0x57, 0x26, 0x86, 0xd5, 0xa5, 0x2b, 0x8d, 0xe3, 0x19, 0x36, 0xf7},
},
{ /* 15P*/
addYX: fp.Elt{0x23, 0x69, 0x47, 0x14, 0xf9, 0x9a, 0x50, 0xff, 0x64, 0xd1, 0x50, 0x35, 0xc3, 0x11, 0xd3, 0x19, 0xcf, 0x87, 0xda, 0x30, 0x0b, 0x50, 0xda, 0xc0, 0xe0, 0x25, 0x00, 0xe5, 0x68, 0x93, 0x04, 0xc2, 0xaf, 0xbd, 0x2f, 0x36, 0x5f, 0x47, 0x96, 0x10, 0xa8, 0xbd, 0xe4, 0x88, 0xac, 0x80, 0x52, 0x61, 0x73, 0xe9, 0x63, 0xdd, 0x99, 0xad, 0x20, 0x5b},
subYX: fp.Elt{0x1b, 0x5e, 0xa2, 0x2a, 0x25, 0x0f, 0x86, 0xc0, 0xb1, 0x2e, 0x0c, 0x13, 0x40, 0x8d, 0xf0, 0xe6, 0x00, 0x55, 0x08, 0xc5, 0x7d, 0xf4, 0xc9, 0x31, 0x25, 0x3a, 0x99, 0x69, 0xdd, 0x67, 0x63, 0x9a, 0xd6, 0x89, 0x2e, 0xa1, 0x19, 0xca, 0x2c, 0xd9, 0x59, 0x5f, 0x5d, 0xc3, 0x6e, 0x62, 0x36, 0x12, 0x59, 0x15, 0xe1, 0xdc, 0xa4, 0xad, 0xc9, 0xd0},
dt2: fp.Elt{0xbc, 0xea, 0xfc, 0xaf, 0x66, 0x23, 0xb7, 0x39, 0x6b, 0x2a, 0x96, 0xa8, 0x54, 0x43, 0xe9, 0xaa, 0x32, 0x40, 0x63, 0x92, 0x5e, 0xdf, 0x35, 0xc2, 0x9f, 0x24, 0x0c, 0xed, 0xfc, 0xde, 0x73, 0x8f, 0xa7, 0xd5, 0xa3, 0x2b, 0x18, 0x1f, 0xb0, 0xf8, 0xeb, 0x55, 0xd9, 0xc3, 0xfd, 0x28, 0x7c, 0x4f, 0xce, 0x0d, 0xf7, 0xae, 0xc2, 0x83, 0xc3, 0x78},
},
{ /* 17P*/
addYX: fp.Elt{0x71, 0xe6, 0x60, 0x93, 0x37, 0xdb, 0x01, 0xa5, 0x4c, 0xba, 0xe8, 0x8e, 0xd5, 0xf9, 0xd3, 0x98, 0xe5, 0xeb, 0xab, 0x3a, 0x15, 0x8b, 0x35, 0x60, 0xbe, 0xe5, 0x9c, 0x2d, 0x10, 0x9b, 0x2e, 0xcf, 0x65, 0x64, 0xea, 0x8f, 0x72, 0xce, 0xf5, 0x18, 0xe5, 0xe2, 0xf0, 0x0e, 0xae, 0x04, 0xec, 0xa0, 0x20, 0x65, 0x63, 0x07, 0xb1, 0x9f, 0x03, 0x97},
subYX: fp.Elt{0x9e, 0x41, 0x64, 0x30, 0x95, 0x7f, 0x3a, 0x89, 0x7b, 0x0a, 0x79, 0x59, 0x23, 0x9a, 0x3b, 0xfe, 0xa4, 0x13, 0x08, 0xb2, 0x2e, 0x04, 0x50, 0x10, 0x30, 0xcd, 0x2e, 0xa4, 0x91, 0x71, 0x50, 0x36, 0x4a, 0x02, 0xf4, 0x8d, 0xa3, 0x36, 0x1b, 0xf4, 0x52, 0xba, 0x15, 0x04, 0x8b, 0x80, 0x25, 0xd9, 0xae, 0x67, 0x20, 0xd9, 0x88, 0x8f, 0x97, 0xa6},
dt2: fp.Elt{0xb5, 0xe7, 0x46, 0xbd, 0x55, 0x23, 0xa0, 0x68, 0xc0, 0x12, 0xd9, 0xf1, 0x0a, 0x75, 0xe2, 0xda, 0xf4, 0x6b, 0xca, 0x14, 0xe4, 0x9f, 0x0f, 0xb5, 0x3c, 0xa6, 0xa5, 0xa2, 0x63, 0x94, 0xd1, 0x1c, 0x39, 0x58, 0x57, 0x02, 0x27, 0x98, 0xb6, 0x47, 0xc6, 0x61, 0x4b, 0x5c, 0xab, 0x6f, 0x2d, 0xab, 0xe3, 0xc1, 0x69, 0xf9, 0x12, 0xb0, 0xc8, 0xd5},
},
{ /* 19P*/
addYX: fp.Elt{0x19, 0x7d, 0xd5, 0xac, 0x79, 0xa2, 0x82, 0x9b, 0x28, 0x31, 0x22, 0xc0, 0x73, 0x02, 0x76, 0x17, 0x10, 0x70, 0x79, 0x57, 0xc9, 0x84, 0x62, 0x8e, 0x04, 0x04, 0x61, 0x67, 0x08, 0x48, 0xb4, 0x4b, 0xde, 0x53, 0x8c, 0xff, 0x36, 0x1b, 0x62, 0x86, 0x5d, 0xe1, 0x9b, 0xb1, 0xe5, 0xe8, 0x44, 0x64, 0xa1, 0x68, 0x3f, 0xa8, 0x45, 0x52, 0x91, 0xed},
subYX: fp.Elt{0x42, 0x1a, 0x36, 0x1f, 0x90, 0x15, 0x24, 0x8d, 0x24, 0x80, 0xe6, 0xfe, 0x1e, 0xf0, 0xad, 0xaf, 0x6a, 0x93, 0xf0, 0xa6, 0x0d, 0x5d, 0xea, 0xf6, 0x62, 0x96, 0x7a, 0x05, 0x76, 0x85, 0x74, 0x32, 0xc7, 0xc8, 0x64, 0x53, 0x62, 0xe7, 0x54, 0x84, 0xe0, 0x40, 0x66, 0x19, 0x70, 0x40, 0x95, 0x35, 0x68, 0x64, 0x43, 0xcd, 0xba, 0x29, 0x32, 0xa8},
dt2: fp.Elt{0x3e, 0xf6, 0xd6, 0xe4, 0x99, 0xeb, 0x20, 0x66, 0x08, 0x2e, 0x26, 0x64, 0xd7, 0x76, 0xf3, 0xb4, 0xc5, 0xa4, 0x35, 0x92, 0xd2, 0x99, 0x70, 0x5a, 0x1a, 0xe9, 0xe9, 0x3d, 0x3b, 0xe1, 0xcd, 0x0e, 0xee, 0x24, 0x13, 0x03, 0x22, 0xd6, 0xd6, 0x72, 0x08, 0x2b, 0xde, 0xfd, 0x93, 0xed, 0x0c, 0x7f, 0x5e, 0x31, 0x22, 0x4d, 0x80, 0x78, 0xc0, 0x48},
},
{ /* 21P*/
addYX: fp.Elt{0x8f, 0x72, 0xd2, 0x9e, 0xc4, 0xcd, 0x2c, 0xbf, 0xa8, 0xd3, 0x24, 0x62, 0x28, 0xee, 0x39, 0x0a, 0x19, 0x3a, 0x58, 0xff, 0x21, 0x2e, 0x69, 0x6c, 0x6e, 0x18, 0xd0, 0xcd, 0x61, 0xc1, 0x18, 0x02, 0x5a, 0xe9, 0xe3, 0xef, 0x1f, 0x8e, 0x10, 0xe8, 0x90, 0x2b, 0x48, 0xcd, 0xee, 0x38, 0xbd, 0x3a, 0xca, 0xbc, 0x2d, 0xe2, 0x3a, 0x03, 0x71, 0x02},
subYX: fp.Elt{0xf8, 0xa4, 0x32, 0x26, 0x66, 0xaf, 0x3b, 0x53, 0xe7, 0xb0, 0x91, 0x92, 0xf5, 0x3c, 0x74, 0xce, 0xf2, 0xdd, 0x68, 0xa9, 0xf4, 0xcd, 0x5f, 0x60, 0xab, 0x71, 0xdf, 0xcd, 0x5c, 0x5d, 0x51, 0x72, 0x3a, 0x96, 0xea, 0xd6, 0xde, 0x54, 0x8e, 0x55, 0x4c, 0x08, 0x4c, 0x60, 0xdd, 0x34, 0xa9, 0x6f, 0xf3, 0x04, 0x02, 0xa8, 0xa6, 0x4e, 0x4d, 0x62},
dt2: fp.Elt{0x76, 0x4a, 0xae, 0x38, 0x62, 0x69, 0x72, 0xdc, 0xe8, 0x43, 0xbe, 0x1d, 0x61, 0xde, 0x31, 0xc3, 0x42, 0x8f, 0x33, 0x9d, 0xca, 0xc7, 0x9c, 0xec, 0x6a, 0xe2, 0xaa, 0x01, 0x49, 0x78, 0x8d, 0x72, 0x4f, 0x38, 0xea, 0x52, 0xc2, 0xd3, 0xc9, 0x39, 0x71, 0xba, 0xb9, 0x09, 0x9b, 0xa3, 0x7f, 0x45, 0x43, 0x65, 0x36, 0x29, 0xca, 0xe7, 0x5c, 0x5f},
},
{ /* 23P*/
addYX: fp.Elt{0x89, 0x42, 0x35, 0x48, 0x6d, 0x74, 0xe5, 0x1f, 0xc3, 0xdd, 0x28, 0x5b, 0x84, 0x41, 0x33, 0x9f, 0x42, 0xf3, 0x1d, 0x5d, 0x15, 0x6d, 0x76, 0x33, 0x36, 0xaf, 0xe9, 0xdd, 0xfa, 0x63, 0x4f, 0x7a, 0x9c, 0xeb, 0x1c, 0x4f, 0x34, 0x65, 0x07, 0x54, 0xbb, 0x4c, 0x8b, 0x62, 0x9d, 0xd0, 0x06, 0x99, 0xb3, 0xe9, 0xda, 0x85, 0x19, 0xb0, 0x3d, 0x3c},
subYX: fp.Elt{0xbb, 0x99, 0xf6, 0xbf, 0xaf, 0x2c, 0x22, 0x0d, 0x7a, 0xaa, 0x98, 0x6f, 0x01, 0x82, 0x99, 0xcf, 0x88, 0xbd, 0x0e, 0x3a, 0x89, 0xe0, 0x9c, 0x8c, 0x17, 0x20, 0xc4, 0xe0, 0xcf, 0x43, 0x7a, 0xef, 0x0d, 0x9f, 0x87, 0xd4, 0xfb, 0xf2, 0x96, 0xb8, 0x03, 0xe8, 0xcb, 0x5c, 0xec, 0x65, 0x5f, 0x49, 0xa4, 0x7c, 0x85, 0xb4, 0xf6, 0xc7, 0xdb, 0xa3},
dt2: fp.Elt{0x11, 0xf3, 0x32, 0xa3, 0xa7, 0xb2, 0x7d, 0x51, 0x82, 0x44, 0xeb, 0xa2, 0x7d, 0x72, 0xcb, 0xc6, 0xf6, 0xc7, 0xb2, 0x38, 0x0e, 0x0f, 0x4f, 0x29, 0x00, 0xe4, 0x5b, 0x94, 0x46, 0x86, 0x66, 0xa1, 0x83, 0xb3, 0xeb, 0x15, 0xb6, 0x31, 0x50, 0x28, 0xeb, 0xed, 0x0d, 0x32, 0x39, 0xe9, 0x23, 0x81, 0x99, 0x3e, 0xff, 0x17, 0x4c, 0x11, 0x43, 0xd1},
},
{ /* 25P*/
addYX: fp.Elt{0xce, 0xe7, 0xf8, 0x94, 0x8f, 0x96, 0xf8, 0x96, 0xe6, 0x72, 0x20, 0x44, 0x2c, 0xa7, 0xfc, 0xba, 0xc8, 0xe1, 0xbb, 0xc9, 0x16, 0x85, 0xcd, 0x0b, 0xe5, 0xb5, 0x5a, 0x7f, 0x51, 0x43, 0x63, 0x8b, 0x23, 0x8e, 0x1d, 0x31, 0xff, 0x46, 0x02, 0x66, 0xcc, 0x9e, 0x4d, 0xa2, 0xca, 0xe2, 0xc7, 0xfd, 0x22, 0xb1, 0xdb, 0xdf, 0x6f, 0xe6, 0xa5, 0x82},
subYX: fp.Elt{0xd0, 0xf5, 0x65, 0x40, 0xec, 0x8e, 0x65, 0x42, 0x78, 0xc1, 0x65, 0xe4, 0x10, 0xc8, 0x0b, 0x1b, 0xdd, 0x96, 0x68, 0xce, 0xee, 0x45, 0x55, 0xd8, 0x6e, 0xd3, 0xe6, 0x77, 0x19, 0xae, 0xc2, 0x8d, 0x8d, 0x3e, 0x14, 0x3f, 0x6d, 0x00, 0x2f, 0x9b, 0xd1, 0x26, 0x60, 0x28, 0x0f, 0x3a, 0x47, 0xb3, 0xe6, 0x68, 0x28, 0x24, 0x25, 0xca, 0xc8, 0x06},
dt2: fp.Elt{0x54, 0xbb, 0x60, 0x92, 0xdb, 0x8f, 0x0f, 0x38, 0xe0, 0xe6, 0xe4, 0xc9, 0xcc, 0x14, 0x62, 0x01, 0xc4, 0x2b, 0x0f, 0xcf, 0xed, 0x7d, 0x8e, 0xa4, 0xd9, 0x73, 0x0b, 0xba, 0x0c, 0xaf, 0x0c, 0xf9, 0xe2, 0xeb, 0x29, 0x2a, 0x53, 0xdf, 0x2c, 0x5a, 0xfa, 0x8f, 0xc1, 0x01, 0xd7, 0xb1, 0x45, 0x73, 0x92, 0x32, 0x83, 0x85, 0x12, 0x74, 0x89, 0x44},
},
{ /* 27P*/
addYX: fp.Elt{0x0b, 0x73, 0x3c, 0xc2, 0xb1, 0x2e, 0xe1, 0xa7, 0xf5, 0xc9, 0x7a, 0xfb, 0x3d, 0x2d, 0xac, 0x59, 0xdb, 0xfa, 0x36, 0x11, 0xd1, 0x13, 0x04, 0x51, 0x1d, 0xab, 0x9b, 0x6b, 0x93, 0xfe, 0xda, 0xb0, 0x8e, 0xb4, 0x79, 0x11, 0x21, 0x0f, 0x65, 0xb9, 0xbb, 0x79, 0x96, 0x2a, 0xfd, 0x30, 0xe0, 0xb4, 0x2d, 0x9a, 0x55, 0x25, 0x5d, 0xd4, 0xad, 0x2a},
subYX: fp.Elt{0x9e, 0xc5, 0x04, 0xfe, 0xec, 0x3c, 0x64, 0x1c, 0xed, 0x95, 0xed, 0xae, 0xaf, 0x5c, 0x6e, 0x08, 0x9e, 0x02, 0x29, 0x59, 0x7e, 0x5f, 0xc4, 0x9a, 0xd5, 0x32, 0x72, 0x86, 0xe1, 0x4e, 0x3c, 0xce, 0x99, 0x69, 0x3b, 0xc4, 0xdd, 0x4d, 0xb7, 0xbb, 0xda, 0x3b, 0x1a, 0x99, 0xaa, 0x62, 0x15, 0xc1, 0xf0, 0xb6, 0x6c, 0xec, 0x56, 0xc1, 0xff, 0x0c},
dt2: fp.Elt{0x2f, 0xf1, 0x3f, 0x7a, 0x2d, 0x56, 0x19, 0x7f, 0xea, 0xbe, 0x59, 0x2e, 0x13, 0x67, 0x81, 0xfb, 0xdb, 0xc8, 0xa3, 0x1d, 0xd5, 0xe9, 0x13, 0x8b, 0x29, 0xdf, 0xcf, 0x9f, 0xe7, 0xd9, 0x0b, 0x70, 0xd3, 0x15, 0x57, 0x4a, 0xe9, 0x50, 0x12, 0x1b, 0x81, 0x4b, 0x98, 0x98, 0xa8, 0x31, 0x1d, 0x27, 0x47, 0x38, 0xed, 0x57, 0x99, 0x26, 0xb2, 0xee},
},
{ /* 29P*/
addYX: fp.Elt{0x1c, 0xb2, 0xb2, 0x67, 0x3b, 0x8b, 0x3d, 0x5a, 0x30, 0x7e, 0x38, 0x7e, 0x3c, 0x3d, 0x28, 0x56, 0x59, 0xd8, 0x87, 0x53, 0x8b, 0xe6, 0x6c, 0x5d, 0xe5, 0x0a, 0x33, 0x10, 0xce, 0xa2, 0x17, 0x0d, 0xe8, 0x76, 0xee, 0x68, 0xa8, 0x72, 0x54, 0xbd, 0xa6, 0x24, 0x94, 0x6e, 0x77, 0xc7, 0x53, 0xb7, 0x89, 0x1c, 0x7a, 0xe9, 0x78, 0x9a, 0x74, 0x5f},
subYX: fp.Elt{0x76, 0x96, 0x1c, 0xcf, 0x08, 0x55, 0xd8, 0x1e, 0x0d, 0xa3, 0x59, 0x95, 0x32, 0xf4, 0xc2, 0x8e, 0x84, 0x5e, 0x4b, 0x04, 0xda, 0x71, 0xc9, 0x78, 0x52, 0xde, 0x14, 0xb4, 0x31, 0xf4, 0xd4, 0xb8, 0x58, 0xc5, 0x20, 0xe8, 0xdd, 0x15, 0xb5, 0xee, 0xea, 0x61, 0xe0, 0xf5, 0xd6, 0xae, 0x55, 0x59, 0x05, 0x3e, 0xaf, 0x74, 0xac, 0x1f, 0x17, 0x82},
dt2: fp.Elt{0x59, 0x24, 0xcd, 0xfc, 0x11, 0x7e, 0x85, 0x18, 0x3d, 0x69, 0xf7, 0x71, 0x31, 0x66, 0x98, 0x42, 0x95, 0x00, 0x8c, 0xb2, 0xae, 0x39, 0x7e, 0x85, 0xd6, 0xb0, 0x02, 0xec, 0xce, 0xfc, 0x25, 0xb2, 0xe3, 0x99, 0x8e, 0x5b, 0x61, 0x96, 0x2e, 0x6d, 0x96, 0x57, 0x71, 0xa5, 0x93, 0x41, 0x0e, 0x6f, 0xfd, 0x0a, 0xbf, 0xa9, 0xf7, 0x56, 0xa9, 0x3e},
},
{ /* 31P*/
addYX: fp.Elt{0xa2, 0x2e, 0x0c, 0x17, 0x4d, 0xcc, 0x85, 0x2c, 0x18, 0xa0, 0xd2, 0x08, 0xba, 0x11, 0xfa, 0x47, 0x71, 0x86, 0xaf, 0x36, 0x6a, 0xd7, 0xfe, 0xb9, 0xb0, 0x2f, 0x89, 0x98, 0x49, 0x69, 0xf8, 0x6a, 0xad, 0x27, 0x5e, 0x0a, 0x22, 0x60, 0x5e, 0x5d, 0xca, 0x06, 0x51, 0x27, 0x99, 0x29, 0x85, 0x68, 0x98, 0xe1, 0xc4, 0x21, 0x50, 0xa0, 0xe9, 0xc1},
subYX: fp.Elt{0x4d, 0x70, 0xee, 0x91, 0x92, 0x3f, 0xb7, 0xd3, 0x1d, 0xdb, 0x8d, 0x6e, 0x16, 0xf5, 0x65, 0x7d, 0x5f, 0xb5, 0x6c, 0x59, 0x26, 0x70, 0x4b, 0xf2, 0xfc, 0xe7, 0xdf, 0x86, 0xfe, 0xa5, 0xa7, 0xa6, 0x5d, 0xfb, 0x06, 0xe9, 0xf9, 0xcc, 0xc0, 0x37, 0xcc, 0xd8, 0x09, 0x04, 0xd2, 0xa5, 0x1d, 0xd7, 0xb7, 0xce, 0x92, 0xac, 0x3c, 0xad, 0xfb, 0xae},
dt2: fp.Elt{0x17, 0xa3, 0x9a, 0xc7, 0x86, 0x2a, 0x51, 0xf7, 0x96, 0x79, 0x49, 0x22, 0x2e, 0x5a, 0x01, 0x5c, 0xb5, 0x95, 0xd4, 0xe8, 0xcb, 0x00, 0xca, 0x2d, 0x55, 0xb6, 0x34, 0x36, 0x0b, 0x65, 0x46, 0xf0, 0x49, 0xfc, 0x87, 0x86, 0xe5, 0xc3, 0x15, 0xdb, 0x32, 0xcd, 0xf2, 0xd3, 0x82, 0x4c, 0xe6, 0x61, 0x8a, 0xaf, 0xd4, 0x9e, 0x0f, 0x5a, 0xf2, 0x81},
},
{ /* 33P*/
addYX: fp.Elt{0x88, 0x10, 0xc0, 0xcb, 0xf5, 0x77, 0xae, 0xa5, 0xbe, 0xf6, 0xcd, 0x2e, 0x8b, 0x7e, 0xbd, 0x79, 0x62, 0x4a, 0xeb, 0x69, 0xc3, 0x28, 0xaa, 0x72, 0x87, 0xa9, 0x25, 0x87, 0x46, 0xea, 0x0e, 0x62, 0xa3, 0x6a, 0x1a, 0xe2, 0xba, 0xdc, 0x81, 0x10, 0x33, 0x01, 0xf6, 0x16, 0x89, 0x80, 0xc6, 0xcd, 0xdb, 0xdc, 0xba, 0x0e, 0x09, 0x4a, 0x35, 0x4a},
subYX: fp.Elt{0x86, 0xb2, 0x2b, 0xd0, 0xb8, 0x4a, 0x6d, 0x66, 0x7b, 0x32, 0xdf, 0x3b, 0x1a, 0x19, 0x1f, 0x63, 0xee, 0x1f, 0x3d, 0x1c, 0x5c, 0x14, 0x60, 0x5b, 0x72, 0x49, 0x07, 0xb1, 0x0d, 0x72, 0xc6, 0x35, 0xf0, 0xbc, 0x5e, 0xda, 0x80, 0x6b, 0x64, 0x5b, 0xe5, 0x34, 0x54, 0x39, 0xdd, 0xe6, 0x3c, 0xcb, 0xe5, 0x29, 0x32, 0x06, 0xc6, 0xb1, 0x96, 0x34},
dt2: fp.Elt{0x85, 0x86, 0xf5, 0x84, 0x86, 0xe6, 0x77, 0x8a, 0x71, 0x85, 0x0c, 0x4f, 0x81, 0x5b, 0x29, 0x06, 0xb5, 0x2e, 0x26, 0x71, 0x07, 0x78, 0x07, 0xae, 0xbc, 0x95, 0x46, 0xc3, 0x65, 0xac, 0xe3, 0x76, 0x51, 0x7d, 0xd4, 0x85, 0x31, 0xe3, 0x43, 0xf3, 0x1b, 0x7c, 0xf7, 0x6b, 0x2c, 0xf8, 0x1c, 0xbb, 0x8d, 0xca, 0xab, 0x4b, 0xba, 0x7f, 0xa4, 0xe2},
},
{ /* 35P*/
addYX: fp.Elt{0x1a, 0xee, 0xe7, 0xa4, 0x8a, 0x9d, 0x53, 0x80, 0xc6, 0xb8, 0x4e, 0xdc, 0x89, 0xe0, 0xc4, 0x2b, 0x60, 0x52, 0x6f, 0xec, 0x81, 0xd2, 0x55, 0x6b, 0x1b, 0x6f, 0x17, 0x67, 0x8e, 0x42, 0x26, 0x4c, 0x65, 0x23, 0x29, 0xc6, 0x7b, 0xcd, 0x9f, 0xad, 0x4b, 0x42, 0xd3, 0x0c, 0x75, 0xc3, 0x8a, 0xf5, 0xbe, 0x9e, 0x55, 0xf7, 0x47, 0x5d, 0xbd, 0x3a},
subYX: fp.Elt{0x0d, 0xa8, 0x3b, 0xf9, 0xc7, 0x7e, 0xc6, 0x86, 0x94, 0xc0, 0x01, 0xff, 0x27, 0xce, 0x43, 0xac, 0xe5, 0xe1, 0xd2, 0x8d, 0xc1, 0x22, 0x31, 0xbe, 0xe1, 0xaf, 0xf9, 0x4a, 0x78, 0xa1, 0x0c, 0xaa, 0xd4, 0x80, 0xe4, 0x09, 0x8d, 0xfb, 0x1d, 0x52, 0xc8, 0x60, 0x2d, 0xf2, 0xa2, 0x89, 0x02, 0x56, 0x3d, 0x56, 0x27, 0x85, 0xc7, 0xf0, 0x2b, 0x9a},
dt2: fp.Elt{0x62, 0x7c, 0xc7, 0x6b, 0x2c, 0x9d, 0x0a, 0x7c, 0xe5, 0x50, 0x3c, 0xe6, 0x87, 0x1c, 0x82, 0x30, 0x67, 0x3c, 0x39, 0xb6, 0xa0, 0x31, 0xfb, 0x03, 0x7b, 0xa1, 0x58, 0xdf, 0x12, 0x76, 0x5d, 0x5d, 0x0a, 0x8f, 0x9b, 0x37, 0x32, 0xc3, 0x60, 0x33, 0xea, 0x9f, 0x0a, 0x99, 0xfa, 0x20, 0xd0, 0x33, 0x21, 0xc3, 0x94, 0xd4, 0x86, 0x49, 0x7c, 0x4e},
},
{ /* 37P*/
addYX: fp.Elt{0xc7, 0x0c, 0x71, 0xfe, 0x55, 0xd1, 0x95, 0x8f, 0x43, 0xbb, 0x6b, 0x74, 0x30, 0xbd, 0xe8, 0x6f, 0x1c, 0x1b, 0x06, 0x62, 0xf5, 0xfc, 0x65, 0xa0, 0xeb, 0x81, 0x12, 0xc9, 0x64, 0x66, 0x61, 0xde, 0xf3, 0x6d, 0xd4, 0xae, 0x8e, 0xb1, 0x72, 0xe0, 0xcd, 0x37, 0x01, 0x28, 0x52, 0xd7, 0x39, 0x46, 0x0c, 0x55, 0xcf, 0x47, 0x70, 0xef, 0xa1, 0x17},
subYX: fp.Elt{0x8d, 0x58, 0xde, 0x83, 0x88, 0x16, 0x0e, 0x12, 0x42, 0x03, 0x50, 0x60, 0x4b, 0xdf, 0xbf, 0x95, 0xcc, 0x7d, 0x18, 0x17, 0x7e, 0x31, 0x5d, 0x8a, 0x66, 0xc1, 0xcf, 0x14, 0xea, 0xf4, 0xf4, 0xe5, 0x63, 0x2d, 0x32, 0x86, 0x9b, 0xed, 0x1f, 0x4f, 0x03, 0xaf, 0x33, 0x92, 0xcb, 0xaf, 0x9c, 0x05, 0x0d, 0x47, 0x1b, 0x42, 0xba, 0x13, 0x22, 0x98},
dt2: fp.Elt{0xb5, 0x48, 0xeb, 0x7d, 0x3d, 0x10, 0x9f, 0x59, 0xde, 0xf8, 0x1c, 0x4f, 0x7d, 0x9d, 0x40, 0x4d, 0x9e, 0x13, 0x24, 0xb5, 0x21, 0x09, 0xb7, 0xee, 0x98, 0x5c, 0x56, 0xbc, 0x5e, 0x2b, 0x78, 0x38, 0x06, 0xac, 0xe3, 0xe0, 0xfa, 0x2e, 0xde, 0x4f, 0xd2, 0xb3, 0xfb, 0x2d, 0x71, 0x84, 0xd1, 0x9d, 0x12, 0x5b, 0x35, 0xc8, 0x03, 0x68, 0x67, 0xc7},
},
{ /* 39P*/
addYX: fp.Elt{0xb6, 0x65, 0xfb, 0xa7, 0x06, 0x35, 0xbb, 0xe0, 0x31, 0x8d, 0x91, 0x40, 0x98, 0xab, 0x30, 0xe4, 0xca, 0x12, 0x59, 0x89, 0xed, 0x65, 0x5d, 0x7f, 0xae, 0x69, 0xa0, 0xa4, 0xfa, 0x78, 0xb4, 0xf7, 0xed, 0xae, 0x86, 0x78, 0x79, 0x64, 0x24, 0xa6, 0xd4, 0xe1, 0xf6, 0xd3, 0xa0, 0x89, 0xba, 0x20, 0xf4, 0x54, 0x0d, 0x8f, 0xdb, 0x1a, 0x79, 0xdb},
subYX: fp.Elt{0xe1, 0x82, 0x0c, 0x4d, 0xde, 0x9f, 0x40, 0xf0, 0xc1, 0xbd, 0x8b, 0xd3, 0x24, 0x03, 0xcd, 0xf2, 0x92, 0x7d, 0xe2, 0x68, 0x7f, 0xf1, 0xbe, 0x69, 0xde, 0x34, 0x67, 0x4c, 0x85, 0x3b, 0xec, 0x98, 0xcc, 0x4d, 0x3e, 0xc0, 0x96, 0x27, 0xe6, 0x75, 0xfc, 0xdf, 0x37, 0xc0, 0x1e, 0x27, 0xe0, 0xf6, 0xc2, 0xbd, 0xbc, 0x3d, 0x9b, 0x39, 0xdc, 0xe2},
dt2: fp.Elt{0xd8, 0x29, 0xa7, 0x39, 0xe3, 0x9f, 0x2f, 0x0e, 0x4b, 0x24, 0x21, 0x70, 0xef, 0xfd, 0x91, 0xea, 0xbf, 0xe1, 0x72, 0x90, 0xcc, 0xc9, 0x84, 0x0e, 0xad, 0xd5, 0xe6, 0xbb, 0xc5, 0x99, 0x7f, 0xa4, 0xf0, 0x2e, 0xcc, 0x95, 0x64, 0x27, 0x19, 0xd8, 0x4c, 0x27, 0x0d, 0xff, 0xb6, 0x29, 0xe2, 0x6c, 0xfa, 0xbb, 0x4d, 0x9c, 0xbb, 0xaf, 0xa5, 0xec},
},
{ /* 41P*/
addYX: fp.Elt{0xd6, 0x33, 0x3f, 0x9f, 0xcf, 0xfd, 0x4c, 0xd1, 0xfe, 0xe5, 0xeb, 0x64, 0x27, 0xae, 0x7a, 0xa2, 0x82, 0x50, 0x6d, 0xaa, 0xe3, 0x5d, 0xe2, 0x48, 0x60, 0xb3, 0x76, 0x04, 0xd9, 0x19, 0xa7, 0xa1, 0x73, 0x8d, 0x38, 0xa9, 0xaf, 0x45, 0xb5, 0xb2, 0x62, 0x9b, 0xf1, 0x35, 0x7b, 0x84, 0x66, 0xeb, 0x06, 0xef, 0xf1, 0xb2, 0x2d, 0x6a, 0x61, 0x15},
subYX: fp.Elt{0x86, 0x50, 0x42, 0xf7, 0xda, 0x59, 0xb2, 0xcf, 0x0d, 0x3d, 0xee, 0x8e, 0x53, 0x5d, 0xf7, 0x9e, 0x6a, 0x26, 0x2d, 0xc7, 0x8c, 0x8e, 0x18, 0x50, 0x6d, 0xb7, 0x51, 0x4c, 0xa7, 0x52, 0x6e, 0x0e, 0x0a, 0x16, 0x74, 0xb2, 0x81, 0x8b, 0x56, 0x27, 0x22, 0x84, 0xf4, 0x56, 0xc5, 0x06, 0xe1, 0x8b, 0xca, 0x2d, 0xdb, 0x9a, 0xf6, 0x10, 0x9c, 0x51},
dt2: fp.Elt{0x1f, 0x16, 0xa2, 0x78, 0x96, 0x1b, 0x85, 0x9c, 0x76, 0x49, 0xd4, 0x0f, 0xac, 0xb0, 0xf4, 0xd0, 0x06, 0x2c, 0x7e, 0x6d, 0x6e, 0x8e, 0xc7, 0x9f, 0x18, 0xad, 0xfc, 0x88, 0x0c, 0x0c, 0x09, 0x05, 0x05, 0xa0, 0x79, 0x72, 0x32, 0x72, 0x87, 0x0f, 0x49, 0x87, 0x0c, 0xb4, 0x12, 0xc2, 0x09, 0xf8, 0x9f, 0x30, 0x72, 0xa9, 0x47, 0x13, 0x93, 0x49},
},
{ /* 43P*/
addYX: fp.Elt{0xcc, 0xb1, 0x4c, 0xd3, 0xc0, 0x9e, 0x9e, 0x4d, 0x6d, 0x28, 0x0b, 0xa5, 0x94, 0xa7, 0x2e, 0xc2, 0xc7, 0xaf, 0x29, 0x73, 0xc9, 0x68, 0xea, 0x0f, 0x34, 0x37, 0x8d, 0x96, 0x8f, 0x3a, 0x3d, 0x73, 0x1e, 0x6d, 0x9f, 0xcf, 0x8d, 0x83, 0xb5, 0x71, 0xb9, 0xe1, 0x4b, 0x67, 0x71, 0xea, 0xcf, 0x56, 0xe5, 0xeb, 0x72, 0x15, 0x2f, 0x9e, 0xa8, 0xaa},
subYX: fp.Elt{0xf4, 0x3e, 0x85, 0x1c, 0x1a, 0xef, 0x50, 0xd1, 0xb4, 0x20, 0xb2, 0x60, 0x05, 0x98, 0xfe, 0x47, 0x3b, 0xc1, 0x76, 0xca, 0x2c, 0x4e, 0x5a, 0x42, 0xa3, 0xf7, 0x20, 0xaa, 0x57, 0x39, 0xee, 0x34, 0x1f, 0xe1, 0x68, 0xd3, 0x7e, 0x06, 0xc4, 0x6c, 0xc7, 0x76, 0x2b, 0xe4, 0x1c, 0x48, 0x44, 0xe6, 0xe5, 0x44, 0x24, 0x8d, 0xb3, 0xb6, 0x88, 0x32},
dt2: fp.Elt{0x18, 0xa7, 0xba, 0xd0, 0x44, 0x6f, 0x33, 0x31, 0x00, 0xf8, 0xf6, 0x12, 0xe3, 0xc5, 0xc7, 0xb5, 0x91, 0x9c, 0x91, 0xb5, 0x75, 0x18, 0x18, 0x8a, 0xab, 0xed, 0x24, 0x11, 0x2e, 0xce, 0x5a, 0x0f, 0x94, 0x5f, 0x2e, 0xca, 0xd3, 0x80, 0xea, 0xe5, 0x34, 0x96, 0x67, 0x8b, 0x6a, 0x26, 0x5e, 0xc8, 0x9d, 0x2c, 0x5e, 0x6c, 0xa2, 0x0c, 0xbf, 0xf0},
},
{ /* 45P*/
addYX: fp.Elt{0xb3, 0xbf, 0xa3, 0x85, 0xee, 0xf6, 0x58, 0x02, 0x78, 0xc4, 0x30, 0xd6, 0x57, 0x59, 0x8c, 0x88, 0x08, 0x7c, 0xbc, 0xbe, 0x0a, 0x74, 0xa9, 0xde, 0x69, 0xe7, 0x41, 0xd8, 0xbf, 0x66, 0x8d, 0x3d, 0x28, 0x00, 0x8c, 0x47, 0x65, 0x34, 0xfe, 0x86, 0x9e, 0x6a, 0xf2, 0x41, 0x6a, 0x94, 0xc4, 0x88, 0x75, 0x23, 0x0d, 0x52, 0x69, 0xee, 0x07, 0x89},
subYX: fp.Elt{0x22, 0x3c, 0xa1, 0x70, 0x58, 0x97, 0x93, 0xbe, 0x59, 0xa8, 0x0b, 0x8a, 0x46, 0x2a, 0x38, 0x1e, 0x08, 0x6b, 0x61, 0x9f, 0xf2, 0x4a, 0x8b, 0x80, 0x68, 0x6e, 0xc8, 0x92, 0x60, 0xf3, 0xc9, 0x89, 0xb2, 0x6d, 0x63, 0xb0, 0xeb, 0x83, 0x15, 0x63, 0x0e, 0x64, 0xbb, 0xb8, 0xfe, 0xb4, 0x81, 0x90, 0x01, 0x28, 0x10, 0xb9, 0x74, 0x6e, 0xde, 0xa4},
dt2: fp.Elt{0x1a, 0x23, 0x45, 0xa8, 0x6f, 0x4e, 0xa7, 0x4a, 0x0c, 0xeb, 0xb0, 0x43, 0xf9, 0xef, 0x99, 0x60, 0x5b, 0xdb, 0x66, 0xc0, 0x86, 0x71, 0x43, 0xb1, 0x22, 0x7b, 0x1c, 0xe7, 0x8d, 0x09, 0x1d, 0x83, 0x76, 0x9c, 0xd3, 0x5a, 0xdd, 0x42, 0xd9, 0x2f, 0x2d, 0xba, 0x7a, 0xc2, 0xd9, 0x6b, 0xd4, 0x7a, 0xf1, 0xd5, 0x5f, 0x6b, 0x85, 0xbf, 0x0b, 0xf1},
},
{ /* 47P*/
addYX: fp.Elt{0xb2, 0x83, 0xfa, 0x1f, 0xd2, 0xce, 0xb6, 0xf2, 0x2d, 0xea, 0x1b, 0xe5, 0x29, 0xa5, 0x72, 0xf9, 0x25, 0x48, 0x4e, 0xf2, 0x50, 0x1b, 0x39, 0xda, 0x34, 0xc5, 0x16, 0x13, 0xb4, 0x0c, 0xa1, 0x00, 0x79, 0x7a, 0xf5, 0x8b, 0xf3, 0x70, 0x14, 0xb6, 0xfc, 0x9a, 0x47, 0x68, 0x1e, 0x42, 0x70, 0x64, 0x2a, 0x84, 0x3e, 0x3d, 0x20, 0x58, 0xf9, 0x6a},
subYX: fp.Elt{0xd9, 0xee, 0xc0, 0xc4, 0xf5, 0xc2, 0x86, 0xaf, 0x45, 0xd2, 0xd2, 0x87, 0x1b, 0x64, 0xd5, 0xe0, 0x8c, 0x44, 0x00, 0x4f, 0x43, 0x89, 0x04, 0x48, 0x4a, 0x0b, 0xca, 0x94, 0x06, 0x2f, 0x23, 0x5b, 0x6c, 0x8d, 0x44, 0x66, 0x53, 0xf5, 0x5a, 0x20, 0x72, 0x28, 0x58, 0x84, 0xcc, 0x73, 0x22, 0x5e, 0xd1, 0x0b, 0x56, 0x5e, 0x6a, 0xa3, 0x11, 0x91},
dt2: fp.Elt{0x6e, 0x9f, 0x88, 0xa8, 0x68, 0x2f, 0x12, 0x37, 0x88, 0xfc, 0x92, 0x8f, 0x24, 0xeb, 0x5b, 0x2a, 0x2a, 0xd0, 0x14, 0x40, 0x4c, 0xa9, 0xa4, 0x03, 0x0c, 0x45, 0x48, 0x13, 0xe8, 0xa6, 0x37, 0xab, 0xc0, 0x06, 0x38, 0x6c, 0x96, 0x73, 0x40, 0x6c, 0xc6, 0xea, 0x56, 0xc6, 0xe9, 0x1a, 0x69, 0xeb, 0x7a, 0xd1, 0x33, 0x69, 0x58, 0x2b, 0xea, 0x2f},
},
{ /* 49P*/
addYX: fp.Elt{0x58, 0xa8, 0x05, 0x41, 0x00, 0x9d, 0xaa, 0xd9, 0x98, 0xcf, 0xb9, 0x41, 0xb5, 0x4a, 0x8d, 0xe2, 0xe7, 0xc0, 0x72, 0xef, 0xc8, 0x28, 0x6b, 0x68, 0x9d, 0xc9, 0xdf, 0x05, 0x8b, 0xd0, 0x04, 0x74, 0x79, 0x45, 0x52, 0x05, 0xa3, 0x6e, 0x35, 0x3a, 0xe3, 0xef, 0xb2, 0xdc, 0x08, 0x6f, 0x4e, 0x76, 0x85, 0x67, 0xba, 0x23, 0x8f, 0xdd, 0xaf, 0x09},
subYX: fp.Elt{0xb4, 0x38, 0xc8, 0xff, 0x4f, 0x65, 0x2a, 0x7e, 0xad, 0xb1, 0xc6, 0xb9, 0x3d, 0xd6, 0xf7, 0x14, 0xcf, 0xf6, 0x98, 0x75, 0xbb, 0x47, 0x83, 0x90, 0xe7, 0xe1, 0xf6, 0x14, 0x99, 0x7e, 0xfa, 0xe4, 0x77, 0x24, 0xe3, 0xe7, 0xf0, 0x1e, 0xdb, 0x27, 0x4e, 0x16, 0x04, 0xf2, 0x08, 0x52, 0xfc, 0xec, 0x55, 0xdb, 0x2e, 0x67, 0xe1, 0x94, 0x32, 0x89},
dt2: fp.Elt{0x00, 0xad, 0x03, 0x35, 0x1a, 0xb1, 0x88, 0xf0, 0xc9, 0x11, 0xe4, 0x12, 0x52, 0x61, 0xfd, 0x8a, 0x1b, 0x6a, 0x0a, 0x4c, 0x42, 0x46, 0x22, 0x0e, 0xa5, 0xf9, 0xe2, 0x50, 0xf2, 0xb2, 0x1f, 0x20, 0x78, 0x10, 0xf6, 0xbf, 0x7f, 0x0c, 0x9c, 0xad, 0x40, 0x8b, 0x82, 0xd4, 0xba, 0x69, 0x09, 0xac, 0x4b, 0x6d, 0xc4, 0x49, 0x17, 0x81, 0x57, 0x3b},
},
{ /* 51P*/
addYX: fp.Elt{0x0d, 0xfe, 0xb4, 0x35, 0x11, 0xbd, 0x1d, 0x6b, 0xc2, 0xc5, 0x3b, 0xd2, 0x23, 0x2c, 0x72, 0xe3, 0x48, 0xb1, 0x48, 0x73, 0xfb, 0xa3, 0x21, 0x6e, 0xc0, 0x09, 0x69, 0xac, 0xe1, 0x60, 0xbc, 0x24, 0x03, 0x99, 0x63, 0x0a, 0x00, 0xf0, 0x75, 0xf6, 0x92, 0xc5, 0xd6, 0xdb, 0x51, 0xd4, 0x7d, 0xe6, 0xf4, 0x11, 0x79, 0xd7, 0xc3, 0xaf, 0x48, 0xd0},
subYX: fp.Elt{0xf4, 0x4f, 0xaf, 0x31, 0xe3, 0x10, 0x89, 0x95, 0xf0, 0x8a, 0xf6, 0x31, 0x9f, 0x48, 0x02, 0xba, 0x42, 0x2b, 0x3c, 0x22, 0x8b, 0xcc, 0x12, 0x98, 0x6e, 0x7a, 0x64, 0x3a, 0xc4, 0xca, 0x32, 0x2a, 0x72, 0xf8, 0x2c, 0xcf, 0x78, 0x5e, 0x7a, 0x75, 0x6e, 0x72, 0x46, 0x48, 0x62, 0x28, 0xac, 0x58, 0x1a, 0xc6, 0x59, 0x88, 0x2a, 0x44, 0x9e, 0x83},
dt2: fp.Elt{0xb3, 0xde, 0x36, 0xfd, 0xeb, 0x1b, 0xd4, 0x24, 0x1b, 0x08, 0x8c, 0xfe, 0xa9, 0x41, 0xa1, 0x64, 0xf2, 0x6d, 0xdb, 0xf9, 0x94, 0xae, 0x86, 0x71, 0xab, 0x10, 0xbf, 0xa3, 0xb2, 0xa0, 0xdf, 0x10, 0x8c, 0x74, 0xce, 0xb3, 0xfc, 0xdb, 0xba, 0x15, 0xf6, 0x91, 0x7a, 0x9c, 0x36, 0x1e, 0x45, 0x07, 0x3c, 0xec, 0x1a, 0x61, 0x26, 0x93, 0xe3, 0x50},
},
{ /* 53P*/
addYX: fp.Elt{0xc5, 0x50, 0xc5, 0x83, 0xb0, 0xbd, 0xd9, 0xf6, 0x6d, 0x15, 0x5e, 0xc1, 0x1a, 0x33, 0xa0, 0xce, 0x13, 0x70, 0x3b, 0xe1, 0x31, 0xc6, 0xc4, 0x02, 0xec, 0x8c, 0xd5, 0x9c, 0x97, 0xd3, 0x12, 0xc4, 0xa2, 0xf9, 0xd5, 0xfb, 0x22, 0x69, 0x94, 0x09, 0x2f, 0x59, 0xce, 0xdb, 0xf2, 0xf2, 0x00, 0xe0, 0xa9, 0x08, 0x44, 0x2e, 0x8b, 0x6b, 0xf5, 0xb3},
subYX: fp.Elt{0x90, 0xdd, 0xec, 0xa2, 0x65, 0xb7, 0x61, 0xbc, 0xaa, 0x70, 0xa2, 0x15, 0xd8, 0xb0, 0xf8, 0x8e, 0x23, 0x3d, 0x9f, 0x46, 0xa3, 0x29, 0x20, 0xd1, 0xa1, 0x15, 0x81, 0xc6, 0xb6, 0xde, 0xbe, 0x60, 0x63, 0x24, 0xac, 0x15, 0xfb, 0xeb, 0xd3, 0xea, 0x57, 0x13, 0x86, 0x38, 0x1e, 0x22, 0xf4, 0x8c, 0x5d, 0xaf, 0x1b, 0x27, 0x21, 0x4f, 0xa3, 0x63},
dt2: fp.Elt{0x07, 0x15, 0x87, 0xc4, 0xfd, 0xa1, 0x97, 0x7a, 0x07, 0x1f, 0x56, 0xcc, 0xe3, 0x6a, 0x01, 0x90, 0xce, 0xf9, 0xfa, 0x50, 0xb2, 0xe0, 0x87, 0x8b, 0x6c, 0x63, 0x6c, 0xf6, 0x2a, 0x09, 0xef, 0xef, 0xd2, 0x31, 0x40, 0x25, 0xf6, 0x84, 0xcb, 0xe0, 0xc4, 0x23, 0xc1, 0xcb, 0xe2, 0x02, 0x83, 0x2d, 0xed, 0x74, 0x74, 0x8b, 0xf8, 0x7c, 0x81, 0x18},
},
{ /* 55P*/
addYX: fp.Elt{0x9e, 0xe5, 0x59, 0x95, 0x63, 0x2e, 0xac, 0x8b, 0x03, 0x3c, 0xc1, 0x8e, 0xe1, 0x5b, 0x56, 0x3c, 0x16, 0x41, 0xe4, 0xc2, 0x60, 0x0c, 0x6d, 0x65, 0x9f, 0xfc, 0x27, 0x68, 0x43, 0x44, 0x05, 0x12, 0x6c, 0xda, 0x04, 0xef, 0xcf, 0xcf, 0xdc, 0x0a, 0x1a, 0x7f, 0x12, 0xd3, 0xeb, 0x02, 0xb6, 0x04, 0xca, 0xd6, 0xcb, 0xf0, 0x22, 0xba, 0x35, 0x6d},
subYX: fp.Elt{0x09, 0x6d, 0xf9, 0x64, 0x4c, 0xe6, 0x41, 0xff, 0x01, 0x4d, 0xce, 0x1e, 0xfa, 0x38, 0xa2, 0x25, 0x62, 0xff, 0x03, 0x39, 0x18, 0x91, 0xbb, 0x9d, 0xce, 0x02, 0xf0, 0xf1, 0x3c, 0x55, 0x18, 0xa9, 0xab, 0x4d, 0xd2, 0x35, 0xfd, 0x8d, 0xa9, 0xb2, 0xad, 0xb7, 0x06, 0x6e, 0xc6, 0x69, 0x49, 0xd6, 0x98, 0x98, 0x0b, 0x22, 0x81, 0x6b, 0xbd, 0xa0},
dt2: fp.Elt{0x22, 0xf4, 0x85, 0x5d, 0x2b, 0xf1, 0x55, 0xa5, 0xd6, 0x27, 0x86, 0x57, 0x12, 0x1f, 0x16, 0x0a, 0x5a, 0x9b, 0xf2, 0x38, 0xb6, 0x28, 0xd8, 0x99, 0x0c, 0x89, 0x1d, 0x7f, 0xca, 0x21, 0x17, 0x1a, 0x0b, 0x02, 0x5f, 0x77, 0x2f, 0x73, 0x30, 0x7c, 0xc8, 0xd7, 0x2b, 0xcc, 0xe7, 0xf3, 0x21, 0xac, 0x53, 0xa7, 0x11, 0x5d, 0xd8, 0x1d, 0x9b, 0xf5},
},
{ /* 57P*/
addYX: fp.Elt{0x94, 0x63, 0x5d, 0xef, 0xfd, 0x6d, 0x25, 0x4e, 0x6d, 0x29, 0x03, 0xed, 0x24, 0x28, 0x27, 0x57, 0x47, 0x3e, 0x6a, 0x1a, 0xfe, 0x37, 0xee, 0x5f, 0x83, 0x29, 0x14, 0xfd, 0x78, 0x25, 0x8a, 0xe1, 0x02, 0x38, 0xd8, 0xca, 0x65, 0x55, 0x40, 0x7d, 0x48, 0x2c, 0x7c, 0x7e, 0x60, 0xb6, 0x0c, 0x6d, 0xf7, 0xe8, 0xb3, 0x62, 0x53, 0xd6, 0x9c, 0x2b},
subYX: fp.Elt{0x47, 0x25, 0x70, 0x62, 0xf5, 0x65, 0x93, 0x62, 0x08, 0xac, 0x59, 0x66, 0xdb, 0x08, 0xd9, 0x1a, 0x19, 0xaf, 0xf4, 0xef, 0x02, 0xa2, 0x78, 0xa9, 0x55, 0x1c, 0xfa, 0x08, 0x11, 0xcb, 0xa3, 0x71, 0x74, 0xb1, 0x62, 0xe7, 0xc7, 0xf3, 0x5a, 0xb5, 0x8b, 0xd4, 0xf6, 0x10, 0x57, 0x79, 0x72, 0x2f, 0x13, 0x86, 0x7b, 0x44, 0x5f, 0x48, 0xfd, 0x88},
dt2: fp.Elt{0x10, 0x02, 0xcd, 0x05, 0x9a, 0xc3, 0x32, 0x6d, 0x10, 0x3a, 0x74, 0xba, 0x06, 0xc4, 0x3b, 0x34, 0xbc, 0x36, 0xed, 0xa3, 0xba, 0x9a, 0xdb, 0x6d, 0xd4, 0x69, 0x99, 0x97, 0xd0, 0xe4, 0xdd, 0xf5, 0xd4, 0x7c, 0xd3, 0x4e, 0xab, 0xd1, 0x3b, 0xbb, 0xe9, 0xc7, 0x6a, 0x94, 0x25, 0x61, 0xf0, 0x06, 0xc5, 0x12, 0xa8, 0x86, 0xe5, 0x35, 0x46, 0xeb},
},
{ /* 59P*/
addYX: fp.Elt{0x9e, 0x95, 0x11, 0xc6, 0xc7, 0xe8, 0xee, 0x5a, 0x26, 0xa0, 0x72, 0x72, 0x59, 0x91, 0x59, 0x16, 0x49, 0x99, 0x7e, 0xbb, 0xd7, 0x15, 0xb4, 0xf2, 0x40, 0xf9, 0x5a, 0x4d, 0xc8, 0xa0, 0xe2, 0x34, 0x7b, 0x34, 0xf3, 0x99, 0xbf, 0xa9, 0xf3, 0x79, 0xc1, 0x1a, 0x0c, 0xf4, 0x86, 0x74, 0x4e, 0xcb, 0xbc, 0x90, 0xad, 0xb6, 0x51, 0x6d, 0xaa, 0x33},
subYX: fp.Elt{0x9f, 0xd1, 0xc5, 0xa2, 0x6c, 0x24, 0x88, 0x15, 0x71, 0x68, 0xf6, 0x07, 0x45, 0x02, 0xc4, 0x73, 0x7e, 0x75, 0x87, 0xca, 0x7c, 0xf0, 0x92, 0x00, 0x75, 0xd6, 0x5a, 0xdd, 0xe0, 0x64, 0x16, 0x9d, 0x62, 0x80, 0x33, 0x9f, 0xf4, 0x8e, 0x1a, 0x15, 0x1c, 0xd3, 0x0f, 0x4d, 0x4f, 0x62, 0x2d, 0xd7, 0xa5, 0x77, 0xe3, 0xea, 0xf0, 0xfb, 0x1a, 0xdb},
dt2: fp.Elt{0x6a, 0xa2, 0xb1, 0xaa, 0xfb, 0x5a, 0x32, 0x4e, 0xff, 0x47, 0x06, 0xd5, 0x9a, 0x4f, 0xce, 0x83, 0x5b, 0x82, 0x34, 0x3e, 0x47, 0xb8, 0xf8, 0xe9, 0x7c, 0x67, 0x69, 0x8d, 0x9c, 0xb7, 0xde, 0x57, 0xf4, 0x88, 0x41, 0x56, 0x0c, 0x87, 0x1e, 0xc9, 0x2f, 0x54, 0xbf, 0x5c, 0x68, 0x2c, 0xd9, 0xc4, 0xef, 0x53, 0x73, 0x1e, 0xa6, 0x38, 0x02, 0x10},
},
{ /* 61P*/
addYX: fp.Elt{0x08, 0x80, 0x4a, 0xc9, 0xb7, 0xa8, 0x88, 0xd9, 0xfc, 0x6a, 0xc0, 0x3e, 0xc2, 0x33, 0x4d, 0x2b, 0x2a, 0xa3, 0x6d, 0x72, 0x3e, 0xdc, 0x34, 0x68, 0x08, 0xbf, 0x27, 0xef, 0xf4, 0xff, 0xe2, 0x0c, 0x31, 0x0c, 0xa2, 0x0a, 0x1f, 0x65, 0xc1, 0x4c, 0x61, 0xd3, 0x1b, 0xbc, 0x25, 0xb1, 0xd0, 0xd4, 0x89, 0xb2, 0x53, 0xfb, 0x43, 0xa5, 0xaf, 0x04},
subYX: fp.Elt{0xe3, 0xe1, 0x37, 0xad, 0x58, 0xa9, 0x55, 0x81, 0xee, 0x64, 0x21, 0xb9, 0xf5, 0x4c, 0x35, 0xea, 0x4a, 0xd3, 0x26, 0xaa, 0x90, 0xd4, 0x60, 0x46, 0x09, 0x4b, 0x4a, 0x62, 0xf9, 0xcd, 0xe1, 0xee, 0xbb, 0xc2, 0x09, 0x0b, 0xb0, 0x96, 0x8e, 0x43, 0x77, 0xaf, 0x25, 0x20, 0x5e, 0x47, 0xe4, 0x1d, 0x50, 0x69, 0x74, 0x08, 0xd7, 0xb9, 0x90, 0x13},
dt2: fp.Elt{0x51, 0x91, 0x95, 0x64, 0x03, 0x16, 0xfd, 0x6e, 0x26, 0x94, 0x6b, 0x61, 0xe7, 0xd9, 0xe0, 0x4a, 0x6d, 0x7c, 0xfa, 0xc0, 0xe2, 0x43, 0x23, 0x53, 0x70, 0xf5, 0x6f, 0x73, 0x8b, 0x81, 0xb0, 0x0c, 0xee, 0x2e, 0x46, 0xf2, 0x8d, 0xa6, 0xfb, 0xb5, 0x1c, 0x33, 0xbf, 0x90, 0x59, 0xc9, 0x7c, 0xb8, 0x6f, 0xad, 0x75, 0x02, 0x90, 0x8e, 0x59, 0x75},
},
{ /* 63P*/
addYX: fp.Elt{0x36, 0x4d, 0x77, 0x04, 0xb8, 0x7d, 0x4a, 0xd1, 0xc5, 0xbb, 0x7b, 0x50, 0x5f, 0x8d, 0x9d, 0x62, 0x0f, 0x66, 0x71, 0xec, 0x87, 0xc5, 0x80, 0x82, 0xc8, 0xf4, 0x6a, 0x94, 0x92, 0x5b, 0xb0, 0x16, 0x9b, 0xb2, 0xc9, 0x6f, 0x2b, 0x2d, 0xee, 0x95, 0x73, 0x2e, 0xc2, 0x1b, 0xc5, 0x55, 0x36, 0x86, 0x24, 0xf8, 0x20, 0x05, 0x0d, 0x93, 0xd7, 0x76},
subYX: fp.Elt{0x7f, 0x01, 0xeb, 0x2e, 0x48, 0x4d, 0x1d, 0xf1, 0x06, 0x7e, 0x7c, 0x2a, 0x43, 0xbf, 0x28, 0xac, 0xe9, 0x58, 0x13, 0xc8, 0xbf, 0x8e, 0xc0, 0xef, 0xe8, 0x4f, 0x46, 0x8a, 0xe7, 0xc0, 0xf6, 0x0f, 0x0a, 0x03, 0x48, 0x91, 0x55, 0x39, 0x2a, 0xe3, 0xdc, 0xf6, 0x22, 0x9d, 0x4d, 0x71, 0x55, 0x68, 0x25, 0x6e, 0x95, 0x52, 0xee, 0x4c, 0xd9, 0x01},
dt2: fp.Elt{0xac, 0x33, 0x3f, 0x7c, 0x27, 0x35, 0x15, 0x91, 0x33, 0x8d, 0xf9, 0xc4, 0xf4, 0xf3, 0x90, 0x09, 0x75, 0x69, 0x62, 0x9f, 0x61, 0x35, 0x83, 0x92, 0x04, 0xef, 0x96, 0x38, 0x80, 0x9e, 0x88, 0xb3, 0x67, 0x95, 0xbe, 0x79, 0x3c, 0x35, 0xd8, 0xdc, 0xb2, 0x3e, 0x2d, 0xe6, 0x46, 0xbe, 0x81, 0xf3, 0x32, 0x0e, 0x37, 0x23, 0x75, 0x2a, 0x3d, 0xa0},
},
}
================================================
FILE: vendor/github.com/cloudflare/circl/ecc/goldilocks/twist_basemult.go
================================================
package goldilocks
import (
"crypto/subtle"
mlsb "github.com/cloudflare/circl/math/mlsbset"
)
const (
// MLSBRecoding parameters
fxT = 448
fxV = 2
fxW = 3
fx2w1 = 1 << (uint(fxW) - 1)
)
// ScalarBaseMult returns kG where G is the generator point.
func (e twistCurve) ScalarBaseMult(k *Scalar) *twistPoint {
m, err := mlsb.New(fxT, fxV, fxW)
if err != nil {
panic(err)
}
if m.IsExtended() {
panic("not extended")
}
var isZero int
if k.IsZero() {
isZero = 1
}
subtle.ConstantTimeCopy(isZero, k[:], order[:])
minusK := *k
isEven := 1 - int(k[0]&0x1)
minusK.Neg()
subtle.ConstantTimeCopy(isEven, k[:], minusK[:])
c, err := m.Encode(k[:])
if err != nil {
panic(err)
}
gP := c.Exp(groupMLSB{})
P := gP.(*twistPoint)
P.cneg(uint(isEven))
return P
}
type groupMLSB struct{}
func (e groupMLSB) ExtendedEltP() mlsb.EltP { return nil }
func (e groupMLSB) Sqr(x mlsb.EltG) { x.(*twistPoint).Double() }
func (e groupMLSB) Mul(x mlsb.EltG, y mlsb.EltP) { x.(*twistPoint).mixAddZ1(y.(*preTwistPointAffine)) }
func (e groupMLSB) Identity() mlsb.EltG { return twistCurve{}.Identity() }
func (e groupMLSB) NewEltP() mlsb.EltP { return &preTwistPointAffine{} }
func (e groupMLSB) Lookup(a mlsb.EltP, v uint, s, u int32) {
Tabj := &tabFixMult[v]
P := a.(*preTwistPointAffine)
for k := range Tabj {
P.cmov(&Tabj[k], uint(subtle.ConstantTimeEq(int32(k), u)))
}
P.cneg(int(s >> 31))
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/conv/conv.go
================================================
package conv
import (
"encoding/binary"
"fmt"
"math/big"
"strings"
)
// BytesLe2Hex returns an hexadecimal string of a number stored in a
// little-endian order slice x.
func BytesLe2Hex(x []byte) string {
b := &strings.Builder{}
b.Grow(2*len(x) + 2)
fmt.Fprint(b, "0x")
if len(x) == 0 {
fmt.Fprint(b, "00")
}
for i := len(x) - 1; i >= 0; i-- {
fmt.Fprintf(b, "%02x", x[i])
}
return b.String()
}
// BytesLe2BigInt converts a little-endian slice x into a big-endian
// math/big.Int.
func BytesLe2BigInt(x []byte) *big.Int {
n := len(x)
b := new(big.Int)
if len(x) > 0 {
y := make([]byte, n)
for i := 0; i < n; i++ {
y[n-1-i] = x[i]
}
b.SetBytes(y)
}
return b
}
// BytesBe2Uint64Le converts a big-endian slice x to a little-endian slice of uint64.
func BytesBe2Uint64Le(x []byte) []uint64 {
l := len(x)
z := make([]uint64, (l+7)/8)
blocks := l / 8
for i := 0; i < blocks; i++ {
z[i] = binary.BigEndian.Uint64(x[l-8*(i+1):])
}
remBytes := l % 8
for i := 0; i < remBytes; i++ {
z[blocks] |= uint64(x[l-1-8*blocks-i]) << uint(8*i)
}
return z
}
// BigInt2BytesLe stores a positive big.Int number x into a little-endian slice z.
// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros).
// If x does not fit in the slice or is negative, z is not modified.
func BigInt2BytesLe(z []byte, x *big.Int) {
xLen := (x.BitLen() + 7) >> 3
zLen := len(z)
if zLen >= xLen && x.Sign() >= 0 {
y := x.Bytes()
for i := 0; i < xLen; i++ {
z[i] = y[xLen-1-i]
}
for i := xLen; i < zLen; i++ {
z[i] = 0
}
}
}
// Uint64Le2BigInt converts a little-endian slice x into a big number.
func Uint64Le2BigInt(x []uint64) *big.Int {
n := len(x)
b := new(big.Int)
var bi big.Int
for i := n - 1; i >= 0; i-- {
bi.SetUint64(x[i])
b.Lsh(b, 64)
b.Add(b, &bi)
}
return b
}
// Uint64Le2BytesLe converts a little-endian slice x to a little-endian slice of bytes.
func Uint64Le2BytesLe(x []uint64) []byte {
b := make([]byte, 8*len(x))
n := len(x)
for i := 0; i < n; i++ {
binary.LittleEndian.PutUint64(b[i*8:], x[i])
}
return b
}
// Uint64Le2BytesBe converts a little-endian slice x to a big-endian slice of bytes.
func Uint64Le2BytesBe(x []uint64) []byte {
b := make([]byte, 8*len(x))
n := len(x)
for i := 0; i < n; i++ {
binary.BigEndian.PutUint64(b[i*8:], x[n-1-i])
}
return b
}
// Uint64Le2Hex returns an hexadecimal string of a number stored in a
// little-endian order slice x.
func Uint64Le2Hex(x []uint64) string {
b := new(strings.Builder)
b.Grow(16*len(x) + 2)
fmt.Fprint(b, "0x")
if len(x) == 0 {
fmt.Fprint(b, "00")
}
for i := len(x) - 1; i >= 0; i-- {
fmt.Fprintf(b, "%016x", x[i])
}
return b.String()
}
// BigInt2Uint64Le stores a positive big.Int number x into a little-endian slice z.
// The slice is modified if the bitlength of x <= 8*len(z) (padding with zeros).
// If x does not fit in the slice or is negative, z is not modified.
func BigInt2Uint64Le(z []uint64, x *big.Int) {
xLen := (x.BitLen() + 63) >> 6 // number of 64-bit words
zLen := len(z)
if zLen >= xLen && x.Sign() > 0 {
var y, yi big.Int
y.Set(x)
two64 := big.NewInt(1)
two64.Lsh(two64, 64).Sub(two64, big.NewInt(1))
for i := 0; i < xLen; i++ {
yi.And(&y, two64)
z[i] = yi.Uint64()
y.Rsh(&y, 64)
}
}
for i := xLen; i < zLen; i++ {
z[i] = 0
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/doc.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package sha3 implements the SHA-3 fixed-output-length hash functions and
// the SHAKE variable-output-length hash functions defined by FIPS-202.
//
// Both types of hash function use the "sponge" construction and the Keccak
// permutation. For a detailed specification see http://keccak.noekeon.org/
//
// # Guidance
//
// If you aren't sure what function you need, use SHAKE256 with at least 64
// bytes of output. The SHAKE instances are faster than the SHA3 instances;
// the latter have to allocate memory to conform to the hash.Hash interface.
//
// If you need a secret-key MAC (message authentication code), prepend the
// secret key to the input, hash with SHAKE256 and read at least 32 bytes of
// output.
//
// # Security strengths
//
// The SHA3-x (x equals 224, 256, 384, or 512) functions have a security
// strength against preimage attacks of x bits. Since they only produce "x"
// bits of output, their collision-resistance is only "x/2" bits.
//
// The SHAKE-256 and -128 functions have a generic security strength of 256 and
// 128 bits against all attacks, provided that at least 2x bits of their output
// is used. Requesting more than 64 or 32 bytes of output, respectively, does
// not increase the collision-resistance of the SHAKE functions.
//
// # The sponge construction
//
// A sponge builds a pseudo-random function from a public pseudo-random
// permutation, by applying the permutation to a state of "rate + capacity"
// bytes, but hiding "capacity" of the bytes.
//
// A sponge starts out with a zero state. To hash an input using a sponge, up
// to "rate" bytes of the input are XORed into the sponge's state. The sponge
// is then "full" and the permutation is applied to "empty" it. This process is
// repeated until all the input has been "absorbed". The input is then padded.
// The digest is "squeezed" from the sponge in the same way, except that output
// is copied out instead of input being XORed in.
//
// A sponge is parameterized by its generic security strength, which is equal
// to half its capacity; capacity + rate is equal to the permutation's width.
// Since the KeccakF-1600 permutation is 1600 bits (200 bytes) wide, this means
// that the security strength of a sponge instance is equal to (1600 - bitrate) / 2.
//
// # Recommendations
//
// The SHAKE functions are recommended for most new uses. They can produce
// output of arbitrary length. SHAKE256, with an output length of at least
// 64 bytes, provides 256-bit security against all attacks. The Keccak team
// recommends it for most applications upgrading from SHA2-512. (NIST chose a
// much stronger, but much slower, sponge instance for SHA3-512.)
//
// The SHA-3 functions are "drop-in" replacements for the SHA-2 functions.
// They produce output of the same length, with the same security strengths
// against all attacks. This means, in particular, that SHA3-256 only has
// 128-bit collision resistance, because its output length is 32 bytes.
package sha3
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/hashes.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sha3
// This file provides functions for creating instances of the SHA-3
// and SHAKE hash functions, as well as utility functions for hashing
// bytes.
// New224 creates a new SHA3-224 hash.
// Its generic security strength is 224 bits against preimage attacks,
// and 112 bits against collision attacks.
func New224() State {
return State{rate: 144, outputLen: 28, dsbyte: 0x06}
}
// New256 creates a new SHA3-256 hash.
// Its generic security strength is 256 bits against preimage attacks,
// and 128 bits against collision attacks.
func New256() State {
return State{rate: 136, outputLen: 32, dsbyte: 0x06}
}
// New384 creates a new SHA3-384 hash.
// Its generic security strength is 384 bits against preimage attacks,
// and 192 bits against collision attacks.
func New384() State {
return State{rate: 104, outputLen: 48, dsbyte: 0x06}
}
// New512 creates a new SHA3-512 hash.
// Its generic security strength is 512 bits against preimage attacks,
// and 256 bits against collision attacks.
func New512() State {
return State{rate: 72, outputLen: 64, dsbyte: 0x06}
}
// Sum224 returns the SHA3-224 digest of the data.
func Sum224(data []byte) (digest [28]byte) {
h := New224()
_, _ = h.Write(data)
h.Sum(digest[:0])
return
}
// Sum256 returns the SHA3-256 digest of the data.
func Sum256(data []byte) (digest [32]byte) {
h := New256()
_, _ = h.Write(data)
h.Sum(digest[:0])
return
}
// Sum384 returns the SHA3-384 digest of the data.
func Sum384(data []byte) (digest [48]byte) {
h := New384()
_, _ = h.Write(data)
h.Sum(digest[:0])
return
}
// Sum512 returns the SHA3-512 digest of the data.
func Sum512(data []byte) (digest [64]byte) {
h := New512()
_, _ = h.Write(data)
h.Sum(digest[:0])
return
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/keccakf.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sha3
// KeccakF1600 applies the Keccak permutation to a 1600b-wide
// state represented as a slice of 25 uint64s.
// If turbo is true, applies the 12-round variant instead of the
// regular 24-round variant.
// nolint:funlen
func KeccakF1600(a *[25]uint64, turbo bool) {
// Implementation translated from Keccak-inplace.c
// in the keccak reference code.
var t, bc0, bc1, bc2, bc3, bc4, d0, d1, d2, d3, d4 uint64
i := 0
if turbo {
i = 12
}
for ; i < 24; i += 4 {
// Combines the 5 steps in each round into 2 steps.
// Unrolls 4 rounds per loop and spreads some steps across rounds.
// Round 1
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[6] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[12] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[18] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[24] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i]
a[6] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[16] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[22] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[3] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[10] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[1] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[7] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[19] ^ d4
bc3 = t<<8 | t>>(64-8)
a[20] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[11] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[23] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[4] ^ d4
bc0 = t<<27 | t>>(64-27)
a[5] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[2] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[8] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[14] ^ d4
bc2 = t<<39 | t>>(64-39)
a[15] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
// Round 2
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[16] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[7] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[23] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[14] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+1]
a[16] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[11] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[2] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[18] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[20] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[6] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[22] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[4] ^ d4
bc3 = t<<8 | t>>(64-8)
a[15] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[1] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[8] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[24] ^ d4
bc0 = t<<27 | t>>(64-27)
a[10] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[12] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[3] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[19] ^ d4
bc2 = t<<39 | t>>(64-39)
a[5] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
// Round 3
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[11] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[22] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[8] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[19] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+2]
a[11] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[1] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[12] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[23] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[15] = bc0 ^ (bc2 &^ bc1)
a[1] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[16] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[2] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[24] ^ d4
bc3 = t<<8 | t>>(64-8)
a[5] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[6] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[3] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[14] ^ d4
bc0 = t<<27 | t>>(64-27)
a[20] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[7] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[18] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[4] ^ d4
bc2 = t<<39 | t>>(64-39)
a[10] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
// Round 4
bc0 = a[0] ^ a[5] ^ a[10] ^ a[15] ^ a[20]
bc1 = a[1] ^ a[6] ^ a[11] ^ a[16] ^ a[21]
bc2 = a[2] ^ a[7] ^ a[12] ^ a[17] ^ a[22]
bc3 = a[3] ^ a[8] ^ a[13] ^ a[18] ^ a[23]
bc4 = a[4] ^ a[9] ^ a[14] ^ a[19] ^ a[24]
d0 = bc4 ^ (bc1<<1 | bc1>>63)
d1 = bc0 ^ (bc2<<1 | bc2>>63)
d2 = bc1 ^ (bc3<<1 | bc3>>63)
d3 = bc2 ^ (bc4<<1 | bc4>>63)
d4 = bc3 ^ (bc0<<1 | bc0>>63)
bc0 = a[0] ^ d0
t = a[1] ^ d1
bc1 = t<<44 | t>>(64-44)
t = a[2] ^ d2
bc2 = t<<43 | t>>(64-43)
t = a[3] ^ d3
bc3 = t<<21 | t>>(64-21)
t = a[4] ^ d4
bc4 = t<<14 | t>>(64-14)
a[0] = bc0 ^ (bc2 &^ bc1) ^ RC[i+3]
a[1] = bc1 ^ (bc3 &^ bc2)
a[2] = bc2 ^ (bc4 &^ bc3)
a[3] = bc3 ^ (bc0 &^ bc4)
a[4] = bc4 ^ (bc1 &^ bc0)
t = a[5] ^ d0
bc2 = t<<3 | t>>(64-3)
t = a[6] ^ d1
bc3 = t<<45 | t>>(64-45)
t = a[7] ^ d2
bc4 = t<<61 | t>>(64-61)
t = a[8] ^ d3
bc0 = t<<28 | t>>(64-28)
t = a[9] ^ d4
bc1 = t<<20 | t>>(64-20)
a[5] = bc0 ^ (bc2 &^ bc1)
a[6] = bc1 ^ (bc3 &^ bc2)
a[7] = bc2 ^ (bc4 &^ bc3)
a[8] = bc3 ^ (bc0 &^ bc4)
a[9] = bc4 ^ (bc1 &^ bc0)
t = a[10] ^ d0
bc4 = t<<18 | t>>(64-18)
t = a[11] ^ d1
bc0 = t<<1 | t>>(64-1)
t = a[12] ^ d2
bc1 = t<<6 | t>>(64-6)
t = a[13] ^ d3
bc2 = t<<25 | t>>(64-25)
t = a[14] ^ d4
bc3 = t<<8 | t>>(64-8)
a[10] = bc0 ^ (bc2 &^ bc1)
a[11] = bc1 ^ (bc3 &^ bc2)
a[12] = bc2 ^ (bc4 &^ bc3)
a[13] = bc3 ^ (bc0 &^ bc4)
a[14] = bc4 ^ (bc1 &^ bc0)
t = a[15] ^ d0
bc1 = t<<36 | t>>(64-36)
t = a[16] ^ d1
bc2 = t<<10 | t>>(64-10)
t = a[17] ^ d2
bc3 = t<<15 | t>>(64-15)
t = a[18] ^ d3
bc4 = t<<56 | t>>(64-56)
t = a[19] ^ d4
bc0 = t<<27 | t>>(64-27)
a[15] = bc0 ^ (bc2 &^ bc1)
a[16] = bc1 ^ (bc3 &^ bc2)
a[17] = bc2 ^ (bc4 &^ bc3)
a[18] = bc3 ^ (bc0 &^ bc4)
a[19] = bc4 ^ (bc1 &^ bc0)
t = a[20] ^ d0
bc3 = t<<41 | t>>(64-41)
t = a[21] ^ d1
bc4 = t<<2 | t>>(64-2)
t = a[22] ^ d2
bc0 = t<<62 | t>>(64-62)
t = a[23] ^ d3
bc1 = t<<55 | t>>(64-55)
t = a[24] ^ d4
bc2 = t<<39 | t>>(64-39)
a[20] = bc0 ^ (bc2 &^ bc1)
a[21] = bc1 ^ (bc3 &^ bc2)
a[22] = bc2 ^ (bc4 &^ bc3)
a[23] = bc3 ^ (bc0 &^ bc4)
a[24] = bc4 ^ (bc1 &^ bc0)
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/rc.go
================================================
package sha3
// RC stores the round constants for use in the ι step.
var RC = [24]uint64{
0x0000000000000001,
0x0000000000008082,
0x800000000000808A,
0x8000000080008000,
0x000000000000808B,
0x0000000080000001,
0x8000000080008081,
0x8000000000008009,
0x000000000000008A,
0x0000000000000088,
0x0000000080008009,
0x000000008000000A,
0x000000008000808B,
0x800000000000008B,
0x8000000000008089,
0x8000000000008003,
0x8000000000008002,
0x8000000000000080,
0x000000000000800A,
0x800000008000000A,
0x8000000080008081,
0x8000000000008080,
0x0000000080000001,
0x8000000080008008,
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/sha3.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sha3
// spongeDirection indicates the direction bytes are flowing through the sponge.
type spongeDirection int
const (
// spongeAbsorbing indicates that the sponge is absorbing input.
spongeAbsorbing spongeDirection = iota
// spongeSqueezing indicates that the sponge is being squeezed.
spongeSqueezing
)
const (
// maxRate is the maximum size of the internal buffer. SHAKE-256
// currently needs the largest buffer.
maxRate = 168
)
func (d *State) buf() []byte {
return d.storage.asBytes()[d.bufo:d.bufe]
}
type State struct {
// Generic sponge components.
a [25]uint64 // main state of the hash
rate int // the number of bytes of state to use
bufo int // offset of buffer in storage
bufe int // end of buffer in storage
// dsbyte contains the "domain separation" bits and the first bit of
// the padding. Sections 6.1 and 6.2 of [1] separate the outputs of the
// SHA-3 and SHAKE functions by appending bitstrings to the message.
// Using a little-endian bit-ordering convention, these are "01" for SHA-3
// and "1111" for SHAKE, or 00000010b and 00001111b, respectively. Then the
// padding rule from section 5.1 is applied to pad the message to a multiple
// of the rate, which involves adding a "1" bit, zero or more "0" bits, and
// a final "1" bit. We merge the first "1" bit from the padding into dsbyte,
// giving 00000110b (0x06) and 00011111b (0x1f).
// [1] http://csrc.nist.gov/publications/drafts/fips-202/fips_202_draft.pdf
// "Draft FIPS 202: SHA-3 Standard: Permutation-Based Hash and
// Extendable-Output Functions (May 2014)"
dsbyte byte
storage storageBuf
// Specific to SHA-3 and SHAKE.
outputLen int // the default output size in bytes
state spongeDirection // whether the sponge is absorbing or squeezing
turbo bool // Whether we're using 12 rounds instead of 24
}
// BlockSize returns the rate of sponge underlying this hash function.
func (d *State) BlockSize() int { return d.rate }
// Size returns the output size of the hash function in bytes.
func (d *State) Size() int { return d.outputLen }
// Reset clears the internal state by zeroing the sponge state and
// the byte buffer, and setting Sponge.state to absorbing.
func (d *State) Reset() {
// Zero the permutation's state.
for i := range d.a {
d.a[i] = 0
}
d.state = spongeAbsorbing
d.bufo = 0
d.bufe = 0
}
func (d *State) clone() *State {
ret := *d
return &ret
}
// permute applies the KeccakF-1600 permutation. It handles
// any input-output buffering.
func (d *State) permute() {
switch d.state {
case spongeAbsorbing:
// If we're absorbing, we need to xor the input into the state
// before applying the permutation.
xorIn(d, d.buf())
d.bufe = 0
d.bufo = 0
KeccakF1600(&d.a, d.turbo)
case spongeSqueezing:
// If we're squeezing, we need to apply the permutation before
// copying more output.
KeccakF1600(&d.a, d.turbo)
d.bufe = d.rate
d.bufo = 0
copyOut(d, d.buf())
}
}
// pads appends the domain separation bits in dsbyte, applies
// the multi-bitrate 10..1 padding rule, and permutes the state.
func (d *State) padAndPermute(dsbyte byte) {
// Pad with this instance's domain-separator bits. We know that there's
// at least one byte of space in d.buf() because, if it were full,
// permute would have been called to empty it. dsbyte also contains the
// first one bit for the padding. See the comment in the state struct.
zerosStart := d.bufe + 1
d.bufe = d.rate
buf := d.buf()
buf[zerosStart-1] = dsbyte
for i := zerosStart; i < d.rate; i++ {
buf[i] = 0
}
// This adds the final one bit for the padding. Because of the way that
// bits are numbered from the LSB upwards, the final bit is the MSB of
// the last byte.
buf[d.rate-1] ^= 0x80
// Apply the permutation
d.permute()
d.state = spongeSqueezing
d.bufe = d.rate
copyOut(d, buf)
}
// Write absorbs more data into the hash's state. It produces an error
// if more data is written to the ShakeHash after writing
func (d *State) Write(p []byte) (written int, err error) {
if d.state != spongeAbsorbing {
panic("sha3: write to sponge after read")
}
written = len(p)
for len(p) > 0 {
bufl := d.bufe - d.bufo
if bufl == 0 && len(p) >= d.rate {
// The fast path; absorb a full "rate" bytes of input and apply the permutation.
xorIn(d, p[:d.rate])
p = p[d.rate:]
KeccakF1600(&d.a, d.turbo)
} else {
// The slow path; buffer the input until we can fill the sponge, and then xor it in.
todo := d.rate - bufl
if todo > len(p) {
todo = len(p)
}
d.bufe += todo
buf := d.buf()
copy(buf[bufl:], p[:todo])
p = p[todo:]
// If the sponge is full, apply the permutation.
if d.bufe == d.rate {
d.permute()
}
}
}
return written, nil
}
// Read squeezes an arbitrary number of bytes from the sponge.
func (d *State) Read(out []byte) (n int, err error) {
// If we're still absorbing, pad and apply the permutation.
if d.state == spongeAbsorbing {
d.padAndPermute(d.dsbyte)
}
n = len(out)
// Now, do the squeezing.
for len(out) > 0 {
buf := d.buf()
n := copy(out, buf)
d.bufo += n
out = out[n:]
// Apply the permutation if we've squeezed the sponge dry.
if d.bufo == d.bufe {
d.permute()
}
}
return
}
// Sum applies padding to the hash state and then squeezes out the desired
// number of output bytes.
func (d *State) Sum(in []byte) []byte {
// Make a copy of the original hash so that caller can keep writing
// and summing.
dup := d.clone()
hash := make([]byte, dup.outputLen)
_, _ = dup.Read(hash)
return append(in, hash...)
}
func (d *State) IsAbsorbing() bool {
return d.state == spongeAbsorbing
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/sha3_s390x.s
================================================
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !gccgo,!appengine
#include "textflag.h"
// func kimd(function code, chain *[200]byte, src []byte)
TEXT ·kimd(SB), NOFRAME|NOSPLIT, $0-40
MOVD function+0(FP), R0
MOVD chain+8(FP), R1
LMG src+16(FP), R2, R3 // R2=base, R3=len
continue:
WORD $0xB93E0002 // KIMD --, R2
BVS continue // continue if interrupted
MOVD $0, R0 // reset R0 for pre-go1.8 compilers
RET
// func klmd(function code, chain *[200]byte, dst, src []byte)
TEXT ·klmd(SB), NOFRAME|NOSPLIT, $0-64
// TODO: SHAKE support
MOVD function+0(FP), R0
MOVD chain+8(FP), R1
LMG dst+16(FP), R2, R3 // R2=base, R3=len
LMG src+40(FP), R4, R5 // R4=base, R5=len
continue:
WORD $0xB93F0024 // KLMD R2, R4
BVS continue // continue if interrupted
MOVD $0, R0 // reset R0 for pre-go1.8 compilers
RET
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/shake.go
================================================
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sha3
// This file defines the ShakeHash interface, and provides
// functions for creating SHAKE and cSHAKE instances, as well as utility
// functions for hashing bytes to arbitrary-length output.
//
//
// SHAKE implementation is based on FIPS PUB 202 [1]
// cSHAKE implementations is based on NIST SP 800-185 [2]
//
// [1] https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
// [2] https://doi.org/10.6028/NIST.SP.800-185
import (
"io"
)
// ShakeHash defines the interface to hash functions that
// support arbitrary-length output.
type ShakeHash interface {
// Write absorbs more data into the hash's state. It panics if input is
// written to it after output has been read from it.
io.Writer
// Read reads more output from the hash; reading affects the hash's
// state. (ShakeHash.Read is thus very different from Hash.Sum)
// It never returns an error.
io.Reader
// Clone returns a copy of the ShakeHash in its current state.
Clone() ShakeHash
// Reset resets the ShakeHash to its initial state.
Reset()
}
// Consts for configuring initial SHA-3 state
const (
dsbyteShake = 0x1f
rate128 = 168
rate256 = 136
)
// Clone returns copy of SHAKE context within its current state.
func (d *State) Clone() ShakeHash {
return d.clone()
}
// NewShake128 creates a new SHAKE128 variable-output-length ShakeHash.
// Its generic security strength is 128 bits against all attacks if at
// least 32 bytes of its output are used.
func NewShake128() State {
return State{rate: rate128, dsbyte: dsbyteShake}
}
// NewTurboShake128 creates a new TurboSHAKE128 variable-output-length ShakeHash.
// Its generic security strength is 128 bits against all attacks if at
// least 32 bytes of its output are used.
// D is the domain separation byte and must be between 0x01 and 0x7f inclusive.
func NewTurboShake128(D byte) State {
if D == 0 || D > 0x7f {
panic("turboshake: D out of range")
}
return State{rate: rate128, dsbyte: D, turbo: true}
}
// NewShake256 creates a new SHAKE256 variable-output-length ShakeHash.
// Its generic security strength is 256 bits against all attacks if
// at least 64 bytes of its output are used.
func NewShake256() State {
return State{rate: rate256, dsbyte: dsbyteShake}
}
// NewTurboShake256 creates a new TurboSHAKE256 variable-output-length ShakeHash.
// Its generic security strength is 256 bits against all attacks if
// at least 64 bytes of its output are used.
// D is the domain separation byte and must be between 0x01 and 0x7f inclusive.
func NewTurboShake256(D byte) State {
if D == 0 || D > 0x7f {
panic("turboshake: D out of range")
}
return State{rate: rate256, dsbyte: D, turbo: true}
}
// ShakeSum128 writes an arbitrary-length digest of data into hash.
func ShakeSum128(hash, data []byte) {
h := NewShake128()
_, _ = h.Write(data)
_, _ = h.Read(hash)
}
// ShakeSum256 writes an arbitrary-length digest of data into hash.
func ShakeSum256(hash, data []byte) {
h := NewShake256()
_, _ = h.Write(data)
_, _ = h.Read(hash)
}
// TurboShakeSum128 writes an arbitrary-length digest of data into hash.
func TurboShakeSum128(hash, data []byte, D byte) {
h := NewTurboShake128(D)
_, _ = h.Write(data)
_, _ = h.Read(hash)
}
// TurboShakeSum256 writes an arbitrary-length digest of data into hash.
func TurboShakeSum256(hash, data []byte, D byte) {
h := NewTurboShake256(D)
_, _ = h.Write(data)
_, _ = h.Read(hash)
}
func (d *State) SwitchDS(D byte) {
d.dsbyte = D
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/xor.go
================================================
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (!amd64 && !386 && !ppc64le) || appengine
// +build !amd64,!386,!ppc64le appengine
package sha3
// A storageBuf is an aligned array of maxRate bytes.
type storageBuf [maxRate]byte
func (b *storageBuf) asBytes() *[maxRate]byte {
return (*[maxRate]byte)(b)
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/xor_generic.go
================================================
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (!amd64 || appengine) && (!386 || appengine) && (!ppc64le || appengine)
// +build !amd64 appengine
// +build !386 appengine
// +build !ppc64le appengine
package sha3
import "encoding/binary"
// xorIn xors the bytes in buf into the state; it
// makes no non-portable assumptions about memory layout
// or alignment.
func xorIn(d *State, buf []byte) {
n := len(buf) / 8
for i := 0; i < n; i++ {
a := binary.LittleEndian.Uint64(buf)
d.a[i] ^= a
buf = buf[8:]
}
}
// copyOut copies ulint64s to a byte buffer.
func copyOut(d *State, b []byte) {
for i := 0; len(b) >= 8; i++ {
binary.LittleEndian.PutUint64(b, d.a[i])
b = b[8:]
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/internal/sha3/xor_unaligned.go
================================================
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build (amd64 || 386 || ppc64le) && !appengine
// +build amd64 386 ppc64le
// +build !appengine
package sha3
import "unsafe"
// A storageBuf is an aligned array of maxRate bytes.
type storageBuf [maxRate / 8]uint64
func (b *storageBuf) asBytes() *[maxRate]byte {
return (*[maxRate]byte)(unsafe.Pointer(b))
}
// xorInuses unaligned reads and writes to update d.a to contain d.a
// XOR buf.
func xorIn(d *State, buf []byte) {
n := len(buf)
bw := (*[maxRate / 8]uint64)(unsafe.Pointer(&buf[0]))[: n/8 : n/8]
if n >= 72 {
d.a[0] ^= bw[0]
d.a[1] ^= bw[1]
d.a[2] ^= bw[2]
d.a[3] ^= bw[3]
d.a[4] ^= bw[4]
d.a[5] ^= bw[5]
d.a[6] ^= bw[6]
d.a[7] ^= bw[7]
d.a[8] ^= bw[8]
}
if n >= 104 {
d.a[9] ^= bw[9]
d.a[10] ^= bw[10]
d.a[11] ^= bw[11]
d.a[12] ^= bw[12]
}
if n >= 136 {
d.a[13] ^= bw[13]
d.a[14] ^= bw[14]
d.a[15] ^= bw[15]
d.a[16] ^= bw[16]
}
if n >= 144 {
d.a[17] ^= bw[17]
}
if n >= 168 {
d.a[18] ^= bw[18]
d.a[19] ^= bw[19]
d.a[20] ^= bw[20]
}
}
func copyOut(d *State, buf []byte) {
ab := (*[maxRate]uint8)(unsafe.Pointer(&d.a[0]))
copy(buf, ab[:])
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp25519/fp.go
================================================
// Package fp25519 provides prime field arithmetic over GF(2^255-19).
package fp25519
import (
"errors"
"github.com/cloudflare/circl/internal/conv"
)
// Size in bytes of an element.
const Size = 32
// Elt is a prime field element.
type Elt [Size]byte
func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) }
// p is the prime modulus 2^255-19.
var p = Elt{
0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
}
// P returns the prime modulus 2^255-19.
func P() Elt { return p }
// ToBytes stores in b the little-endian byte representation of x.
func ToBytes(b []byte, x *Elt) error {
if len(b) != Size {
return errors.New("wrong size")
}
Modp(x)
copy(b, x[:])
return nil
}
// IsZero returns true if x is equal to 0.
func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} }
// SetOne assigns x=1.
func SetOne(x *Elt) { *x = Elt{}; x[0] = 1 }
// Neg calculates z = -x.
func Neg(z, x *Elt) { Sub(z, &p, x) }
// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue, which is
// indicated by returning isQR = true. Otherwise, when x/y is a quadratic
// non-residue, z will have an undetermined value and isQR = false.
func InvSqrt(z, x, y *Elt) (isQR bool) {
sqrtMinusOne := &Elt{
0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
0xa7, 0xd7, 0xfb, 0x3d, 0x99, 0x00, 0x4d, 0x2b,
0x0b, 0xdf, 0xc1, 0x4f, 0x80, 0x24, 0x83, 0x2b,
}
t0, t1, t2, t3 := &Elt{}, &Elt{}, &Elt{}, &Elt{}
Mul(t0, x, y) // t0 = u*v
Sqr(t1, y) // t1 = v^2
Mul(t2, t0, t1) // t2 = u*v^3
Sqr(t0, t1) // t0 = v^4
Mul(t1, t0, t2) // t1 = u*v^7
var Tab [4]*Elt
Tab[0] = &Elt{}
Tab[1] = &Elt{}
Tab[2] = t3
Tab[3] = t1
*Tab[0] = *t1
Sqr(Tab[0], Tab[0])
Sqr(Tab[1], Tab[0])
Sqr(Tab[1], Tab[1])
Mul(Tab[1], Tab[1], Tab[3])
Mul(Tab[0], Tab[0], Tab[1])
Sqr(Tab[0], Tab[0])
Mul(Tab[0], Tab[0], Tab[1])
Sqr(Tab[1], Tab[0])
for i := 0; i < 4; i++ {
Sqr(Tab[1], Tab[1])
}
Mul(Tab[1], Tab[1], Tab[0])
Sqr(Tab[2], Tab[1])
for i := 0; i < 4; i++ {
Sqr(Tab[2], Tab[2])
}
Mul(Tab[2], Tab[2], Tab[0])
Sqr(Tab[1], Tab[2])
for i := 0; i < 14; i++ {
Sqr(Tab[1], Tab[1])
}
Mul(Tab[1], Tab[1], Tab[2])
Sqr(Tab[2], Tab[1])
for i := 0; i < 29; i++ {
Sqr(Tab[2], Tab[2])
}
Mul(Tab[2], Tab[2], Tab[1])
Sqr(Tab[1], Tab[2])
for i := 0; i < 59; i++ {
Sqr(Tab[1], Tab[1])
}
Mul(Tab[1], Tab[1], Tab[2])
for i := 0; i < 5; i++ {
Sqr(Tab[1], Tab[1])
}
Mul(Tab[1], Tab[1], Tab[0])
Sqr(Tab[2], Tab[1])
for i := 0; i < 124; i++ {
Sqr(Tab[2], Tab[2])
}
Mul(Tab[2], Tab[2], Tab[1])
Sqr(Tab[2], Tab[2])
Sqr(Tab[2], Tab[2])
Mul(Tab[2], Tab[2], Tab[3])
Mul(z, t3, t2) // z = xy^(p+3)/8 = xy^3*(xy^7)^(p-5)/8
// Checking whether y z^2 == x
Sqr(t0, z) // t0 = z^2
Mul(t0, t0, y) // t0 = yz^2
Sub(t1, t0, x) // t1 = t0-u
Add(t2, t0, x) // t2 = t0+u
if IsZero(t1) {
return true
} else if IsZero(t2) {
Mul(z, z, sqrtMinusOne) // z = z*sqrt(-1)
return true
} else {
return false
}
}
// Inv calculates z = 1/x mod p.
func Inv(z, x *Elt) {
x0, x1, x2 := &Elt{}, &Elt{}, &Elt{}
Sqr(x1, x)
Sqr(x0, x1)
Sqr(x0, x0)
Mul(x0, x0, x)
Mul(z, x0, x1)
Sqr(x1, z)
Mul(x0, x0, x1)
Sqr(x1, x0)
for i := 0; i < 4; i++ {
Sqr(x1, x1)
}
Mul(x0, x0, x1)
Sqr(x1, x0)
for i := 0; i < 9; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, x0)
Sqr(x2, x1)
for i := 0; i < 19; i++ {
Sqr(x2, x2)
}
Mul(x2, x2, x1)
for i := 0; i < 10; i++ {
Sqr(x2, x2)
}
Mul(x2, x2, x0)
Sqr(x0, x2)
for i := 0; i < 49; i++ {
Sqr(x0, x0)
}
Mul(x0, x0, x2)
Sqr(x1, x0)
for i := 0; i < 99; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, x0)
for i := 0; i < 50; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, x2)
for i := 0; i < 5; i++ {
Sqr(x1, x1)
}
Mul(z, z, x1)
}
// Cmov assigns y to x if n is 1.
func Cmov(x, y *Elt, n uint) { cmov(x, y, n) }
// Cswap interchanges x and y if n is 1.
func Cswap(x, y *Elt, n uint) { cswap(x, y, n) }
// Add calculates z = x+y mod p.
func Add(z, x, y *Elt) { add(z, x, y) }
// Sub calculates z = x-y mod p.
func Sub(z, x, y *Elt) { sub(z, x, y) }
// AddSub calculates (x,y) = (x+y mod p, x-y mod p).
func AddSub(x, y *Elt) { addsub(x, y) }
// Mul calculates z = x*y mod p.
func Mul(z, x, y *Elt) { mul(z, x, y) }
// Sqr calculates z = x^2 mod p.
func Sqr(z, x *Elt) { sqr(z, x) }
// Modp ensures that z is between [0,p-1].
func Modp(z *Elt) { modp(z) }
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.go
================================================
//go:build amd64 && !purego
// +build amd64,!purego
package fp25519
import (
"golang.org/x/sys/cpu"
)
var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX
var _ = hasBmi2Adx
func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) }
func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) }
func add(z, x, y *Elt) { addAmd64(z, x, y) }
func sub(z, x, y *Elt) { subAmd64(z, x, y) }
func addsub(x, y *Elt) { addsubAmd64(x, y) }
func mul(z, x, y *Elt) { mulAmd64(z, x, y) }
func sqr(z, x *Elt) { sqrAmd64(z, x) }
func modp(z *Elt) { modpAmd64(z) }
//go:noescape
func cmovAmd64(x, y *Elt, n uint)
//go:noescape
func cswapAmd64(x, y *Elt, n uint)
//go:noescape
func addAmd64(z, x, y *Elt)
//go:noescape
func subAmd64(z, x, y *Elt)
//go:noescape
func addsubAmd64(x, y *Elt)
//go:noescape
func mulAmd64(z, x, y *Elt)
//go:noescape
func sqrAmd64(z, x *Elt)
//go:noescape
func modpAmd64(z *Elt)
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp25519/fp_amd64.h
================================================
// This code was imported from https://github.com/armfazh/rfc7748_precomputed
// CHECK_BMI2ADX triggers bmi2adx if supported,
// otherwise it fallbacks to legacy code.
#define CHECK_BMI2ADX(label, legacy, bmi2adx) \
CMPB ·hasBmi2Adx(SB), $0 \
JE label \
bmi2adx \
RET \
label: \
legacy \
RET
// cselect is a conditional move
// if b=1: it copies y into x;
// if b=0: x remains with the same value;
// if b<> 0,1: undefined.
// Uses: AX, DX, FLAGS
// Instr: x86_64, cmov
#define cselect(x,y,b) \
TESTQ b, b \
MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \
MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \
MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \
MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x;
// cswap is a conditional swap
// if b=1: x,y <- y,x;
// if b=0: x,y remain with the same values;
// if b<> 0,1: undefined.
// Uses: AX, DX, R8, FLAGS
// Instr: x86_64, cmov
#define cswap(x,y,b) \
TESTQ b, b \
MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \
MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \
MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \
MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y;
// additionLeg adds x and y and stores in z
// Uses: AX, DX, R8-R11, FLAGS
// Instr: x86_64, cmov
#define additionLeg(z,x,y) \
MOVL $38, AX; \
MOVL $0, DX; \
MOVQ 0+x, R8; ADDQ 0+y, R8; \
MOVQ 8+x, R9; ADCQ 8+y, R9; \
MOVQ 16+x, R10; ADCQ 16+y, R10; \
MOVQ 24+x, R11; ADCQ 24+y, R11; \
CMOVQCS AX, DX; \
ADDQ DX, R8; \
ADCQ $0, R9; MOVQ R9, 8+z; \
ADCQ $0, R10; MOVQ R10, 16+z; \
ADCQ $0, R11; MOVQ R11, 24+z; \
MOVL $0, DX; \
CMOVQCS AX, DX; \
ADDQ DX, R8; MOVQ R8, 0+z;
// additionAdx adds x and y and stores in z
// Uses: AX, DX, R8-R11, FLAGS
// Instr: x86_64, cmov, adx
#define additionAdx(z,x,y) \
MOVL $38, AX; \
XORL DX, DX; \
MOVQ 0+x, R8; ADCXQ 0+y, R8; \
MOVQ 8+x, R9; ADCXQ 8+y, R9; \
MOVQ 16+x, R10; ADCXQ 16+y, R10; \
MOVQ 24+x, R11; ADCXQ 24+y, R11; \
CMOVQCS AX, DX ; \
XORL AX, AX; \
ADCXQ DX, R8; \
ADCXQ AX, R9; MOVQ R9, 8+z; \
ADCXQ AX, R10; MOVQ R10, 16+z; \
ADCXQ AX, R11; MOVQ R11, 24+z; \
MOVL $38, DX; \
CMOVQCS DX, AX; \
ADDQ AX, R8; MOVQ R8, 0+z;
// subtraction subtracts y from x and stores in z
// Uses: AX, DX, R8-R11, FLAGS
// Instr: x86_64, cmov
#define subtraction(z,x,y) \
MOVL $38, AX; \
MOVQ 0+x, R8; SUBQ 0+y, R8; \
MOVQ 8+x, R9; SBBQ 8+y, R9; \
MOVQ 16+x, R10; SBBQ 16+y, R10; \
MOVQ 24+x, R11; SBBQ 24+y, R11; \
MOVL $0, DX; \
CMOVQCS AX, DX; \
SUBQ DX, R8; \
SBBQ $0, R9; MOVQ R9, 8+z; \
SBBQ $0, R10; MOVQ R10, 16+z; \
SBBQ $0, R11; MOVQ R11, 24+z; \
MOVL $0, DX; \
CMOVQCS AX, DX; \
SUBQ DX, R8; MOVQ R8, 0+z;
// integerMulAdx multiplies x and y and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64, bmi2, adx
#define integerMulAdx(z,x,y) \
MOVL $0,R15; \
MOVQ 0+y, DX; XORL AX, AX; \
MULXQ 0+x, AX, R8; MOVQ AX, 0+z; \
MULXQ 8+x, AX, R9; ADCXQ AX, R8; \
MULXQ 16+x, AX, R10; ADCXQ AX, R9; \
MULXQ 24+x, AX, R11; ADCXQ AX, R10; \
MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; \
MOVQ 8+y, DX; XORL AX, AX; \
MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 8+z; \
MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; \
MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; \
MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; \
MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; \
MOVQ 16+y, DX; XORL AX, AX; \
MULXQ 0+x, AX, R8; ADCXQ R12, AX; MOVQ AX, 16+z; \
MULXQ 8+x, AX, R9; ADCXQ R13, R8; ADOXQ AX, R8; \
MULXQ 16+x, AX, R10; ADCXQ R14, R9; ADOXQ AX, R9; \
MULXQ 24+x, AX, R11; ADCXQ R15, R10; ADOXQ AX, R10; \
MOVL $0, AX;;;;;;;;; ADCXQ AX, R11; ADOXQ AX, R11; \
MOVQ 24+y, DX; XORL AX, AX; \
MULXQ 0+x, AX, R12; ADCXQ R8, AX; MOVQ AX, 24+z; \
MULXQ 8+x, AX, R13; ADCXQ R9, R12; ADOXQ AX, R12; MOVQ R12, 32+z; \
MULXQ 16+x, AX, R14; ADCXQ R10, R13; ADOXQ AX, R13; MOVQ R13, 40+z; \
MULXQ 24+x, AX, R15; ADCXQ R11, R14; ADOXQ AX, R14; MOVQ R14, 48+z; \
MOVL $0, AX;;;;;;;;; ADCXQ AX, R15; ADOXQ AX, R15; MOVQ R15, 56+z;
// integerMulLeg multiplies x and y and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64
#define integerMulLeg(z,x,y) \
MOVQ 0+y, R8; \
MOVQ 0+x, AX; MULQ R8; MOVQ AX, 0+z; MOVQ DX, R15; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R8; \
ADDQ R13, R15; \
ADCQ R14, R10; MOVQ R10, 16+z; \
ADCQ AX, R11; MOVQ R11, 24+z; \
ADCQ $0, DX; MOVQ DX, 32+z; \
MOVQ 8+y, R8; \
MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R8; \
ADDQ R12, R15; MOVQ R15, 8+z; \
ADCQ R13, R9; \
ADCQ R14, R10; \
ADCQ AX, R11; \
ADCQ $0, DX; \
ADCQ 16+z, R9; MOVQ R9, R15; \
ADCQ 24+z, R10; MOVQ R10, 24+z; \
ADCQ 32+z, R11; MOVQ R11, 32+z; \
ADCQ $0, DX; MOVQ DX, 40+z; \
MOVQ 16+y, R8; \
MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R8; \
ADDQ R12, R15; MOVQ R15, 16+z; \
ADCQ R13, R9; \
ADCQ R14, R10; \
ADCQ AX, R11; \
ADCQ $0, DX; \
ADCQ 24+z, R9; MOVQ R9, R15; \
ADCQ 32+z, R10; MOVQ R10, 32+z; \
ADCQ 40+z, R11; MOVQ R11, 40+z; \
ADCQ $0, DX; MOVQ DX, 48+z; \
MOVQ 24+y, R8; \
MOVQ 0+x, AX; MULQ R8; MOVQ AX, R12; MOVQ DX, R9; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, R13; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R8; \
ADDQ R12, R15; MOVQ R15, 24+z; \
ADCQ R13, R9; \
ADCQ R14, R10; \
ADCQ AX, R11; \
ADCQ $0, DX; \
ADCQ 32+z, R9; MOVQ R9, 32+z; \
ADCQ 40+z, R10; MOVQ R10, 40+z; \
ADCQ 48+z, R11; MOVQ R11, 48+z; \
ADCQ $0, DX; MOVQ DX, 56+z;
// integerSqrLeg squares x and stores in z
// Uses: AX, CX, DX, R8-R15, FLAGS
// Instr: x86_64
#define integerSqrLeg(z,x) \
MOVQ 0+x, R8; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, R9; MOVQ DX, R10; /* A[0]*A[1] */ \
MOVQ 16+x, AX; MULQ R8; MOVQ AX, R14; MOVQ DX, R11; /* A[0]*A[2] */ \
MOVQ 24+x, AX; MULQ R8; MOVQ AX, R15; MOVQ DX, R12; /* A[0]*A[3] */ \
MOVQ 24+x, R8; \
MOVQ 8+x, AX; MULQ R8; MOVQ AX, CX; MOVQ DX, R13; /* A[3]*A[1] */ \
MOVQ 16+x, AX; MULQ R8; /* A[3]*A[2] */ \
\
ADDQ R14, R10;\
ADCQ R15, R11; MOVL $0, R15;\
ADCQ CX, R12;\
ADCQ AX, R13;\
ADCQ $0, DX; MOVQ DX, R14;\
MOVQ 8+x, AX; MULQ 16+x;\
\
ADDQ AX, R11;\
ADCQ DX, R12;\
ADCQ $0, R13;\
ADCQ $0, R14;\
ADCQ $0, R15;\
\
SHLQ $1, R14, R15; MOVQ R15, 56+z;\
SHLQ $1, R13, R14; MOVQ R14, 48+z;\
SHLQ $1, R12, R13; MOVQ R13, 40+z;\
SHLQ $1, R11, R12; MOVQ R12, 32+z;\
SHLQ $1, R10, R11; MOVQ R11, 24+z;\
SHLQ $1, R9, R10; MOVQ R10, 16+z;\
SHLQ $1, R9; MOVQ R9, 8+z;\
\
MOVQ 0+x,AX; MULQ AX; MOVQ AX, 0+z; MOVQ DX, R9;\
MOVQ 8+x,AX; MULQ AX; MOVQ AX, R10; MOVQ DX, R11;\
MOVQ 16+x,AX; MULQ AX; MOVQ AX, R12; MOVQ DX, R13;\
MOVQ 24+x,AX; MULQ AX; MOVQ AX, R14; MOVQ DX, R15;\
\
ADDQ 8+z, R9; MOVQ R9, 8+z;\
ADCQ 16+z, R10; MOVQ R10, 16+z;\
ADCQ 24+z, R11; MOVQ R11, 24+z;\
ADCQ 32+z, R12; MOVQ R12, 32+z;\
ADCQ 40+z, R13; MOVQ R13, 40+z;\
ADCQ 48+z, R14; MOVQ R14, 48+z;\
ADCQ 56+z, R15; MOVQ R15, 56+z;
// integerSqrAdx squares x and stores in z
// Uses: AX, CX, DX, R8-R15, FLAGS
// Instr: x86_64, bmi2, adx
#define integerSqrAdx(z,x) \
MOVQ 0+x, DX; /* A[0] */ \
MULXQ 8+x, R8, R14; /* A[1]*A[0] */ XORL R15, R15; \
MULXQ 16+x, R9, R10; /* A[2]*A[0] */ ADCXQ R14, R9; \
MULXQ 24+x, AX, CX; /* A[3]*A[0] */ ADCXQ AX, R10; \
MOVQ 24+x, DX; /* A[3] */ \
MULXQ 8+x, R11, R12; /* A[1]*A[3] */ ADCXQ CX, R11; \
MULXQ 16+x, AX, R13; /* A[2]*A[3] */ ADCXQ AX, R12; \
MOVQ 8+x, DX; /* A[1] */ ADCXQ R15, R13; \
MULXQ 16+x, AX, CX; /* A[2]*A[1] */ MOVL $0, R14; \
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADCXQ R15, R14; \
XORL R15, R15; \
ADOXQ AX, R10; ADCXQ R8, R8; \
ADOXQ CX, R11; ADCXQ R9, R9; \
ADOXQ R15, R12; ADCXQ R10, R10; \
ADOXQ R15, R13; ADCXQ R11, R11; \
ADOXQ R15, R14; ADCXQ R12, R12; \
;;;;;;;;;;;;;;; ADCXQ R13, R13; \
;;;;;;;;;;;;;;; ADCXQ R14, R14; \
MOVQ 0+x, DX; MULXQ DX, AX, CX; /* A[0]^2 */ \
;;;;;;;;;;;;;;; MOVQ AX, 0+z; \
ADDQ CX, R8; MOVQ R8, 8+z; \
MOVQ 8+x, DX; MULXQ DX, AX, CX; /* A[1]^2 */ \
ADCQ AX, R9; MOVQ R9, 16+z; \
ADCQ CX, R10; MOVQ R10, 24+z; \
MOVQ 16+x, DX; MULXQ DX, AX, CX; /* A[2]^2 */ \
ADCQ AX, R11; MOVQ R11, 32+z; \
ADCQ CX, R12; MOVQ R12, 40+z; \
MOVQ 24+x, DX; MULXQ DX, AX, CX; /* A[3]^2 */ \
ADCQ AX, R13; MOVQ R13, 48+z; \
ADCQ CX, R14; MOVQ R14, 56+z;
// reduceFromDouble finds z congruent to x modulo p such that 0> 63)
// PUT BIT 255 IN CARRY FLAG AND CLEAR
x3 &^= 1 << 63
x0, c0 := bits.Add64(x0, cx, 0)
x1, c1 := bits.Add64(x1, 0, c0)
x2, c2 := bits.Add64(x2, 0, c1)
x3, _ = bits.Add64(x3, 0, c2)
// TEST FOR BIT 255 AGAIN; ONLY TRIGGERED ON OVERFLOW MODULO 2^255-19
// cx = C[255] ? 0 : 19
cx = uint64(19) &^ (-(x3 >> 63))
// CLEAR BIT 255
x3 &^= 1 << 63
x0, c0 = bits.Sub64(x0, cx, 0)
x1, c1 = bits.Sub64(x1, 0, c0)
x2, c2 = bits.Sub64(x2, 0, c1)
x3, _ = bits.Sub64(x3, 0, c2)
binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
}
func red64(z *Elt, x0, x1, x2, x3, x4, x5, x6, x7 uint64) {
h0, l0 := bits.Mul64(x4, 38)
h1, l1 := bits.Mul64(x5, 38)
h2, l2 := bits.Mul64(x6, 38)
h3, l3 := bits.Mul64(x7, 38)
l1, c0 := bits.Add64(h0, l1, 0)
l2, c1 := bits.Add64(h1, l2, c0)
l3, c2 := bits.Add64(h2, l3, c1)
l4, _ := bits.Add64(h3, 0, c2)
l0, c0 = bits.Add64(l0, x0, 0)
l1, c1 = bits.Add64(l1, x1, c0)
l2, c2 = bits.Add64(l2, x2, c1)
l3, c3 := bits.Add64(l3, x3, c2)
l4, _ = bits.Add64(l4, 0, c3)
_, l4 = bits.Mul64(l4, 38)
l0, c0 = bits.Add64(l0, l4, 0)
z1, c1 := bits.Add64(l1, 0, c0)
z2, c2 := bits.Add64(l2, 0, c1)
z3, c3 := bits.Add64(l3, 0, c2)
z0, _ := bits.Add64(l0, (-c3)&38, 0)
binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp25519/fp_noasm.go
================================================
//go:build !amd64 || purego
// +build !amd64 purego
package fp25519
func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) }
func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) }
func add(z, x, y *Elt) { addGeneric(z, x, y) }
func sub(z, x, y *Elt) { subGeneric(z, x, y) }
func addsub(x, y *Elt) { addsubGeneric(x, y) }
func mul(z, x, y *Elt) { mulGeneric(z, x, y) }
func sqr(z, x *Elt) { sqrGeneric(z, x) }
func modp(z *Elt) { modpGeneric(z) }
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp.go
================================================
// Package fp448 provides prime field arithmetic over GF(2^448-2^224-1).
package fp448
import (
"errors"
"github.com/cloudflare/circl/internal/conv"
)
// Size in bytes of an element.
const Size = 56
// Elt is a prime field element.
type Elt [Size]byte
func (e Elt) String() string { return conv.BytesLe2Hex(e[:]) }
// p is the prime modulus 2^448-2^224-1.
var p = Elt{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
// P returns the prime modulus 2^448-2^224-1.
func P() Elt { return p }
// ToBytes stores in b the little-endian byte representation of x.
func ToBytes(b []byte, x *Elt) error {
if len(b) != Size {
return errors.New("wrong size")
}
Modp(x)
copy(b, x[:])
return nil
}
// IsZero returns true if x is equal to 0.
func IsZero(x *Elt) bool { Modp(x); return *x == Elt{} }
// IsOne returns true if x is equal to 1.
func IsOne(x *Elt) bool { Modp(x); return *x == Elt{1} }
// SetOne assigns x=1.
func SetOne(x *Elt) { *x = Elt{1} }
// One returns the 1 element.
func One() (x Elt) { x = Elt{1}; return }
// Neg calculates z = -x.
func Neg(z, x *Elt) { Sub(z, &p, x) }
// Modp ensures that z is between [0,p-1].
func Modp(z *Elt) { Sub(z, z, &p) }
// InvSqrt calculates z = sqrt(x/y) iff x/y is a quadratic-residue. If so,
// isQR = true; otherwise, isQR = false, since x/y is a quadratic non-residue,
// and z = sqrt(-x/y).
func InvSqrt(z, x, y *Elt) (isQR bool) {
// First note that x^(2(k+1)) = x^(p-1)/2 * x = legendre(x) * x
// so that's x if x is a quadratic residue and -x otherwise.
// Next, y^(6k+3) = y^(4k+2) * y^(2k+1) = y^(p-1) * y^((p-1)/2) = legendre(y).
// So the z we compute satisfies z^2 y = x^(2(k+1)) y^(6k+3) = legendre(x)*legendre(y).
// Thus if x and y are quadratic residues, then z is indeed sqrt(x/y).
t0, t1 := &Elt{}, &Elt{}
Mul(t0, x, y) // x*y
Sqr(t1, y) // y^2
Mul(t1, t0, t1) // x*y^3
powPminus3div4(z, t1) // (x*y^3)^k
Mul(z, z, t0) // z = x*y*(x*y^3)^k = x^(k+1) * y^(3k+1)
// Check if x/y is a quadratic residue
Sqr(t0, z) // z^2
Mul(t0, t0, y) // y*z^2
Sub(t0, t0, x) // y*z^2-x
return IsZero(t0)
}
// Inv calculates z = 1/x mod p.
func Inv(z, x *Elt) {
// Calculates z = x^(4k+1) = x^(p-3+1) = x^(p-2) = x^-1, where k = (p-3)/4.
t := &Elt{}
powPminus3div4(t, x) // t = x^k
Sqr(t, t) // t = x^2k
Sqr(t, t) // t = x^4k
Mul(z, t, x) // z = x^(4k+1)
}
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
func powPminus3div4(z, x *Elt) {
x0, x1 := &Elt{}, &Elt{}
Sqr(z, x)
Mul(z, z, x)
Sqr(x0, z)
Mul(x0, x0, x)
Sqr(z, x0)
Sqr(z, z)
Sqr(z, z)
Mul(z, z, x0)
Sqr(x1, z)
for i := 0; i < 5; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, z)
Sqr(z, x1)
for i := 0; i < 11; i++ {
Sqr(z, z)
}
Mul(z, z, x1)
Sqr(z, z)
Sqr(z, z)
Sqr(z, z)
Mul(z, z, x0)
Sqr(x1, z)
for i := 0; i < 26; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, z)
Sqr(z, x1)
for i := 0; i < 53; i++ {
Sqr(z, z)
}
Mul(z, z, x1)
Sqr(z, z)
Sqr(z, z)
Sqr(z, z)
Mul(z, z, x0)
Sqr(x1, z)
for i := 0; i < 110; i++ {
Sqr(x1, x1)
}
Mul(x1, x1, z)
Sqr(z, x1)
Mul(z, z, x)
for i := 0; i < 223; i++ {
Sqr(z, z)
}
Mul(z, z, x1)
}
// Cmov assigns y to x if n is 1.
func Cmov(x, y *Elt, n uint) { cmov(x, y, n) }
// Cswap interchanges x and y if n is 1.
func Cswap(x, y *Elt, n uint) { cswap(x, y, n) }
// Add calculates z = x+y mod p.
func Add(z, x, y *Elt) { add(z, x, y) }
// Sub calculates z = x-y mod p.
func Sub(z, x, y *Elt) { sub(z, x, y) }
// AddSub calculates (x,y) = (x+y mod p, x-y mod p).
func AddSub(x, y *Elt) { addsub(x, y) }
// Mul calculates z = x*y mod p.
func Mul(z, x, y *Elt) { mul(z, x, y) }
// Sqr calculates z = x^2 mod p.
func Sqr(z, x *Elt) { sqr(z, x) }
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.go
================================================
//go:build amd64 && !purego
// +build amd64,!purego
package fp448
import (
"golang.org/x/sys/cpu"
)
var hasBmi2Adx = cpu.X86.HasBMI2 && cpu.X86.HasADX
var _ = hasBmi2Adx
func cmov(x, y *Elt, n uint) { cmovAmd64(x, y, n) }
func cswap(x, y *Elt, n uint) { cswapAmd64(x, y, n) }
func add(z, x, y *Elt) { addAmd64(z, x, y) }
func sub(z, x, y *Elt) { subAmd64(z, x, y) }
func addsub(x, y *Elt) { addsubAmd64(x, y) }
func mul(z, x, y *Elt) { mulAmd64(z, x, y) }
func sqr(z, x *Elt) { sqrAmd64(z, x) }
/* Functions defined in fp_amd64.s */
//go:noescape
func cmovAmd64(x, y *Elt, n uint)
//go:noescape
func cswapAmd64(x, y *Elt, n uint)
//go:noescape
func addAmd64(z, x, y *Elt)
//go:noescape
func subAmd64(z, x, y *Elt)
//go:noescape
func addsubAmd64(x, y *Elt)
//go:noescape
func mulAmd64(z, x, y *Elt)
//go:noescape
func sqrAmd64(z, x *Elt)
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.h
================================================
// This code was imported from https://github.com/armfazh/rfc7748_precomputed
// CHECK_BMI2ADX triggers bmi2adx if supported,
// otherwise it fallbacks to legacy code.
#define CHECK_BMI2ADX(label, legacy, bmi2adx) \
CMPB ·hasBmi2Adx(SB), $0 \
JE label \
bmi2adx \
RET \
label: \
legacy \
RET
// cselect is a conditional move
// if b=1: it copies y into x;
// if b=0: x remains with the same value;
// if b<> 0,1: undefined.
// Uses: AX, DX, FLAGS
// Instr: x86_64, cmov
#define cselect(x,y,b) \
TESTQ b, b \
MOVQ 0+x, AX; MOVQ 0+y, DX; CMOVQNE DX, AX; MOVQ AX, 0+x; \
MOVQ 8+x, AX; MOVQ 8+y, DX; CMOVQNE DX, AX; MOVQ AX, 8+x; \
MOVQ 16+x, AX; MOVQ 16+y, DX; CMOVQNE DX, AX; MOVQ AX, 16+x; \
MOVQ 24+x, AX; MOVQ 24+y, DX; CMOVQNE DX, AX; MOVQ AX, 24+x; \
MOVQ 32+x, AX; MOVQ 32+y, DX; CMOVQNE DX, AX; MOVQ AX, 32+x; \
MOVQ 40+x, AX; MOVQ 40+y, DX; CMOVQNE DX, AX; MOVQ AX, 40+x; \
MOVQ 48+x, AX; MOVQ 48+y, DX; CMOVQNE DX, AX; MOVQ AX, 48+x;
// cswap is a conditional swap
// if b=1: x,y <- y,x;
// if b=0: x,y remain with the same values;
// if b<> 0,1: undefined.
// Uses: AX, DX, R8, FLAGS
// Instr: x86_64, cmov
#define cswap(x,y,b) \
TESTQ b, b \
MOVQ 0+x, AX; MOVQ AX, R8; MOVQ 0+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 0+x; MOVQ DX, 0+y; \
MOVQ 8+x, AX; MOVQ AX, R8; MOVQ 8+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 8+x; MOVQ DX, 8+y; \
MOVQ 16+x, AX; MOVQ AX, R8; MOVQ 16+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 16+x; MOVQ DX, 16+y; \
MOVQ 24+x, AX; MOVQ AX, R8; MOVQ 24+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 24+x; MOVQ DX, 24+y; \
MOVQ 32+x, AX; MOVQ AX, R8; MOVQ 32+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 32+x; MOVQ DX, 32+y; \
MOVQ 40+x, AX; MOVQ AX, R8; MOVQ 40+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 40+x; MOVQ DX, 40+y; \
MOVQ 48+x, AX; MOVQ AX, R8; MOVQ 48+y, DX; CMOVQNE DX, AX; CMOVQNE R8, DX; MOVQ AX, 48+x; MOVQ DX, 48+y;
// additionLeg adds x and y and stores in z
// Uses: AX, DX, R8-R14, FLAGS
// Instr: x86_64
#define additionLeg(z,x,y) \
MOVQ 0+x, R8; ADDQ 0+y, R8; \
MOVQ 8+x, R9; ADCQ 8+y, R9; \
MOVQ 16+x, R10; ADCQ 16+y, R10; \
MOVQ 24+x, R11; ADCQ 24+y, R11; \
MOVQ 32+x, R12; ADCQ 32+y, R12; \
MOVQ 40+x, R13; ADCQ 40+y, R13; \
MOVQ 48+x, R14; ADCQ 48+y, R14; \
MOVQ $0, AX; ADCQ $0, AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
ADDQ AX, R8; MOVQ $0, AX; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ DX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
ADCQ $0, AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
ADDQ AX, R8; MOVQ R8, 0+z; \
ADCQ $0, R9; MOVQ R9, 8+z; \
ADCQ $0, R10; MOVQ R10, 16+z; \
ADCQ DX, R11; MOVQ R11, 24+z; \
ADCQ $0, R12; MOVQ R12, 32+z; \
ADCQ $0, R13; MOVQ R13, 40+z; \
ADCQ $0, R14; MOVQ R14, 48+z;
// additionAdx adds x and y and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64, adx
#define additionAdx(z,x,y) \
MOVL $32, R15; \
XORL DX, DX; \
MOVQ 0+x, R8; ADCXQ 0+y, R8; \
MOVQ 8+x, R9; ADCXQ 8+y, R9; \
MOVQ 16+x, R10; ADCXQ 16+y, R10; \
MOVQ 24+x, R11; ADCXQ 24+y, R11; \
MOVQ 32+x, R12; ADCXQ 32+y, R12; \
MOVQ 40+x, R13; ADCXQ 40+y, R13; \
MOVQ 48+x, R14; ADCXQ 48+y, R14; \
;;;;;;;;;;;;;;; ADCXQ DX, DX; \
XORL AX, AX; \
ADCXQ DX, R8; SHLXQ R15, DX, DX; \
ADCXQ AX, R9; \
ADCXQ AX, R10; \
ADCXQ DX, R11; \
ADCXQ AX, R12; \
ADCXQ AX, R13; \
ADCXQ AX, R14; \
ADCXQ AX, AX; \
XORL DX, DX; \
ADCXQ AX, R8; MOVQ R8, 0+z; SHLXQ R15, AX, AX; \
ADCXQ DX, R9; MOVQ R9, 8+z; \
ADCXQ DX, R10; MOVQ R10, 16+z; \
ADCXQ AX, R11; MOVQ R11, 24+z; \
ADCXQ DX, R12; MOVQ R12, 32+z; \
ADCXQ DX, R13; MOVQ R13, 40+z; \
ADCXQ DX, R14; MOVQ R14, 48+z;
// subtraction subtracts y from x and stores in z
// Uses: AX, DX, R8-R14, FLAGS
// Instr: x86_64
#define subtraction(z,x,y) \
MOVQ 0+x, R8; SUBQ 0+y, R8; \
MOVQ 8+x, R9; SBBQ 8+y, R9; \
MOVQ 16+x, R10; SBBQ 16+y, R10; \
MOVQ 24+x, R11; SBBQ 24+y, R11; \
MOVQ 32+x, R12; SBBQ 32+y, R12; \
MOVQ 40+x, R13; SBBQ 40+y, R13; \
MOVQ 48+x, R14; SBBQ 48+y, R14; \
MOVQ $0, AX; SETCS AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
SUBQ AX, R8; MOVQ $0, AX; \
SBBQ $0, R9; \
SBBQ $0, R10; \
SBBQ DX, R11; \
SBBQ $0, R12; \
SBBQ $0, R13; \
SBBQ $0, R14; \
SETCS AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
SUBQ AX, R8; MOVQ R8, 0+z; \
SBBQ $0, R9; MOVQ R9, 8+z; \
SBBQ $0, R10; MOVQ R10, 16+z; \
SBBQ DX, R11; MOVQ R11, 24+z; \
SBBQ $0, R12; MOVQ R12, 32+z; \
SBBQ $0, R13; MOVQ R13, 40+z; \
SBBQ $0, R14; MOVQ R14, 48+z;
// maddBmi2Adx multiplies x and y and accumulates in z
// Uses: AX, DX, R15, FLAGS
// Instr: x86_64, bmi2, adx
#define maddBmi2Adx(z,x,y,i,r0,r1,r2,r3,r4,r5,r6) \
MOVQ i+y, DX; XORL AX, AX; \
MULXQ 0+x, AX, R8; ADOXQ AX, r0; ADCXQ R8, r1; MOVQ r0,i+z; \
MULXQ 8+x, AX, r0; ADOXQ AX, r1; ADCXQ r0, r2; MOVQ $0, R8; \
MULXQ 16+x, AX, r0; ADOXQ AX, r2; ADCXQ r0, r3; \
MULXQ 24+x, AX, r0; ADOXQ AX, r3; ADCXQ r0, r4; \
MULXQ 32+x, AX, r0; ADOXQ AX, r4; ADCXQ r0, r5; \
MULXQ 40+x, AX, r0; ADOXQ AX, r5; ADCXQ r0, r6; \
MULXQ 48+x, AX, r0; ADOXQ AX, r6; ADCXQ R8, r0; \
;;;;;;;;;;;;;;;;;;; ADOXQ R8, r0;
// integerMulAdx multiplies x and y and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64, bmi2, adx
#define integerMulAdx(z,x,y) \
MOVL $0,R15; \
MOVQ 0+y, DX; XORL AX, AX; MOVQ $0, R8; \
MULXQ 0+x, AX, R9; MOVQ AX, 0+z; \
MULXQ 8+x, AX, R10; ADCXQ AX, R9; \
MULXQ 16+x, AX, R11; ADCXQ AX, R10; \
MULXQ 24+x, AX, R12; ADCXQ AX, R11; \
MULXQ 32+x, AX, R13; ADCXQ AX, R12; \
MULXQ 40+x, AX, R14; ADCXQ AX, R13; \
MULXQ 48+x, AX, R15; ADCXQ AX, R14; \
;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R15; \
maddBmi2Adx(z,x,y, 8, R9,R10,R11,R12,R13,R14,R15) \
maddBmi2Adx(z,x,y,16,R10,R11,R12,R13,R14,R15, R9) \
maddBmi2Adx(z,x,y,24,R11,R12,R13,R14,R15, R9,R10) \
maddBmi2Adx(z,x,y,32,R12,R13,R14,R15, R9,R10,R11) \
maddBmi2Adx(z,x,y,40,R13,R14,R15, R9,R10,R11,R12) \
maddBmi2Adx(z,x,y,48,R14,R15, R9,R10,R11,R12,R13) \
MOVQ R15, 56+z; \
MOVQ R9, 64+z; \
MOVQ R10, 72+z; \
MOVQ R11, 80+z; \
MOVQ R12, 88+z; \
MOVQ R13, 96+z; \
MOVQ R14, 104+z;
// maddLegacy multiplies x and y and accumulates in z
// Uses: AX, DX, R15, FLAGS
// Instr: x86_64
#define maddLegacy(z,x,y,i) \
MOVQ i+y, R15; \
MOVQ 0+x, AX; MULQ R15; MOVQ AX, R8; ;;;;;;;;;;;; MOVQ DX, R9; \
MOVQ 8+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \
MOVQ 16+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \
MOVQ 24+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \
MOVQ 32+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \
MOVQ 40+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \
MOVQ 48+x, AX; MULQ R15; ADDQ AX, R14; ADCQ $0, DX; \
ADDQ 0+i+z, R8; MOVQ R8, 0+i+z; \
ADCQ 8+i+z, R9; MOVQ R9, 8+i+z; \
ADCQ 16+i+z, R10; MOVQ R10, 16+i+z; \
ADCQ 24+i+z, R11; MOVQ R11, 24+i+z; \
ADCQ 32+i+z, R12; MOVQ R12, 32+i+z; \
ADCQ 40+i+z, R13; MOVQ R13, 40+i+z; \
ADCQ 48+i+z, R14; MOVQ R14, 48+i+z; \
ADCQ $0, DX; MOVQ DX, 56+i+z;
// integerMulLeg multiplies x and y and stores in z
// Uses: AX, DX, R8-R15, FLAGS
// Instr: x86_64
#define integerMulLeg(z,x,y) \
MOVQ 0+y, R15; \
MOVQ 0+x, AX; MULQ R15; MOVQ AX, 0+z; ;;;;;;;;;;;; MOVQ DX, R8; \
MOVQ 8+x, AX; MULQ R15; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \
MOVQ 16+x, AX; MULQ R15; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; MOVQ R9, 16+z; \
MOVQ 24+x, AX; MULQ R15; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; MOVQ R10, 24+z; \
MOVQ 32+x, AX; MULQ R15; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; MOVQ R11, 32+z; \
MOVQ 40+x, AX; MULQ R15; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; MOVQ R12, 40+z; \
MOVQ 48+x, AX; MULQ R15; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX,56+z; MOVQ R13, 48+z; \
maddLegacy(z,x,y, 8) \
maddLegacy(z,x,y,16) \
maddLegacy(z,x,y,24) \
maddLegacy(z,x,y,32) \
maddLegacy(z,x,y,40) \
maddLegacy(z,x,y,48)
// integerSqrLeg squares x and stores in z
// Uses: AX, CX, DX, R8-R15, FLAGS
// Instr: x86_64
#define integerSqrLeg(z,x) \
XORL R15, R15; \
MOVQ 0+x, CX; \
MOVQ CX, AX; MULQ CX; MOVQ AX, 0+z; MOVQ DX, R8; \
ADDQ CX, CX; ADCQ $0, R15; \
MOVQ 8+x, AX; MULQ CX; ADDQ AX, R8; ADCQ $0, DX; MOVQ DX, R9; MOVQ R8, 8+z; \
MOVQ 16+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ DX, R10; \
MOVQ 24+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; MOVQ DX, R11; \
MOVQ 32+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ DX, R12; \
MOVQ 40+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; MOVQ DX, R13; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ DX, R14; \
\
MOVQ 8+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9,16+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 8+x, AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \
ADDQ 8+x, CX; ADCQ $0, R15; \
MOVQ 16+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 24+z; \
MOVQ 24+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 32+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 40+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R9; \
\
MOVQ 16+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 32+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 16+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \
ADDQ 16+x, CX; ADCQ $0, R15; \
MOVQ 24+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 40+z; \
MOVQ 32+x, AX; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; ADDQ R8, R13; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 40+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX,R10; \
\
MOVQ 24+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 48+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 24+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \
ADDQ 24+x, CX; ADCQ $0, R15; \
MOVQ 32+x, AX; MULQ CX; ADDQ AX, R14; ADCQ $0, DX; ADDQ R8, R14; ADCQ $0, DX; MOVQ DX, R8; MOVQ R14, 56+z; \
MOVQ 40+x, AX; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; ADDQ R8, R9; ADCQ $0, DX; MOVQ DX, R8; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX,R11; \
\
MOVQ 32+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R9; ADCQ $0, DX; MOVQ R9, 64+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 32+x,AX; ADDQ AX, DX; ADCQ $0, R11; MOVQ DX, R8; \
ADDQ 32+x, CX; ADCQ $0, R15; \
MOVQ 40+x, AX; MULQ CX; ADDQ AX, R10; ADCQ $0, DX; ADDQ R8, R10; ADCQ $0, DX; MOVQ DX, R8; MOVQ R10, 72+z; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; ADDQ R8, R11; ADCQ $0, DX; MOVQ DX,R12; \
\
XORL R13, R13; \
XORL R14, R14; \
MOVQ 40+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R11; ADCQ $0, DX; MOVQ R11, 80+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 40+x,AX; ADDQ AX, DX; ADCQ $0, R13; MOVQ DX, R8; \
ADDQ 40+x, CX; ADCQ $0, R15; \
MOVQ 48+x, AX; MULQ CX; ADDQ AX, R12; ADCQ $0, DX; ADDQ R8, R12; ADCQ $0, DX; MOVQ DX, R8; MOVQ R12, 88+z; \
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8, R13; ADCQ $0,R14; \
\
XORL R9, R9; \
MOVQ 48+x, CX; \
MOVQ CX, AX; ADDQ R15, CX; MOVQ $0, R15; ADCQ $0, R15; \
;;;;;;;;;;;;;; MULQ CX; ADDQ AX, R13; ADCQ $0, DX; MOVQ R13, 96+z; \
MOVQ R15, AX; NEGQ AX; ANDQ 48+x,AX; ADDQ AX, DX; ADCQ $0, R9; MOVQ DX, R8; \
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ADDQ R8,R14; ADCQ $0, R9; MOVQ R14, 104+z;
// integerSqrAdx squares x and stores in z
// Uses: AX, CX, DX, R8-R15, FLAGS
// Instr: x86_64, bmi2, adx
#define integerSqrAdx(z,x) \
XORL R15, R15; \
MOVQ 0+x, DX; \
;;;;;;;;;;;;;; MULXQ DX, AX, R8; MOVQ AX, 0+z; \
ADDQ DX, DX; ADCQ $0, R15; CLC; \
MULXQ 8+x, AX, R9; ADCXQ AX, R8; MOVQ R8, 8+z; \
MULXQ 16+x, AX, R10; ADCXQ AX, R9; MOVQ $0, R8;\
MULXQ 24+x, AX, R11; ADCXQ AX, R10; \
MULXQ 32+x, AX, R12; ADCXQ AX, R11; \
MULXQ 40+x, AX, R13; ADCXQ AX, R12; \
MULXQ 48+x, AX, R14; ADCXQ AX, R13; \
;;;;;;;;;;;;;;;;;;;; ADCXQ R8, R14; \
\
MOVQ 8+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 8+x, R8; \
ADDQ AX, R9; MOVQ R9, 16+z; \
ADCQ CX, R8; \
ADCQ $0, R11; \
ADDQ 8+x, DX; \
ADCQ $0, R15; \
XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \
MULXQ 16+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 24+z; \
MULXQ 24+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; MOVQ $0, R10; \
MULXQ 32+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; \
MULXQ 40+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; \
MULXQ 48+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \
;;;;;;;;;;;;;;;;;;; ADCXQ R10, R9; \
\
MOVQ 16+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 16+x, R8; \
ADDQ AX, R11; MOVQ R11, 32+z; \
ADCQ CX, R8; \
ADCQ $0, R13; \
ADDQ 16+x, DX; \
ADCQ $0, R15; \
XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \
MULXQ 24+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 40+z; \
MULXQ 32+x, AX, CX; ADCXQ AX, R13; ADOXQ CX, R14; MOVQ $0, R12; \
MULXQ 40+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; \
MULXQ 48+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; \
;;;;;;;;;;;;;;;;;;; ADCXQ R11,R10; \
\
MOVQ 24+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 24+x, R8; \
ADDQ AX, R13; MOVQ R13, 48+z; \
ADCQ CX, R8; \
ADCQ $0, R9; \
ADDQ 24+x, DX; \
ADCQ $0, R15; \
XORL R13, R13; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R14; \
MULXQ 32+x, AX, CX; ADCXQ AX, R14; ADOXQ CX, R9; MOVQ R14, 56+z; \
MULXQ 40+x, AX, CX; ADCXQ AX, R9; ADOXQ CX, R10; MOVQ $0, R14; \
MULXQ 48+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; \
;;;;;;;;;;;;;;;;;;; ADCXQ R12,R11; \
\
MOVQ 32+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 32+x, R8; \
ADDQ AX, R9; MOVQ R9, 64+z; \
ADCQ CX, R8; \
ADCQ $0, R11; \
ADDQ 32+x, DX; \
ADCQ $0, R15; \
XORL R9, R9; ;;;;;;;;;;;;;;;;;;;;; ADOXQ R8, R10; \
MULXQ 40+x, AX, CX; ADCXQ AX, R10; ADOXQ CX, R11; MOVQ R10, 72+z; \
MULXQ 48+x, AX, CX; ADCXQ AX, R11; ADOXQ CX, R12; \
;;;;;;;;;;;;;;;;;;; ADCXQ R13,R12; \
\
MOVQ 40+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 40+x, R8; \
ADDQ AX, R11; MOVQ R11, 80+z; \
ADCQ CX, R8; \
ADCQ $0, R13; \
ADDQ 40+x, DX; \
ADCQ $0, R15; \
XORL R11, R11; ;;;;;;;;;;;;;;;;;;; ADOXQ R8, R12; \
MULXQ 48+x, AX, CX; ADCXQ AX, R12; ADOXQ CX, R13; MOVQ R12, 88+z; \
;;;;;;;;;;;;;;;;;;; ADCXQ R14,R13; \
\
MOVQ 48+x, DX; \
MOVQ DX, AX; ADDQ R15, DX; MOVQ $0, R15; ADCQ $0, R15; \
MULXQ AX, AX, CX; \
MOVQ R15, R8; NEGQ R8; ANDQ 48+x, R8; \
XORL R10, R10; ;;;;;;;;;;;;;; ADOXQ CX, R14; \
;;;;;;;;;;;;;; ADCXQ AX, R13; ;;;;;;;;;;;;;; MOVQ R13, 96+z; \
;;;;;;;;;;;;;; ADCXQ R8, R14; MOVQ R14, 104+z;
// reduceFromDoubleLeg finds a z=x modulo p such that z<2^448 and stores in z
// Uses: AX, R8-R15, FLAGS
// Instr: x86_64
#define reduceFromDoubleLeg(z,x) \
/* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \
/* (r14, r13, r12, r11, r10,r9,r8,r15) */ \
MOVQ 80+x,AX; MOVQ AX,R10; \
MOVQ $0xFFFFFFFF00000000, R8; \
ANDQ R8,R10; \
\
MOVQ $0,R14; \
MOVQ 104+x,R13; SHLQ $1,R13,R14; \
MOVQ 96+x,R12; SHLQ $1,R12,R13; \
MOVQ 88+x,R11; SHLQ $1,R11,R12; \
MOVQ 72+x, R9; SHLQ $1,R10,R11; \
MOVQ 64+x, R8; SHLQ $1,R10; \
MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \
MOVQ 56+x,R15; \
\
ADDQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \
ADCQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \
ADCQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \
ADCQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \
ADCQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \
ADCQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \
ADCQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \
ADCQ $0,R14; \
/* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \
/* ( r9, r8, r15, r13, r12, r11, r10) */ \
MOVQ R10, AX; \
SHRQ $32,R11,R10; \
SHRQ $32,R12,R11; \
SHRQ $32,R13,R12; \
SHRQ $32,R15,R13; \
SHRQ $32, R8,R15; \
SHRQ $32, R9, R8; \
SHRQ $32, AX, R9; \
\
ADDQ 0+z,R10; \
ADCQ 8+z,R11; \
ADCQ 16+z,R12; \
ADCQ 24+z,R13; \
ADCQ 32+z,R15; \
ADCQ 40+z, R8; \
ADCQ 48+z, R9; \
ADCQ $0,R14; \
/* ( c7) + (c6,...,c0) */ \
/* (r14) */ \
MOVQ R14, AX; SHLQ $32, AX; \
ADDQ R14,R10; MOVQ $0,R14; \
ADCQ $0,R11; \
ADCQ $0,R12; \
ADCQ AX,R13; \
ADCQ $0,R15; \
ADCQ $0, R8; \
ADCQ $0, R9; \
ADCQ $0,R14; \
/* ( c7) + (c6,...,c0) */ \
/* (r14) */ \
MOVQ R14, AX; SHLQ $32,AX; \
ADDQ R14,R10; MOVQ R10, 0+z; \
ADCQ $0,R11; MOVQ R11, 8+z; \
ADCQ $0,R12; MOVQ R12,16+z; \
ADCQ AX,R13; MOVQ R13,24+z; \
ADCQ $0,R15; MOVQ R15,32+z; \
ADCQ $0, R8; MOVQ R8,40+z; \
ADCQ $0, R9; MOVQ R9,48+z;
// reduceFromDoubleAdx finds a z=x modulo p such that z<2^448 and stores in z
// Uses: AX, R8-R15, FLAGS
// Instr: x86_64, adx
#define reduceFromDoubleAdx(z,x) \
/* ( ,2C13,2C12,2C11,2C10|C10,C9,C8, C7) + (C6,...,C0) */ \
/* (r14, r13, r12, r11, r10,r9,r8,r15) */ \
MOVQ 80+x,AX; MOVQ AX,R10; \
MOVQ $0xFFFFFFFF00000000, R8; \
ANDQ R8,R10; \
\
MOVQ $0,R14; \
MOVQ 104+x,R13; SHLQ $1,R13,R14; \
MOVQ 96+x,R12; SHLQ $1,R12,R13; \
MOVQ 88+x,R11; SHLQ $1,R11,R12; \
MOVQ 72+x, R9; SHLQ $1,R10,R11; \
MOVQ 64+x, R8; SHLQ $1,R10; \
MOVQ $0xFFFFFFFF,R15; ANDQ R15,AX; ORQ AX,R10; \
MOVQ 56+x,R15; \
\
XORL AX,AX; \
ADCXQ 0+x,R15; MOVQ R15, 0+z; MOVQ 56+x,R15; \
ADCXQ 8+x, R8; MOVQ R8, 8+z; MOVQ 64+x, R8; \
ADCXQ 16+x, R9; MOVQ R9,16+z; MOVQ 72+x, R9; \
ADCXQ 24+x,R10; MOVQ R10,24+z; MOVQ 80+x,R10; \
ADCXQ 32+x,R11; MOVQ R11,32+z; MOVQ 88+x,R11; \
ADCXQ 40+x,R12; MOVQ R12,40+z; MOVQ 96+x,R12; \
ADCXQ 48+x,R13; MOVQ R13,48+z; MOVQ 104+x,R13; \
ADCXQ AX,R14; \
/* (c10c9,c9c8,c8c7,c7c13,c13c12,c12c11,c11c10) + (c6,...,c0) */ \
/* ( r9, r8, r15, r13, r12, r11, r10) */ \
MOVQ R10, AX; \
SHRQ $32,R11,R10; \
SHRQ $32,R12,R11; \
SHRQ $32,R13,R12; \
SHRQ $32,R15,R13; \
SHRQ $32, R8,R15; \
SHRQ $32, R9, R8; \
SHRQ $32, AX, R9; \
\
XORL AX,AX; \
ADCXQ 0+z,R10; \
ADCXQ 8+z,R11; \
ADCXQ 16+z,R12; \
ADCXQ 24+z,R13; \
ADCXQ 32+z,R15; \
ADCXQ 40+z, R8; \
ADCXQ 48+z, R9; \
ADCXQ AX,R14; \
/* ( c7) + (c6,...,c0) */ \
/* (r14) */ \
MOVQ R14, AX; SHLQ $32, AX; \
CLC; \
ADCXQ R14,R10; MOVQ $0,R14; \
ADCXQ R14,R11; \
ADCXQ R14,R12; \
ADCXQ AX,R13; \
ADCXQ R14,R15; \
ADCXQ R14, R8; \
ADCXQ R14, R9; \
ADCXQ R14,R14; \
/* ( c7) + (c6,...,c0) */ \
/* (r14) */ \
MOVQ R14, AX; SHLQ $32, AX; \
CLC; \
ADCXQ R14,R10; MOVQ R10, 0+z; MOVQ $0,R14; \
ADCXQ R14,R11; MOVQ R11, 8+z; \
ADCXQ R14,R12; MOVQ R12,16+z; \
ADCXQ AX,R13; MOVQ R13,24+z; \
ADCXQ R14,R15; MOVQ R15,32+z; \
ADCXQ R14, R8; MOVQ R8,40+z; \
ADCXQ R14, R9; MOVQ R9,48+z;
// addSub calculates two operations: x,y = x+y,x-y
// Uses: AX, DX, R8-R15, FLAGS
#define addSub(x,y) \
MOVQ 0+x, R8; ADDQ 0+y, R8; \
MOVQ 8+x, R9; ADCQ 8+y, R9; \
MOVQ 16+x, R10; ADCQ 16+y, R10; \
MOVQ 24+x, R11; ADCQ 24+y, R11; \
MOVQ 32+x, R12; ADCQ 32+y, R12; \
MOVQ 40+x, R13; ADCQ 40+y, R13; \
MOVQ 48+x, R14; ADCQ 48+y, R14; \
MOVQ $0, AX; ADCQ $0, AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
ADDQ AX, R8; MOVQ $0, AX; \
ADCQ $0, R9; \
ADCQ $0, R10; \
ADCQ DX, R11; \
ADCQ $0, R12; \
ADCQ $0, R13; \
ADCQ $0, R14; \
ADCQ $0, AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
ADDQ AX, R8; MOVQ 0+x,AX; MOVQ R8, 0+x; MOVQ AX, R8; \
ADCQ $0, R9; MOVQ 8+x,AX; MOVQ R9, 8+x; MOVQ AX, R9; \
ADCQ $0, R10; MOVQ 16+x,AX; MOVQ R10, 16+x; MOVQ AX, R10; \
ADCQ DX, R11; MOVQ 24+x,AX; MOVQ R11, 24+x; MOVQ AX, R11; \
ADCQ $0, R12; MOVQ 32+x,AX; MOVQ R12, 32+x; MOVQ AX, R12; \
ADCQ $0, R13; MOVQ 40+x,AX; MOVQ R13, 40+x; MOVQ AX, R13; \
ADCQ $0, R14; MOVQ 48+x,AX; MOVQ R14, 48+x; MOVQ AX, R14; \
SUBQ 0+y, R8; \
SBBQ 8+y, R9; \
SBBQ 16+y, R10; \
SBBQ 24+y, R11; \
SBBQ 32+y, R12; \
SBBQ 40+y, R13; \
SBBQ 48+y, R14; \
MOVQ $0, AX; SETCS AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
SUBQ AX, R8; MOVQ $0, AX; \
SBBQ $0, R9; \
SBBQ $0, R10; \
SBBQ DX, R11; \
SBBQ $0, R12; \
SBBQ $0, R13; \
SBBQ $0, R14; \
SETCS AX; \
MOVQ AX, DX; \
SHLQ $32, DX; \
SUBQ AX, R8; MOVQ R8, 0+y; \
SBBQ $0, R9; MOVQ R9, 8+y; \
SBBQ $0, R10; MOVQ R10, 16+y; \
SBBQ DX, R11; MOVQ R11, 24+y; \
SBBQ $0, R12; MOVQ R12, 32+y; \
SBBQ $0, R13; MOVQ R13, 40+y; \
SBBQ $0, R14; MOVQ R14, 48+y;
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp_amd64.s
================================================
// +build amd64
#include "textflag.h"
#include "fp_amd64.h"
// func cmovAmd64(x, y *Elt, n uint)
TEXT ·cmovAmd64(SB),NOSPLIT,$0-24
MOVQ x+0(FP), DI
MOVQ y+8(FP), SI
MOVQ n+16(FP), BX
cselect(0(DI),0(SI),BX)
RET
// func cswapAmd64(x, y *Elt, n uint)
TEXT ·cswapAmd64(SB),NOSPLIT,$0-24
MOVQ x+0(FP), DI
MOVQ y+8(FP), SI
MOVQ n+16(FP), BX
cswap(0(DI),0(SI),BX)
RET
// func subAmd64(z, x, y *Elt)
TEXT ·subAmd64(SB),NOSPLIT,$0-24
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
MOVQ y+16(FP), BX
subtraction(0(DI),0(SI),0(BX))
RET
// func addsubAmd64(x, y *Elt)
TEXT ·addsubAmd64(SB),NOSPLIT,$0-16
MOVQ x+0(FP), DI
MOVQ y+8(FP), SI
addSub(0(DI),0(SI))
RET
#define addLegacy \
additionLeg(0(DI),0(SI),0(BX))
#define addBmi2Adx \
additionAdx(0(DI),0(SI),0(BX))
#define mulLegacy \
integerMulLeg(0(SP),0(SI),0(BX)) \
reduceFromDoubleLeg(0(DI),0(SP))
#define mulBmi2Adx \
integerMulAdx(0(SP),0(SI),0(BX)) \
reduceFromDoubleAdx(0(DI),0(SP))
#define sqrLegacy \
integerSqrLeg(0(SP),0(SI)) \
reduceFromDoubleLeg(0(DI),0(SP))
#define sqrBmi2Adx \
integerSqrAdx(0(SP),0(SI)) \
reduceFromDoubleAdx(0(DI),0(SP))
// func addAmd64(z, x, y *Elt)
TEXT ·addAmd64(SB),NOSPLIT,$0-24
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
MOVQ y+16(FP), BX
CHECK_BMI2ADX(LADD, addLegacy, addBmi2Adx)
// func mulAmd64(z, x, y *Elt)
TEXT ·mulAmd64(SB),NOSPLIT,$112-24
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
MOVQ y+16(FP), BX
CHECK_BMI2ADX(LMUL, mulLegacy, mulBmi2Adx)
// func sqrAmd64(z, x *Elt)
TEXT ·sqrAmd64(SB),NOSPLIT,$112-16
MOVQ z+0(FP), DI
MOVQ x+8(FP), SI
CHECK_BMI2ADX(LSQR, sqrLegacy, sqrBmi2Adx)
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp_generic.go
================================================
package fp448
import (
"encoding/binary"
"math/bits"
)
func cmovGeneric(x, y *Elt, n uint) {
m := -uint64(n & 0x1)
x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8])
x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8])
x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8])
y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8])
y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8])
y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8])
x0 = (x0 &^ m) | (y0 & m)
x1 = (x1 &^ m) | (y1 & m)
x2 = (x2 &^ m) | (y2 & m)
x3 = (x3 &^ m) | (y3 & m)
x4 = (x4 &^ m) | (y4 & m)
x5 = (x5 &^ m) | (y5 & m)
x6 = (x6 &^ m) | (y6 & m)
binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
binary.LittleEndian.PutUint64(x[4*8:5*8], x4)
binary.LittleEndian.PutUint64(x[5*8:6*8], x5)
binary.LittleEndian.PutUint64(x[6*8:7*8], x6)
}
func cswapGeneric(x, y *Elt, n uint) {
m := -uint64(n & 0x1)
x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8])
x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8])
x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8])
y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8])
y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8])
y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8])
t0 := m & (x0 ^ y0)
t1 := m & (x1 ^ y1)
t2 := m & (x2 ^ y2)
t3 := m & (x3 ^ y3)
t4 := m & (x4 ^ y4)
t5 := m & (x5 ^ y5)
t6 := m & (x6 ^ y6)
x0 ^= t0
x1 ^= t1
x2 ^= t2
x3 ^= t3
x4 ^= t4
x5 ^= t5
x6 ^= t6
y0 ^= t0
y1 ^= t1
y2 ^= t2
y3 ^= t3
y4 ^= t4
y5 ^= t5
y6 ^= t6
binary.LittleEndian.PutUint64(x[0*8:1*8], x0)
binary.LittleEndian.PutUint64(x[1*8:2*8], x1)
binary.LittleEndian.PutUint64(x[2*8:3*8], x2)
binary.LittleEndian.PutUint64(x[3*8:4*8], x3)
binary.LittleEndian.PutUint64(x[4*8:5*8], x4)
binary.LittleEndian.PutUint64(x[5*8:6*8], x5)
binary.LittleEndian.PutUint64(x[6*8:7*8], x6)
binary.LittleEndian.PutUint64(y[0*8:1*8], y0)
binary.LittleEndian.PutUint64(y[1*8:2*8], y1)
binary.LittleEndian.PutUint64(y[2*8:3*8], y2)
binary.LittleEndian.PutUint64(y[3*8:4*8], y3)
binary.LittleEndian.PutUint64(y[4*8:5*8], y4)
binary.LittleEndian.PutUint64(y[5*8:6*8], y5)
binary.LittleEndian.PutUint64(y[6*8:7*8], y6)
}
func addGeneric(z, x, y *Elt) {
x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8])
x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8])
x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8])
y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8])
y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8])
y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8])
z0, c0 := bits.Add64(x0, y0, 0)
z1, c1 := bits.Add64(x1, y1, c0)
z2, c2 := bits.Add64(x2, y2, c1)
z3, c3 := bits.Add64(x3, y3, c2)
z4, c4 := bits.Add64(x4, y4, c3)
z5, c5 := bits.Add64(x5, y5, c4)
z6, z7 := bits.Add64(x6, y6, c5)
z0, c0 = bits.Add64(z0, z7, 0)
z1, c1 = bits.Add64(z1, 0, c0)
z2, c2 = bits.Add64(z2, 0, c1)
z3, c3 = bits.Add64(z3, z7<<32, c2)
z4, c4 = bits.Add64(z4, 0, c3)
z5, c5 = bits.Add64(z5, 0, c4)
z6, z7 = bits.Add64(z6, 0, c5)
z0, c0 = bits.Add64(z0, z7, 0)
z1, c1 = bits.Add64(z1, 0, c0)
z2, c2 = bits.Add64(z2, 0, c1)
z3, c3 = bits.Add64(z3, z7<<32, c2)
z4, c4 = bits.Add64(z4, 0, c3)
z5, c5 = bits.Add64(z5, 0, c4)
z6, _ = bits.Add64(z6, 0, c5)
binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
binary.LittleEndian.PutUint64(z[4*8:5*8], z4)
binary.LittleEndian.PutUint64(z[5*8:6*8], z5)
binary.LittleEndian.PutUint64(z[6*8:7*8], z6)
}
func subGeneric(z, x, y *Elt) {
x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8])
x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8])
x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8])
y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8])
y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8])
y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8])
z0, c0 := bits.Sub64(x0, y0, 0)
z1, c1 := bits.Sub64(x1, y1, c0)
z2, c2 := bits.Sub64(x2, y2, c1)
z3, c3 := bits.Sub64(x3, y3, c2)
z4, c4 := bits.Sub64(x4, y4, c3)
z5, c5 := bits.Sub64(x5, y5, c4)
z6, z7 := bits.Sub64(x6, y6, c5)
z0, c0 = bits.Sub64(z0, z7, 0)
z1, c1 = bits.Sub64(z1, 0, c0)
z2, c2 = bits.Sub64(z2, 0, c1)
z3, c3 = bits.Sub64(z3, z7<<32, c2)
z4, c4 = bits.Sub64(z4, 0, c3)
z5, c5 = bits.Sub64(z5, 0, c4)
z6, z7 = bits.Sub64(z6, 0, c5)
z0, c0 = bits.Sub64(z0, z7, 0)
z1, c1 = bits.Sub64(z1, 0, c0)
z2, c2 = bits.Sub64(z2, 0, c1)
z3, c3 = bits.Sub64(z3, z7<<32, c2)
z4, c4 = bits.Sub64(z4, 0, c3)
z5, c5 = bits.Sub64(z5, 0, c4)
z6, _ = bits.Sub64(z6, 0, c5)
binary.LittleEndian.PutUint64(z[0*8:1*8], z0)
binary.LittleEndian.PutUint64(z[1*8:2*8], z1)
binary.LittleEndian.PutUint64(z[2*8:3*8], z2)
binary.LittleEndian.PutUint64(z[3*8:4*8], z3)
binary.LittleEndian.PutUint64(z[4*8:5*8], z4)
binary.LittleEndian.PutUint64(z[5*8:6*8], z5)
binary.LittleEndian.PutUint64(z[6*8:7*8], z6)
}
func addsubGeneric(x, y *Elt) {
z := &Elt{}
addGeneric(z, x, y)
subGeneric(y, x, y)
*x = *z
}
func mulGeneric(z, x, y *Elt) {
x0 := binary.LittleEndian.Uint64(x[0*8 : 1*8])
x1 := binary.LittleEndian.Uint64(x[1*8 : 2*8])
x2 := binary.LittleEndian.Uint64(x[2*8 : 3*8])
x3 := binary.LittleEndian.Uint64(x[3*8 : 4*8])
x4 := binary.LittleEndian.Uint64(x[4*8 : 5*8])
x5 := binary.LittleEndian.Uint64(x[5*8 : 6*8])
x6 := binary.LittleEndian.Uint64(x[6*8 : 7*8])
y0 := binary.LittleEndian.Uint64(y[0*8 : 1*8])
y1 := binary.LittleEndian.Uint64(y[1*8 : 2*8])
y2 := binary.LittleEndian.Uint64(y[2*8 : 3*8])
y3 := binary.LittleEndian.Uint64(y[3*8 : 4*8])
y4 := binary.LittleEndian.Uint64(y[4*8 : 5*8])
y5 := binary.LittleEndian.Uint64(y[5*8 : 6*8])
y6 := binary.LittleEndian.Uint64(y[6*8 : 7*8])
yy := [7]uint64{y0, y1, y2, y3, y4, y5, y6}
zz := [7]uint64{}
yi := yy[0]
h0, l0 := bits.Mul64(x0, yi)
h1, l1 := bits.Mul64(x1, yi)
h2, l2 := bits.Mul64(x2, yi)
h3, l3 := bits.Mul64(x3, yi)
h4, l4 := bits.Mul64(x4, yi)
h5, l5 := bits.Mul64(x5, yi)
h6, l6 := bits.Mul64(x6, yi)
zz[0] = l0
a0, c0 := bits.Add64(h0, l1, 0)
a1, c1 := bits.Add64(h1, l2, c0)
a2, c2 := bits.Add64(h2, l3, c1)
a3, c3 := bits.Add64(h3, l4, c2)
a4, c4 := bits.Add64(h4, l5, c3)
a5, c5 := bits.Add64(h5, l6, c4)
a6, _ := bits.Add64(h6, 0, c5)
for i := 1; i < 7; i++ {
yi = yy[i]
h0, l0 = bits.Mul64(x0, yi)
h1, l1 = bits.Mul64(x1, yi)
h2, l2 = bits.Mul64(x2, yi)
h3, l3 = bits.Mul64(x3, yi)
h4, l4 = bits.Mul64(x4, yi)
h5, l5 = bits.Mul64(x5, yi)
h6, l6 = bits.Mul64(x6, yi)
zz[i], c0 = bits.Add64(a0, l0, 0)
a0, c1 = bits.Add64(a1, l1, c0)
a1, c2 = bits.Add64(a2, l2, c1)
a2, c3 = bits.Add64(a3, l3, c2)
a3, c4 = bits.Add64(a4, l4, c3)
a4, c5 = bits.Add64(a5, l5, c4)
a5, a6 = bits.Add64(a6, l6, c5)
a0, c0 = bits.Add64(a0, h0, 0)
a1, c1 = bits.Add64(a1, h1, c0)
a2, c2 = bits.Add64(a2, h2, c1)
a3, c3 = bits.Add64(a3, h3, c2)
a4, c4 = bits.Add64(a4, h4, c3)
a5, c5 = bits.Add64(a5, h5, c4)
a6, _ = bits.Add64(a6, h6, c5)
}
red64(z, &zz, &[7]uint64{a0, a1, a2, a3, a4, a5, a6})
}
func sqrGeneric(z, x *Elt) { mulGeneric(z, x, x) }
func red64(z *Elt, l, h *[7]uint64) {
/* (2C13, 2C12, 2C11, 2C10|C10, C9, C8, C7) + (C6,...,C0) */
h0 := h[0]
h1 := h[1]
h2 := h[2]
h3 := ((h[3] & (0xFFFFFFFF << 32)) << 1) | (h[3] & 0xFFFFFFFF)
h4 := (h[3] >> 63) | (h[4] << 1)
h5 := (h[4] >> 63) | (h[5] << 1)
h6 := (h[5] >> 63) | (h[6] << 1)
h7 := (h[6] >> 63)
l0, c0 := bits.Add64(h0, l[0], 0)
l1, c1 := bits.Add64(h1, l[1], c0)
l2, c2 := bits.Add64(h2, l[2], c1)
l3, c3 := bits.Add64(h3, l[3], c2)
l4, c4 := bits.Add64(h4, l[4], c3)
l5, c5 := bits.Add64(h5, l[5], c4)
l6, c6 := bits.Add64(h6, l[6], c5)
l7, _ := bits.Add64(h7, 0, c6)
/* (C10C9, C9C8,C8C7,C7C13,C13C12,C12C11,C11C10) + (C6,...,C0) */
h0 = (h[3] >> 32) | (h[4] << 32)
h1 = (h[4] >> 32) | (h[5] << 32)
h2 = (h[5] >> 32) | (h[6] << 32)
h3 = (h[6] >> 32) | (h[0] << 32)
h4 = (h[0] >> 32) | (h[1] << 32)
h5 = (h[1] >> 32) | (h[2] << 32)
h6 = (h[2] >> 32) | (h[3] << 32)
l0, c0 = bits.Add64(l0, h0, 0)
l1, c1 = bits.Add64(l1, h1, c0)
l2, c2 = bits.Add64(l2, h2, c1)
l3, c3 = bits.Add64(l3, h3, c2)
l4, c4 = bits.Add64(l4, h4, c3)
l5, c5 = bits.Add64(l5, h5, c4)
l6, c6 = bits.Add64(l6, h6, c5)
l7, _ = bits.Add64(l7, 0, c6)
/* (C7) + (C6,...,C0) */
l0, c0 = bits.Add64(l0, l7, 0)
l1, c1 = bits.Add64(l1, 0, c0)
l2, c2 = bits.Add64(l2, 0, c1)
l3, c3 = bits.Add64(l3, l7<<32, c2)
l4, c4 = bits.Add64(l4, 0, c3)
l5, c5 = bits.Add64(l5, 0, c4)
l6, l7 = bits.Add64(l6, 0, c5)
/* (C7) + (C6,...,C0) */
l0, c0 = bits.Add64(l0, l7, 0)
l1, c1 = bits.Add64(l1, 0, c0)
l2, c2 = bits.Add64(l2, 0, c1)
l3, c3 = bits.Add64(l3, l7<<32, c2)
l4, c4 = bits.Add64(l4, 0, c3)
l5, c5 = bits.Add64(l5, 0, c4)
l6, _ = bits.Add64(l6, 0, c5)
binary.LittleEndian.PutUint64(z[0*8:1*8], l0)
binary.LittleEndian.PutUint64(z[1*8:2*8], l1)
binary.LittleEndian.PutUint64(z[2*8:3*8], l2)
binary.LittleEndian.PutUint64(z[3*8:4*8], l3)
binary.LittleEndian.PutUint64(z[4*8:5*8], l4)
binary.LittleEndian.PutUint64(z[5*8:6*8], l5)
binary.LittleEndian.PutUint64(z[6*8:7*8], l6)
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fp_noasm.go
================================================
//go:build !amd64 || purego
// +build !amd64 purego
package fp448
func cmov(x, y *Elt, n uint) { cmovGeneric(x, y, n) }
func cswap(x, y *Elt, n uint) { cswapGeneric(x, y, n) }
func add(z, x, y *Elt) { addGeneric(z, x, y) }
func sub(z, x, y *Elt) { subGeneric(z, x, y) }
func addsub(x, y *Elt) { addsubGeneric(x, y) }
func mul(z, x, y *Elt) { mulGeneric(z, x, y) }
func sqr(z, x *Elt) { sqrGeneric(z, x) }
================================================
FILE: vendor/github.com/cloudflare/circl/math/fp448/fuzzer.go
================================================
//go:build gofuzz
// +build gofuzz
// How to run the fuzzer:
//
// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz
// $ go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
// $ go-fuzz-build -libfuzzer -func FuzzReduction -o lib.a
// $ clang -fsanitize=fuzzer lib.a -o fu.exe
// $ ./fu.exe
package fp448
import (
"encoding/binary"
"fmt"
"math/big"
"github.com/cloudflare/circl/internal/conv"
)
// FuzzReduction is a fuzzer target for red64 function, which reduces t
// (112 bits) to a number t' (56 bits) congruent modulo p448.
func FuzzReduction(data []byte) int {
if len(data) != 2*Size {
return -1
}
var got, want Elt
var lo, hi [7]uint64
a := data[:Size]
b := data[Size:]
lo[0] = binary.LittleEndian.Uint64(a[0*8 : 1*8])
lo[1] = binary.LittleEndian.Uint64(a[1*8 : 2*8])
lo[2] = binary.LittleEndian.Uint64(a[2*8 : 3*8])
lo[3] = binary.LittleEndian.Uint64(a[3*8 : 4*8])
lo[4] = binary.LittleEndian.Uint64(a[4*8 : 5*8])
lo[5] = binary.LittleEndian.Uint64(a[5*8 : 6*8])
lo[6] = binary.LittleEndian.Uint64(a[6*8 : 7*8])
hi[0] = binary.LittleEndian.Uint64(b[0*8 : 1*8])
hi[1] = binary.LittleEndian.Uint64(b[1*8 : 2*8])
hi[2] = binary.LittleEndian.Uint64(b[2*8 : 3*8])
hi[3] = binary.LittleEndian.Uint64(b[3*8 : 4*8])
hi[4] = binary.LittleEndian.Uint64(b[4*8 : 5*8])
hi[5] = binary.LittleEndian.Uint64(b[5*8 : 6*8])
hi[6] = binary.LittleEndian.Uint64(b[6*8 : 7*8])
red64(&got, &lo, &hi)
t := conv.BytesLe2BigInt(data[:2*Size])
two448 := big.NewInt(1)
two448.Lsh(two448, 448) // 2^448
mask448 := big.NewInt(1)
mask448.Sub(two448, mask448) // 2^448-1
two224plus1 := big.NewInt(1)
two224plus1.Lsh(two224plus1, 224)
two224plus1.Add(two224plus1, big.NewInt(1)) // 2^224+1
var loBig, hiBig big.Int
for t.Cmp(two448) >= 0 {
loBig.And(t, mask448)
hiBig.Rsh(t, 448)
t.Mul(&hiBig, two224plus1)
t.Add(t, &loBig)
}
conv.BigInt2BytesLe(want[:], t)
if got != want {
fmt.Printf("in: %v\n", conv.BytesLe2BigInt(data[:2*Size]))
fmt.Printf("got: %v\n", got)
fmt.Printf("want: %v\n", want)
panic("error found")
}
return 1
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/mlsbset/mlsbset.go
================================================
// Package mlsbset provides a constant-time exponentiation method with precomputation.
//
// References: "Efficient and secure algorithms for GLV-based scalar
// multiplication and their implementation on GLV–GLS curves" by (Faz-Hernandez et al.)
// - https://doi.org/10.1007/s13389-014-0085-7
// - https://eprint.iacr.org/2013/158
package mlsbset
import (
"errors"
"fmt"
"math/big"
"github.com/cloudflare/circl/internal/conv"
)
// EltG is a group element.
type EltG interface{}
// EltP is a precomputed group element.
type EltP interface{}
// Group defines the operations required by MLSBSet exponentiation method.
type Group interface {
Identity() EltG // Returns the identity of the group.
Sqr(x EltG) // Calculates x = x^2.
Mul(x EltG, y EltP) // Calculates x = x*y.
NewEltP() EltP // Returns an arbitrary precomputed element.
ExtendedEltP() EltP // Returns the precomputed element x^(2^(w*d)).
Lookup(a EltP, v uint, s, u int32) // Sets a = s*T[v][u].
}
// Params contains the parameters of the encoding.
type Params struct {
T uint // T is the maximum size (in bits) of exponents.
V uint // V is the number of tables.
W uint // W is the window size.
E uint // E is the number of digits per table.
D uint // D is the number of digits in total.
L uint // L is the length of the code.
}
// Encoder allows to convert integers into valid powers.
type Encoder struct{ p Params }
// New produces an encoder of the MLSBSet algorithm.
func New(t, v, w uint) (Encoder, error) {
if !(t > 1 && v >= 1 && w >= 2) {
return Encoder{}, errors.New("t>1, v>=1, w>=2")
}
e := (t + w*v - 1) / (w * v)
d := e * v
l := d * w
return Encoder{Params{t, v, w, e, d, l}}, nil
}
// Encode converts an odd integer k into a valid power for exponentiation.
func (m Encoder) Encode(k []byte) (*Power, error) {
if len(k) == 0 {
return nil, errors.New("empty slice")
}
if !(len(k) <= int(m.p.L+7)>>3) {
return nil, errors.New("k too big")
}
if k[0]%2 == 0 {
return nil, errors.New("k must be odd")
}
ap := int((m.p.L+7)/8) - len(k)
k = append(k, make([]byte, ap)...)
s := m.signs(k)
b := make([]int32, m.p.L-m.p.D)
c := conv.BytesLe2BigInt(k)
c.Rsh(c, m.p.D)
var bi big.Int
for i := m.p.D; i < m.p.L; i++ {
c0 := int32(c.Bit(0))
b[i-m.p.D] = s[i%m.p.D] * c0
bi.SetInt64(int64(b[i-m.p.D] >> 1))
c.Rsh(c, 1)
c.Sub(c, &bi)
}
carry := int(c.Int64())
return &Power{m, s, b, carry}, nil
}
// signs calculates the set of signs.
func (m Encoder) signs(k []byte) []int32 {
s := make([]int32, m.p.D)
s[m.p.D-1] = 1
for i := uint(1); i < m.p.D; i++ {
ki := int32((k[i>>3] >> (i & 0x7)) & 0x1)
s[i-1] = 2*ki - 1
}
return s
}
// GetParams returns the complementary parameters of the encoding.
func (m Encoder) GetParams() Params { return m.p }
// tableSize returns the size of each table.
func (m Encoder) tableSize() uint { return 1 << (m.p.W - 1) }
// Elts returns the total number of elements that must be precomputed.
func (m Encoder) Elts() uint { return m.p.V * m.tableSize() }
// IsExtended returns true if the element x^(2^(wd)) must be calculated.
func (m Encoder) IsExtended() bool { q := m.p.T / (m.p.V * m.p.W); return m.p.T == q*m.p.V*m.p.W }
// Ops returns the number of squares and multiplications executed during an exponentiation.
func (m Encoder) Ops() (S uint, M uint) {
S = m.p.E
M = m.p.E * m.p.V
if m.IsExtended() {
M++
}
return
}
func (m Encoder) String() string {
return fmt.Sprintf("T: %v W: %v V: %v e: %v d: %v l: %v wv|t: %v",
m.p.T, m.p.W, m.p.V, m.p.E, m.p.D, m.p.L, m.IsExtended())
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/mlsbset/power.go
================================================
package mlsbset
import "fmt"
// Power is a valid exponent produced by the MLSBSet encoding algorithm.
type Power struct {
set Encoder // parameters of code.
s []int32 // set of signs.
b []int32 // set of digits.
c int // carry is {0,1}.
}
// Exp is calculates x^k, where x is a predetermined element of a group G.
func (p *Power) Exp(G Group) EltG {
a, b := G.Identity(), G.NewEltP()
for e := int(p.set.p.E - 1); e >= 0; e-- {
G.Sqr(a)
for v := uint(0); v < p.set.p.V; v++ {
sgnElt, idElt := p.Digit(v, uint(e))
G.Lookup(b, v, sgnElt, idElt)
G.Mul(a, b)
}
}
if p.set.IsExtended() && p.c == 1 {
G.Mul(a, G.ExtendedEltP())
}
return a
}
// Digit returns the (v,e)-th digit and its sign.
func (p *Power) Digit(v, e uint) (sgn, dig int32) {
sgn = p.bit(0, v, e)
dig = 0
for i := p.set.p.W - 1; i > 0; i-- {
dig = 2*dig + p.bit(i, v, e)
}
mask := dig >> 31
dig = (dig + mask) ^ mask
return sgn, dig
}
// bit returns the (w,v,e)-th bit of the code.
func (p *Power) bit(w, v, e uint) int32 {
if !(w < p.set.p.W &&
v < p.set.p.V &&
e < p.set.p.E) {
panic(fmt.Errorf("indexes outside (%v,%v,%v)", w, v, e))
}
if w == 0 {
return p.s[p.set.p.E*v+e]
}
return p.b[p.set.p.D*(w-1)+p.set.p.E*v+e]
}
func (p *Power) String() string {
dig := ""
for j := uint(0); j < p.set.p.V; j++ {
for i := uint(0); i < p.set.p.E; i++ {
s, d := p.Digit(j, i)
dig += fmt.Sprintf("(%2v,%2v) = %+2v %+2v\n", j, i, s, d)
}
}
return fmt.Sprintf("len: %v\ncarry: %v\ndigits:\n%v", len(p.b)+len(p.s), p.c, dig)
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/primes.go
================================================
package math
import (
"crypto/rand"
"io"
"math/big"
)
// IsSafePrime reports whether p is (probably) a safe prime.
// The prime p=2*q+1 is safe prime if both p and q are primes.
// Note that ProbablyPrime is not suitable for judging primes
// that an adversary may have crafted to fool the test.
func IsSafePrime(p *big.Int) bool {
pdiv2 := new(big.Int).Rsh(p, 1)
return p.ProbablyPrime(20) && pdiv2.ProbablyPrime(20)
}
// SafePrime returns a number of the given bit length that is a safe prime with high probability.
// The number returned p=2*q+1 is a safe prime if both p and q are primes.
// SafePrime will return error for any error returned by rand.Read or if bits < 2.
func SafePrime(random io.Reader, bits int) (*big.Int, error) {
one := big.NewInt(1)
p := new(big.Int)
for {
q, err := rand.Prime(random, bits-1)
if err != nil {
return nil, err
}
p.Lsh(q, 1).Add(p, one)
if p.ProbablyPrime(20) {
return p, nil
}
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/math/wnaf.go
================================================
// Package math provides some utility functions for big integers.
package math
import "math/big"
// SignedDigit obtains the signed-digit recoding of n and returns a list L of
// digits such that n = sum( L[i]*2^(i*(w-1)) ), and each L[i] is an odd number
// in the set {±1, ±3, ..., ±2^(w-1)-1}. The third parameter ensures that the
// output has ceil(l/(w-1)) digits.
//
// Restrictions:
// - n is odd and n > 0.
// - 1 < w < 32.
// - l >= bit length of n.
//
// References:
// - Alg.6 in "Exponent Recoding and Regular Exponentiation Algorithms"
// by Joye-Tunstall. http://doi.org/10.1007/978-3-642-02384-2_21
// - Alg.6 in "Selecting Elliptic Curves for Cryptography: An Efficiency and
// Security Analysis" by Bos et al. http://doi.org/10.1007/s13389-015-0097-y
func SignedDigit(n *big.Int, w, l uint) []int32 {
if n.Sign() <= 0 || n.Bit(0) == 0 {
panic("n must be non-zero, odd, and positive")
}
if w <= 1 || w >= 32 {
panic("Verify that 1 < w < 32")
}
if uint(n.BitLen()) > l {
panic("n is too big to fit in l digits")
}
lenN := (l + (w - 1) - 1) / (w - 1) // ceil(l/(w-1))
L := make([]int32, lenN+1)
var k, v big.Int
k.Set(n)
var i uint
for i = 0; i < lenN; i++ {
words := k.Bits()
value := int32(words[0] & ((1 << w) - 1))
value -= int32(1) << (w - 1)
L[i] = value
v.SetInt64(int64(value))
k.Sub(&k, &v)
k.Rsh(&k, w-1)
}
L[i] = int32(k.Int64())
return L
}
// OmegaNAF obtains the window-w Non-Adjacent Form of a positive number n and
// 1 < w < 32. The returned slice L holds n = sum( L[i]*2^i ).
//
// Reference:
// - Alg.9 "Efficient arithmetic on Koblitz curves" by Solinas.
// http://doi.org/10.1023/A:1008306223194
func OmegaNAF(n *big.Int, w uint) (L []int32) {
if n.Sign() < 0 {
panic("n must be positive")
}
if w <= 1 || w >= 32 {
panic("Verify that 1 < w < 32")
}
L = make([]int32, n.BitLen()+1)
var k, v big.Int
k.Set(n)
i := 0
for ; k.Sign() > 0; i++ {
value := int32(0)
if k.Bit(0) == 1 {
words := k.Bits()
value = int32(words[0] & ((1 << w) - 1))
if value >= (int32(1) << (w - 1)) {
value -= int32(1) << w
}
v.SetInt64(int64(value))
k.Sub(&k, &v)
}
L[i] = value
k.Rsh(&k, 1)
}
return L[:i]
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/ed25519.go
================================================
// Package ed25519 implements Ed25519 signature scheme as described in RFC-8032.
//
// This package provides optimized implementations of the three signature
// variants and maintaining closer compatibility with crypto/ed25519.
//
// | Scheme Name | Sign Function | Verification | Context |
// |-------------|-------------------|---------------|-------------------|
// | Ed25519 | Sign | Verify | None |
// | Ed25519Ph | SignPh | VerifyPh | Yes, can be empty |
// | Ed25519Ctx | SignWithCtx | VerifyWithCtx | Yes, non-empty |
// | All above | (PrivateKey).Sign | VerifyAny | As above |
//
// Specific functions for sign and verify are defined. A generic signing
// function for all schemes is available through the crypto.Signer interface,
// which is implemented by the PrivateKey type. A correspond all-in-one
// verification method is provided by the VerifyAny function.
//
// Signing with Ed25519Ph or Ed25519Ctx requires a context string for domain
// separation. This parameter is passed using a SignerOptions struct defined
// in this package. While Ed25519Ph accepts an empty context, Ed25519Ctx
// enforces non-empty context strings.
//
// # Compatibility with crypto.ed25519
//
// These functions are compatible with the “Ed25519” function defined in
// RFC-8032. However, unlike RFC 8032's formulation, this package's private
// key representation includes a public key suffix to make multiple signing
// operations with the same key more efficient. This package refers to the
// RFC-8032 private key as the “seed”.
//
// References
//
// - RFC-8032: https://rfc-editor.org/rfc/rfc8032.txt
// - Ed25519: https://ed25519.cr.yp.to/
// - EdDSA: High-speed high-security signatures. https://doi.org/10.1007/s13389-012-0027-1
package ed25519
import (
"bytes"
"crypto"
cryptoRand "crypto/rand"
"crypto/sha512"
"crypto/subtle"
"errors"
"fmt"
"io"
"strconv"
"github.com/cloudflare/circl/sign"
)
const (
// ContextMaxSize is the maximum length (in bytes) allowed for context.
ContextMaxSize = 255
// PublicKeySize is the size, in bytes, of public keys as used in this package.
PublicKeySize = 32
// PrivateKeySize is the size, in bytes, of private keys as used in this package.
PrivateKeySize = 64
// SignatureSize is the size, in bytes, of signatures generated and verified by this package.
SignatureSize = 64
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 32
)
const (
paramB = 256 / 8 // Size of keys in bytes.
)
// SignerOptions implements crypto.SignerOpts and augments with parameters
// that are specific to the Ed25519 signature schemes.
type SignerOptions struct {
// Hash must be crypto.Hash(0) for Ed25519/Ed25519ctx, or crypto.SHA512
// for Ed25519ph.
crypto.Hash
// Context is an optional domain separation string for Ed25519ph and a
// must for Ed25519ctx. Its length must be less or equal than 255 bytes.
Context string
// Scheme is an identifier for choosing a signature scheme. The zero value
// is ED25519.
Scheme SchemeID
}
// SchemeID is an identifier for each signature scheme.
type SchemeID uint
const (
ED25519 SchemeID = iota
ED25519Ph
ED25519Ctx
)
// PrivateKey is the type of Ed25519 private keys. It implements crypto.Signer.
type PrivateKey []byte
// Equal reports whether priv and x have the same value.
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
xx, ok := x.(PrivateKey)
return ok && subtle.ConstantTimeCompare(priv, xx) == 1
}
// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, priv[SeedSize:])
return publicKey
}
// Seed returns the private key seed corresponding to priv. It is provided for
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
// in this package.
func (priv PrivateKey) Seed() []byte {
seed := make([]byte, SeedSize)
copy(seed, priv[:SeedSize])
return seed
}
func (priv PrivateKey) Scheme() sign.Scheme { return sch }
func (pub PublicKey) Scheme() sign.Scheme { return sch }
func (priv PrivateKey) MarshalBinary() (data []byte, err error) {
privateKey := make(PrivateKey, PrivateKeySize)
copy(privateKey, priv)
return privateKey, nil
}
func (pub PublicKey) MarshalBinary() (data []byte, err error) {
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, pub)
return publicKey, nil
}
// Equal reports whether pub and x have the same value.
func (pub PublicKey) Equal(x crypto.PublicKey) bool {
xx, ok := x.(PublicKey)
return ok && bytes.Equal(pub, xx)
}
// Sign creates a signature of a message with priv key.
// This function is compatible with crypto.ed25519 and also supports the
// three signature variants defined in RFC-8032, namely Ed25519 (or pure
// EdDSA), Ed25519Ph, and Ed25519Ctx.
// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx
// variant. This can be achieved by passing crypto.Hash(0) as the value for
// opts.
// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant.
// This can be achieved by passing crypto.SHA512 as the value for opts.
// Use a SignerOptions struct (defined in this package) to pass a context
// string for signing.
func (priv PrivateKey) Sign(
rand io.Reader,
message []byte,
opts crypto.SignerOpts,
) (signature []byte, err error) {
var ctx string
var scheme SchemeID
if o, ok := opts.(SignerOptions); ok {
ctx = o.Context
scheme = o.Scheme
}
switch true {
case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0):
return Sign(priv, message), nil
case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512:
return SignPh(priv, message, ctx), nil
case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0:
return SignWithCtx(priv, message, ctx), nil
default:
return nil, errors.New("ed25519: bad hash algorithm")
}
}
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptoRand.Reader
}
seed := make([]byte, SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
return nil, nil, err
}
privateKey := NewKeyFromSeed(seed)
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, privateKey[SeedSize:])
return publicKey, privateKey, nil
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
privateKey := make(PrivateKey, PrivateKeySize)
newKeyFromSeed(privateKey, seed)
return privateKey
}
func newKeyFromSeed(privateKey, seed []byte) {
if l := len(seed); l != SeedSize {
panic("ed25519: bad seed length: " + strconv.Itoa(l))
}
var P pointR1
k := sha512.Sum512(seed)
clamp(k[:])
reduceModOrder(k[:paramB], false)
P.fixedMult(k[:paramB])
copy(privateKey[:SeedSize], seed)
_ = P.ToBytes(privateKey[SeedSize:])
}
func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) {
if l := len(privateKey); l != PrivateKeySize {
panic("ed25519: bad private key length: " + strconv.Itoa(l))
}
H := sha512.New()
var PHM []byte
if preHash {
_, _ = H.Write(message)
PHM = H.Sum(nil)
H.Reset()
} else {
PHM = message
}
// 1. Hash the 32-byte private key using SHA-512.
_, _ = H.Write(privateKey[:SeedSize])
h := H.Sum(nil)
clamp(h[:])
prefix, s := h[paramB:], h[:paramB]
// 2. Compute SHA-512(dom2(F, C) || prefix || PH(M))
H.Reset()
writeDom(H, ctx, preHash)
_, _ = H.Write(prefix)
_, _ = H.Write(PHM)
r := H.Sum(nil)
reduceModOrder(r[:], true)
// 3. Compute the point [r]B.
var P pointR1
P.fixedMult(r[:paramB])
R := (&[paramB]byte{})[:]
if err := P.ToBytes(R); err != nil {
panic(err)
}
// 4. Compute SHA512(dom2(F, C) || R || A || PH(M)).
H.Reset()
writeDom(H, ctx, preHash)
_, _ = H.Write(R)
_, _ = H.Write(privateKey[SeedSize:])
_, _ = H.Write(PHM)
hRAM := H.Sum(nil)
reduceModOrder(hRAM[:], true)
// 5. Compute S = (r + k * s) mod order.
S := (&[paramB]byte{})[:]
calculateS(S, r[:paramB], hRAM[:paramB], s)
// 6. The signature is the concatenation of R and S.
copy(signature[:paramB], R[:])
copy(signature[paramB:], S[:])
}
// Sign signs the message with privateKey and returns a signature.
// This function supports the signature variant defined in RFC-8032: Ed25519,
// also known as the pure version of EdDSA.
// It will panic if len(privateKey) is not PrivateKeySize.
func Sign(privateKey PrivateKey, message []byte) []byte {
signature := make([]byte, SignatureSize)
signAll(signature, privateKey, message, []byte(""), false)
return signature
}
// SignPh creates a signature of a message with private key and context.
// This function supports the signature variant defined in RFC-8032: Ed25519ph,
// meaning it internally hashes the message using SHA-512, and optionally
// accepts a context string.
// It will panic if len(privateKey) is not PrivateKeySize.
// Context could be passed to this function, which length should be no more than
// ContextMaxSize=255. It can be empty.
func SignPh(privateKey PrivateKey, message []byte, ctx string) []byte {
if len(ctx) > ContextMaxSize {
panic(fmt.Errorf("ed25519: bad context length: %v", len(ctx)))
}
signature := make([]byte, SignatureSize)
signAll(signature, privateKey, message, []byte(ctx), true)
return signature
}
// SignWithCtx creates a signature of a message with private key and context.
// This function supports the signature variant defined in RFC-8032: Ed25519ctx,
// meaning it accepts a non-empty context string.
// It will panic if len(privateKey) is not PrivateKeySize.
// Context must be passed to this function, which length should be no more than
// ContextMaxSize=255 and cannot be empty.
func SignWithCtx(privateKey PrivateKey, message []byte, ctx string) []byte {
if len(ctx) == 0 || len(ctx) > ContextMaxSize {
panic(fmt.Errorf("ed25519: bad context length: %v > %v", len(ctx), ContextMaxSize))
}
signature := make([]byte, SignatureSize)
signAll(signature, privateKey, message, []byte(ctx), false)
return signature
}
func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool {
if len(public) != PublicKeySize ||
len(signature) != SignatureSize ||
!isLessThanOrder(signature[paramB:]) {
return false
}
var P pointR1
if ok := P.FromBytes(public); !ok {
return false
}
H := sha512.New()
var PHM []byte
if preHash {
_, _ = H.Write(message)
PHM = H.Sum(nil)
H.Reset()
} else {
PHM = message
}
R := signature[:paramB]
writeDom(H, ctx, preHash)
_, _ = H.Write(R)
_, _ = H.Write(public)
_, _ = H.Write(PHM)
hRAM := H.Sum(nil)
reduceModOrder(hRAM[:], true)
var Q pointR1
encR := (&[paramB]byte{})[:]
P.neg()
Q.doubleMult(&P, signature[paramB:], hRAM[:paramB])
_ = Q.ToBytes(encR)
return bytes.Equal(R, encR)
}
// VerifyAny returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports all the three signature variants defined in RFC-8032,
// namely Ed25519 (or pure EdDSA), Ed25519Ph, and Ed25519Ctx.
// The opts.HashFunc() must return zero to specify either Ed25519 or Ed25519Ctx
// variant. This can be achieved by passing crypto.Hash(0) as the value for opts.
// The opts.HashFunc() must return SHA512 to specify the Ed25519Ph variant.
// This can be achieved by passing crypto.SHA512 as the value for opts.
// Use a SignerOptions struct to pass a context string for signing.
func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool {
var ctx string
var scheme SchemeID
if o, ok := opts.(SignerOptions); ok {
ctx = o.Context
scheme = o.Scheme
}
switch true {
case scheme == ED25519 && opts.HashFunc() == crypto.Hash(0):
return Verify(public, message, signature)
case scheme == ED25519Ph && opts.HashFunc() == crypto.SHA512:
return VerifyPh(public, message, signature, ctx)
case scheme == ED25519Ctx && opts.HashFunc() == crypto.Hash(0) && len(ctx) > 0:
return VerifyWithCtx(public, message, signature, ctx)
default:
return false
}
}
// Verify returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports the signature variant defined in RFC-8032: Ed25519,
// also known as the pure version of EdDSA.
func Verify(public PublicKey, message, signature []byte) bool {
return verify(public, message, signature, []byte(""), false)
}
// VerifyPh returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports the signature variant defined in RFC-8032: Ed25519ph,
// meaning it internally hashes the message using SHA-512.
// Context could be passed to this function, which length should be no more than
// 255. It can be empty.
func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool {
return verify(public, message, signature, []byte(ctx), true)
}
// VerifyWithCtx returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded, or when context is
// not provided.
// This function supports the signature variant defined in RFC-8032: Ed25519ctx,
// meaning it does not handle prehashed messages. Non-empty context string must be
// provided, and must not be more than 255 of length.
func VerifyWithCtx(public PublicKey, message, signature []byte, ctx string) bool {
if len(ctx) == 0 || len(ctx) > ContextMaxSize {
return false
}
return verify(public, message, signature, []byte(ctx), false)
}
func clamp(k []byte) {
k[0] &= 248
k[paramB-1] = (k[paramB-1] & 127) | 64
}
// isLessThanOrder returns true if 0 <= x < order.
func isLessThanOrder(x []byte) bool {
i := len(order) - 1
for i > 0 && x[i] == order[i] {
i--
}
return x[i] < order[i]
}
func writeDom(h io.Writer, ctx []byte, preHash bool) {
dom2 := "SigEd25519 no Ed25519 collisions"
if len(ctx) > 0 {
_, _ = h.Write([]byte(dom2))
if preHash {
_, _ = h.Write([]byte{byte(0x01), byte(len(ctx))})
} else {
_, _ = h.Write([]byte{byte(0x00), byte(len(ctx))})
}
_, _ = h.Write(ctx)
} else if preHash {
_, _ = h.Write([]byte(dom2))
_, _ = h.Write([]byte{0x01, 0x00})
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/modular.go
================================================
package ed25519
import (
"encoding/binary"
"math/bits"
)
var order = [paramB]byte{
0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
}
// isLessThan returns true if 0 <= x < y, and assumes that slices have the same length.
func isLessThan(x, y []byte) bool {
i := len(x) - 1
for i > 0 && x[i] == y[i] {
i--
}
return x[i] < y[i]
}
// reduceModOrder calculates k = k mod order of the curve.
func reduceModOrder(k []byte, is512Bit bool) {
var X [((2 * paramB) * 8) / 64]uint64
numWords := len(k) >> 3
for i := 0; i < numWords; i++ {
X[i] = binary.LittleEndian.Uint64(k[i*8 : (i+1)*8])
}
red512(&X, is512Bit)
for i := 0; i < numWords; i++ {
binary.LittleEndian.PutUint64(k[i*8:(i+1)*8], X[i])
}
}
// red512 calculates x = x mod Order of the curve.
func red512(x *[8]uint64, full bool) {
// Implementation of Algs.(14.47)+(14.52) of Handbook of Applied
// Cryptography, by A. Menezes, P. van Oorschot, and S. Vanstone.
const (
ell0 = uint64(0x5812631a5cf5d3ed)
ell1 = uint64(0x14def9dea2f79cd6)
ell160 = uint64(0x812631a5cf5d3ed0)
ell161 = uint64(0x4def9dea2f79cd65)
ell162 = uint64(0x0000000000000001)
)
var c0, c1, c2, c3 uint64
r0, r1, r2, r3, r4 := x[0], x[1], x[2], x[3], uint64(0)
if full {
q0, q1, q2, q3 := x[4], x[5], x[6], x[7]
for i := 0; i < 3; i++ {
h0, s0 := bits.Mul64(q0, ell160)
h1, s1 := bits.Mul64(q1, ell160)
h2, s2 := bits.Mul64(q2, ell160)
h3, s3 := bits.Mul64(q3, ell160)
s1, c0 = bits.Add64(h0, s1, 0)
s2, c1 = bits.Add64(h1, s2, c0)
s3, c2 = bits.Add64(h2, s3, c1)
s4, _ := bits.Add64(h3, 0, c2)
h0, l0 := bits.Mul64(q0, ell161)
h1, l1 := bits.Mul64(q1, ell161)
h2, l2 := bits.Mul64(q2, ell161)
h3, l3 := bits.Mul64(q3, ell161)
l1, c0 = bits.Add64(h0, l1, 0)
l2, c1 = bits.Add64(h1, l2, c0)
l3, c2 = bits.Add64(h2, l3, c1)
l4, _ := bits.Add64(h3, 0, c2)
s1, c0 = bits.Add64(s1, l0, 0)
s2, c1 = bits.Add64(s2, l1, c0)
s3, c2 = bits.Add64(s3, l2, c1)
s4, c3 = bits.Add64(s4, l3, c2)
s5, s6 := bits.Add64(l4, 0, c3)
s2, c0 = bits.Add64(s2, q0, 0)
s3, c1 = bits.Add64(s3, q1, c0)
s4, c2 = bits.Add64(s4, q2, c1)
s5, c3 = bits.Add64(s5, q3, c2)
s6, s7 := bits.Add64(s6, 0, c3)
q := q0 | q1 | q2 | q3
m := -((q | -q) >> 63) // if q=0 then m=0...0 else m=1..1
s0 &= m
s1 &= m
s2 &= m
s3 &= m
q0, q1, q2, q3 = s4, s5, s6, s7
if (i+1)%2 == 0 {
r0, c0 = bits.Add64(r0, s0, 0)
r1, c1 = bits.Add64(r1, s1, c0)
r2, c2 = bits.Add64(r2, s2, c1)
r3, c3 = bits.Add64(r3, s3, c2)
r4, _ = bits.Add64(r4, 0, c3)
} else {
r0, c0 = bits.Sub64(r0, s0, 0)
r1, c1 = bits.Sub64(r1, s1, c0)
r2, c2 = bits.Sub64(r2, s2, c1)
r3, c3 = bits.Sub64(r3, s3, c2)
r4, _ = bits.Sub64(r4, 0, c3)
}
}
m := -(r4 >> 63)
r0, c0 = bits.Add64(r0, m&ell160, 0)
r1, c1 = bits.Add64(r1, m&ell161, c0)
r2, c2 = bits.Add64(r2, m&ell162, c1)
r3, c3 = bits.Add64(r3, 0, c2)
r4, _ = bits.Add64(r4, m&1, c3)
x[4], x[5], x[6], x[7] = 0, 0, 0, 0
}
q0 := (r4 << 4) | (r3 >> 60)
r3 &= (uint64(1) << 60) - 1
h0, s0 := bits.Mul64(ell0, q0)
h1, s1 := bits.Mul64(ell1, q0)
s1, c0 = bits.Add64(h0, s1, 0)
s2, _ := bits.Add64(h1, 0, c0)
r0, c0 = bits.Sub64(r0, s0, 0)
r1, c1 = bits.Sub64(r1, s1, c0)
r2, c2 = bits.Sub64(r2, s2, c1)
r3, _ = bits.Sub64(r3, 0, c2)
x[0], x[1], x[2], x[3] = r0, r1, r2, r3
}
// calculateS performs s = r+k*a mod Order of the curve.
func calculateS(s, r, k, a []byte) {
K := [4]uint64{
binary.LittleEndian.Uint64(k[0*8 : 1*8]),
binary.LittleEndian.Uint64(k[1*8 : 2*8]),
binary.LittleEndian.Uint64(k[2*8 : 3*8]),
binary.LittleEndian.Uint64(k[3*8 : 4*8]),
}
S := [8]uint64{
binary.LittleEndian.Uint64(r[0*8 : 1*8]),
binary.LittleEndian.Uint64(r[1*8 : 2*8]),
binary.LittleEndian.Uint64(r[2*8 : 3*8]),
binary.LittleEndian.Uint64(r[3*8 : 4*8]),
}
var c3 uint64
for i := range K {
ai := binary.LittleEndian.Uint64(a[i*8 : (i+1)*8])
h0, l0 := bits.Mul64(K[0], ai)
h1, l1 := bits.Mul64(K[1], ai)
h2, l2 := bits.Mul64(K[2], ai)
h3, l3 := bits.Mul64(K[3], ai)
l1, c0 := bits.Add64(h0, l1, 0)
l2, c1 := bits.Add64(h1, l2, c0)
l3, c2 := bits.Add64(h2, l3, c1)
l4, _ := bits.Add64(h3, 0, c2)
S[i+0], c0 = bits.Add64(S[i+0], l0, 0)
S[i+1], c1 = bits.Add64(S[i+1], l1, c0)
S[i+2], c2 = bits.Add64(S[i+2], l2, c1)
S[i+3], c3 = bits.Add64(S[i+3], l3, c2)
S[i+4], _ = bits.Add64(S[i+4], l4, c3)
}
red512(&S, true)
binary.LittleEndian.PutUint64(s[0*8:1*8], S[0])
binary.LittleEndian.PutUint64(s[1*8:2*8], S[1])
binary.LittleEndian.PutUint64(s[2*8:3*8], S[2])
binary.LittleEndian.PutUint64(s[3*8:4*8], S[3])
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/mult.go
================================================
package ed25519
import (
"crypto/subtle"
"encoding/binary"
"math/bits"
"github.com/cloudflare/circl/internal/conv"
"github.com/cloudflare/circl/math"
fp "github.com/cloudflare/circl/math/fp25519"
)
var paramD = fp.Elt{
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52,
}
// mLSBRecoding parameters.
const (
fxT = 257
fxV = 2
fxW = 3
fx2w1 = 1 << (uint(fxW) - 1)
numWords64 = (paramB * 8 / 64)
)
// mLSBRecoding is the odd-only modified LSB-set.
//
// Reference:
//
// "Efficient and secure algorithms for GLV-based scalar multiplication and
// their implementation on GLV–GLS curves" by (Faz-Hernandez et al.)
// http://doi.org/10.1007/s13389-014-0085-7.
func mLSBRecoding(L []int8, k []byte) {
const ee = (fxT + fxW*fxV - 1) / (fxW * fxV)
const dd = ee * fxV
const ll = dd * fxW
if len(L) == (ll + 1) {
var m [numWords64 + 1]uint64
for i := 0; i < numWords64; i++ {
m[i] = binary.LittleEndian.Uint64(k[8*i : 8*i+8])
}
condAddOrderN(&m)
L[dd-1] = 1
for i := 0; i < dd-1; i++ {
kip1 := (m[(i+1)/64] >> (uint(i+1) % 64)) & 0x1
L[i] = int8(kip1<<1) - 1
}
{ // right-shift by d
right := uint(dd % 64)
left := uint(64) - right
lim := ((numWords64+1)*64 - dd) / 64
j := dd / 64
for i := 0; i < lim; i++ {
m[i] = (m[i+j] >> right) | (m[i+j+1] << left)
}
m[lim] = m[lim+j] >> right
}
for i := dd; i < ll; i++ {
L[i] = L[i%dd] * int8(m[0]&0x1)
div2subY(m[:], int64(L[i]>>1), numWords64)
}
L[ll] = int8(m[0])
}
}
// absolute returns always a positive value.
func absolute(x int32) int32 {
mask := x >> 31
return (x + mask) ^ mask
}
// condAddOrderN updates x = x+order if x is even, otherwise x remains unchanged.
func condAddOrderN(x *[numWords64 + 1]uint64) {
isOdd := (x[0] & 0x1) - 1
c := uint64(0)
for i := 0; i < numWords64; i++ {
orderWord := binary.LittleEndian.Uint64(order[8*i : 8*i+8])
o := isOdd & orderWord
x0, c0 := bits.Add64(x[i], o, c)
x[i] = x0
c = c0
}
x[numWords64], _ = bits.Add64(x[numWords64], 0, c)
}
// div2subY update x = (x/2) - y.
func div2subY(x []uint64, y int64, l int) {
s := uint64(y >> 63)
for i := 0; i < l-1; i++ {
x[i] = (x[i] >> 1) | (x[i+1] << 63)
}
x[l-1] = (x[l-1] >> 1)
b := uint64(0)
x0, b0 := bits.Sub64(x[0], uint64(y), b)
x[0] = x0
b = b0
for i := 1; i < l-1; i++ {
x0, b0 := bits.Sub64(x[i], s, b)
x[i] = x0
b = b0
}
x[l-1], _ = bits.Sub64(x[l-1], s, b)
}
func (P *pointR1) fixedMult(scalar []byte) {
if len(scalar) != paramB {
panic("wrong scalar size")
}
const ee = (fxT + fxW*fxV - 1) / (fxW * fxV)
const dd = ee * fxV
const ll = dd * fxW
L := make([]int8, ll+1)
mLSBRecoding(L[:], scalar)
S := &pointR3{}
P.SetIdentity()
for ii := ee - 1; ii >= 0; ii-- {
P.double()
for j := 0; j < fxV; j++ {
dig := L[fxW*dd-j*ee+ii-ee]
for i := (fxW-1)*dd - j*ee + ii - ee; i >= (2*dd - j*ee + ii - ee); i = i - dd {
dig = 2*dig + L[i]
}
idx := absolute(int32(dig))
sig := L[dd-j*ee+ii-ee]
Tabj := &tabSign[fxV-j-1]
for k := 0; k < fx2w1; k++ {
S.cmov(&Tabj[k], subtle.ConstantTimeEq(int32(k), idx))
}
S.cneg(subtle.ConstantTimeEq(int32(sig), -1))
P.mixAdd(S)
}
}
}
const (
omegaFix = 7
omegaVar = 5
)
// doubleMult returns P=mG+nQ.
func (P *pointR1) doubleMult(Q *pointR1, m, n []byte) {
nafFix := math.OmegaNAF(conv.BytesLe2BigInt(m), omegaFix)
nafVar := math.OmegaNAF(conv.BytesLe2BigInt(n), omegaVar)
if len(nafFix) > len(nafVar) {
nafVar = append(nafVar, make([]int32, len(nafFix)-len(nafVar))...)
} else if len(nafFix) < len(nafVar) {
nafFix = append(nafFix, make([]int32, len(nafVar)-len(nafFix))...)
}
var TabQ [1 << (omegaVar - 2)]pointR2
Q.oddMultiples(TabQ[:])
P.SetIdentity()
for i := len(nafFix) - 1; i >= 0; i-- {
P.double()
// Generator point
if nafFix[i] != 0 {
idxM := absolute(nafFix[i]) >> 1
R := tabVerif[idxM]
if nafFix[i] < 0 {
R.neg()
}
P.mixAdd(&R)
}
// Variable input point
if nafVar[i] != 0 {
idxN := absolute(nafVar[i]) >> 1
S := TabQ[idxN]
if nafVar[i] < 0 {
S.neg()
}
P.add(&S)
}
}
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/point.go
================================================
package ed25519
import fp "github.com/cloudflare/circl/math/fp25519"
type (
pointR1 struct{ x, y, z, ta, tb fp.Elt }
pointR2 struct {
pointR3
z2 fp.Elt
}
)
type pointR3 struct{ addYX, subYX, dt2 fp.Elt }
func (P *pointR1) neg() {
fp.Neg(&P.x, &P.x)
fp.Neg(&P.ta, &P.ta)
}
func (P *pointR1) SetIdentity() {
P.x = fp.Elt{}
fp.SetOne(&P.y)
fp.SetOne(&P.z)
P.ta = fp.Elt{}
P.tb = fp.Elt{}
}
func (P *pointR1) toAffine() {
fp.Inv(&P.z, &P.z)
fp.Mul(&P.x, &P.x, &P.z)
fp.Mul(&P.y, &P.y, &P.z)
fp.Modp(&P.x)
fp.Modp(&P.y)
fp.SetOne(&P.z)
P.ta = P.x
P.tb = P.y
}
func (P *pointR1) ToBytes(k []byte) error {
P.toAffine()
var x [fp.Size]byte
err := fp.ToBytes(k[:fp.Size], &P.y)
if err != nil {
return err
}
err = fp.ToBytes(x[:], &P.x)
if err != nil {
return err
}
b := x[0] & 1
k[paramB-1] = k[paramB-1] | (b << 7)
return nil
}
func (P *pointR1) FromBytes(k []byte) bool {
if len(k) != paramB {
panic("wrong size")
}
signX := k[paramB-1] >> 7
copy(P.y[:], k[:fp.Size])
P.y[fp.Size-1] &= 0x7F
p := fp.P()
if !isLessThan(P.y[:], p[:]) {
return false
}
one, u, v := &fp.Elt{}, &fp.Elt{}, &fp.Elt{}
fp.SetOne(one)
fp.Sqr(u, &P.y) // u = y^2
fp.Mul(v, u, ¶mD) // v = dy^2
fp.Sub(u, u, one) // u = y^2-1
fp.Add(v, v, one) // v = dy^2+1
isQR := fp.InvSqrt(&P.x, u, v) // x = sqrt(u/v)
if !isQR {
return false
}
fp.Modp(&P.x) // x = x mod p
if fp.IsZero(&P.x) && signX == 1 {
return false
}
if signX != (P.x[0] & 1) {
fp.Neg(&P.x, &P.x)
}
P.ta = P.x
P.tb = P.y
fp.SetOne(&P.z)
return true
}
// double calculates 2P for curves with A=-1.
func (P *pointR1) double() {
Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb
a, b, c, e, f, g, h := Px, Py, Pz, Pta, Px, Py, Ptb
fp.Add(e, Px, Py) // x+y
fp.Sqr(a, Px) // A = x^2
fp.Sqr(b, Py) // B = y^2
fp.Sqr(c, Pz) // z^2
fp.Add(c, c, c) // C = 2*z^2
fp.Add(h, a, b) // H = A+B
fp.Sqr(e, e) // (x+y)^2
fp.Sub(e, e, h) // E = (x+y)^2-A-B
fp.Sub(g, b, a) // G = B-A
fp.Sub(f, c, g) // F = C-G
fp.Mul(Pz, f, g) // Z = F * G
fp.Mul(Px, e, f) // X = E * F
fp.Mul(Py, g, h) // Y = G * H, T = E * H
}
func (P *pointR1) mixAdd(Q *pointR3) {
fp.Add(&P.z, &P.z, &P.z) // D = 2*z1
P.coreAddition(Q)
}
func (P *pointR1) add(Q *pointR2) {
fp.Mul(&P.z, &P.z, &Q.z2) // D = 2*z1*z2
P.coreAddition(&Q.pointR3)
}
// coreAddition calculates P=P+Q for curves with A=-1.
func (P *pointR1) coreAddition(Q *pointR3) {
Px, Py, Pz, Pta, Ptb := &P.x, &P.y, &P.z, &P.ta, &P.tb
addYX2, subYX2, dt2 := &Q.addYX, &Q.subYX, &Q.dt2
a, b, c, d, e, f, g, h := Px, Py, &fp.Elt{}, Pz, Pta, Px, Py, Ptb
fp.Mul(c, Pta, Ptb) // t1 = ta*tb
fp.Sub(h, Py, Px) // y1-x1
fp.Add(b, Py, Px) // y1+x1
fp.Mul(a, h, subYX2) // A = (y1-x1)*(y2-x2)
fp.Mul(b, b, addYX2) // B = (y1+x1)*(y2+x2)
fp.Mul(c, c, dt2) // C = 2*D*t1*t2
fp.Sub(e, b, a) // E = B-A
fp.Add(h, b, a) // H = B+A
fp.Sub(f, d, c) // F = D-C
fp.Add(g, d, c) // G = D+C
fp.Mul(Pz, f, g) // Z = F * G
fp.Mul(Px, e, f) // X = E * F
fp.Mul(Py, g, h) // Y = G * H, T = E * H
}
func (P *pointR1) oddMultiples(T []pointR2) {
var R pointR2
n := len(T)
T[0].fromR1(P)
_2P := *P
_2P.double()
R.fromR1(&_2P)
for i := 1; i < n; i++ {
P.add(&R)
T[i].fromR1(P)
}
}
func (P *pointR1) isEqual(Q *pointR1) bool {
l, r := &fp.Elt{}, &fp.Elt{}
fp.Mul(l, &P.x, &Q.z)
fp.Mul(r, &Q.x, &P.z)
fp.Sub(l, l, r)
b := fp.IsZero(l)
fp.Mul(l, &P.y, &Q.z)
fp.Mul(r, &Q.y, &P.z)
fp.Sub(l, l, r)
b = b && fp.IsZero(l)
fp.Mul(l, &P.ta, &P.tb)
fp.Mul(l, l, &Q.z)
fp.Mul(r, &Q.ta, &Q.tb)
fp.Mul(r, r, &P.z)
fp.Sub(l, l, r)
b = b && fp.IsZero(l)
return b
}
func (P *pointR3) neg() {
P.addYX, P.subYX = P.subYX, P.addYX
fp.Neg(&P.dt2, &P.dt2)
}
func (P *pointR2) fromR1(Q *pointR1) {
fp.Add(&P.addYX, &Q.y, &Q.x)
fp.Sub(&P.subYX, &Q.y, &Q.x)
fp.Mul(&P.dt2, &Q.ta, &Q.tb)
fp.Mul(&P.dt2, &P.dt2, ¶mD)
fp.Add(&P.dt2, &P.dt2, &P.dt2)
fp.Add(&P.z2, &Q.z, &Q.z)
}
func (P *pointR3) cneg(b int) {
t := &fp.Elt{}
fp.Cswap(&P.addYX, &P.subYX, uint(b))
fp.Neg(t, &P.dt2)
fp.Cmov(&P.dt2, t, uint(b))
}
func (P *pointR3) cmov(Q *pointR3, b int) {
fp.Cmov(&P.addYX, &Q.addYX, uint(b))
fp.Cmov(&P.subYX, &Q.subYX, uint(b))
fp.Cmov(&P.dt2, &Q.dt2, uint(b))
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/pubkey.go
================================================
//go:build go1.13
// +build go1.13
package ed25519
import cryptoEd25519 "crypto/ed25519"
// PublicKey is the type of Ed25519 public keys.
type PublicKey cryptoEd25519.PublicKey
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/pubkey112.go
================================================
//go:build !go1.13
// +build !go1.13
package ed25519
// PublicKey is the type of Ed25519 public keys.
type PublicKey []byte
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/signapi.go
================================================
package ed25519
import (
"crypto/rand"
"encoding/asn1"
"github.com/cloudflare/circl/sign"
)
var sch sign.Scheme = &scheme{}
// Scheme returns a signature interface.
func Scheme() sign.Scheme { return sch }
type scheme struct{}
func (*scheme) Name() string { return "Ed25519" }
func (*scheme) PublicKeySize() int { return PublicKeySize }
func (*scheme) PrivateKeySize() int { return PrivateKeySize }
func (*scheme) SignatureSize() int { return SignatureSize }
func (*scheme) SeedSize() int { return SeedSize }
func (*scheme) TLSIdentifier() uint { return 0x0807 }
func (*scheme) SupportsContext() bool { return false }
func (*scheme) Oid() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 101, 112}
}
func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) {
return GenerateKey(rand.Reader)
}
func (*scheme) Sign(
sk sign.PrivateKey,
message []byte,
opts *sign.SignatureOpts,
) []byte {
priv, ok := sk.(PrivateKey)
if !ok {
panic(sign.ErrTypeMismatch)
}
if opts != nil && opts.Context != "" {
panic(sign.ErrContextNotSupported)
}
return Sign(priv, message)
}
func (*scheme) Verify(
pk sign.PublicKey,
message, signature []byte,
opts *sign.SignatureOpts,
) bool {
pub, ok := pk.(PublicKey)
if !ok {
panic(sign.ErrTypeMismatch)
}
if opts != nil {
if opts.Context != "" {
panic(sign.ErrContextNotSupported)
}
}
return Verify(pub, message, signature)
}
func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) {
privateKey := NewKeyFromSeed(seed)
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, privateKey[SeedSize:])
return publicKey, privateKey
}
func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) {
if len(buf) < PublicKeySize {
return nil, sign.ErrPubKeySize
}
pub := make(PublicKey, PublicKeySize)
copy(pub, buf[:PublicKeySize])
return pub, nil
}
func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) {
if len(buf) < PrivateKeySize {
return nil, sign.ErrPrivKeySize
}
priv := make(PrivateKey, PrivateKeySize)
copy(priv, buf[:PrivateKeySize])
return priv, nil
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed25519/tables.go
================================================
package ed25519
import fp "github.com/cloudflare/circl/math/fp25519"
var tabSign = [fxV][fx2w1]pointR3{
{
pointR3{
addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07},
subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44},
dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f},
},
{
addYX: fp.Elt{0x7c, 0xb0, 0x9e, 0xe6, 0xc5, 0xbf, 0xfa, 0x13, 0x8e, 0x0d, 0x22, 0xde, 0xc8, 0xd1, 0xce, 0x52, 0x02, 0xd5, 0x62, 0x31, 0x71, 0x0e, 0x8e, 0x9d, 0xb0, 0xd6, 0x00, 0xa5, 0x5a, 0x0e, 0xce, 0x72},
subYX: fp.Elt{0x1a, 0x8e, 0x5c, 0xdc, 0xa4, 0xb3, 0x6c, 0x51, 0x18, 0xa0, 0x09, 0x80, 0x9a, 0x46, 0x33, 0xd5, 0xe0, 0x3c, 0x4d, 0x3b, 0xfc, 0x49, 0xa2, 0x43, 0x29, 0xe1, 0x29, 0xa9, 0x93, 0xea, 0x7c, 0x35},
dt2: fp.Elt{0x08, 0x46, 0x6f, 0x68, 0x7f, 0x0b, 0x7c, 0x9e, 0xad, 0xba, 0x07, 0x61, 0x74, 0x83, 0x2f, 0xfc, 0x26, 0xd6, 0x09, 0xb9, 0x00, 0x34, 0x36, 0x4f, 0x01, 0xf3, 0x48, 0xdb, 0x43, 0xba, 0x04, 0x44},
},
{
addYX: fp.Elt{0x4c, 0xda, 0x0d, 0x13, 0x66, 0xfd, 0x82, 0x84, 0x9f, 0x75, 0x5b, 0xa2, 0x17, 0xfe, 0x34, 0xbf, 0x1f, 0xcb, 0xba, 0x90, 0x55, 0x80, 0x83, 0xfd, 0x63, 0xb9, 0x18, 0xf8, 0x5b, 0x5d, 0x94, 0x1e},
subYX: fp.Elt{0xb9, 0xdb, 0x6c, 0x04, 0x88, 0x22, 0xd8, 0x79, 0x83, 0x2f, 0x8d, 0x65, 0x6b, 0xd2, 0xab, 0x1b, 0xdd, 0x65, 0xe5, 0x93, 0x63, 0xf8, 0xa2, 0xd8, 0x3c, 0xf1, 0x4b, 0xc5, 0x99, 0xd1, 0xf2, 0x12},
dt2: fp.Elt{0x05, 0x4c, 0xb8, 0x3b, 0xfe, 0xf5, 0x9f, 0x2e, 0xd1, 0xb2, 0xb8, 0xff, 0xfe, 0x6d, 0xd9, 0x37, 0xe0, 0xae, 0xb4, 0x5a, 0x51, 0x80, 0x7e, 0x9b, 0x1d, 0xd1, 0x8d, 0x8c, 0x56, 0xb1, 0x84, 0x35},
},
{
addYX: fp.Elt{0x39, 0x71, 0x43, 0x34, 0xe3, 0x42, 0x45, 0xa1, 0xf2, 0x68, 0x71, 0xa7, 0xe8, 0x23, 0xfd, 0x9f, 0x86, 0x48, 0xff, 0xe5, 0x96, 0x74, 0xcf, 0x05, 0x49, 0xe2, 0xb3, 0x6c, 0x17, 0x77, 0x2f, 0x6d},
subYX: fp.Elt{0x73, 0x3f, 0xc1, 0xc7, 0x6a, 0x66, 0xa1, 0x20, 0xdd, 0x11, 0xfb, 0x7a, 0x6e, 0xa8, 0x51, 0xb8, 0x3f, 0x9d, 0xa2, 0x97, 0x84, 0xb5, 0xc7, 0x90, 0x7c, 0xab, 0x48, 0xd6, 0x84, 0xa3, 0xd5, 0x1a},
dt2: fp.Elt{0x63, 0x27, 0x3c, 0x49, 0x4b, 0xfc, 0x22, 0xf2, 0x0b, 0x50, 0xc2, 0x0f, 0xb4, 0x1f, 0x31, 0x0c, 0x2f, 0x53, 0xab, 0xaa, 0x75, 0x6f, 0xe0, 0x69, 0x39, 0x56, 0xe0, 0x3b, 0xb7, 0xa8, 0xbf, 0x45},
},
},
{
{
addYX: fp.Elt{0x00, 0x45, 0xd9, 0x0d, 0x58, 0x03, 0xfc, 0x29, 0x93, 0xec, 0xbb, 0x6f, 0xa4, 0x7a, 0xd2, 0xec, 0xf8, 0xa7, 0xe2, 0xc2, 0x5f, 0x15, 0x0a, 0x13, 0xd5, 0xa1, 0x06, 0xb7, 0x1a, 0x15, 0x6b, 0x41},
subYX: fp.Elt{0x85, 0x8c, 0xb2, 0x17, 0xd6, 0x3b, 0x0a, 0xd3, 0xea, 0x3b, 0x77, 0x39, 0xb7, 0x77, 0xd3, 0xc5, 0xbf, 0x5c, 0x6a, 0x1e, 0x8c, 0xe7, 0xc6, 0xc6, 0xc4, 0xb7, 0x2a, 0x8b, 0xf7, 0xb8, 0x61, 0x0d},
dt2: fp.Elt{0xb0, 0x36, 0xc1, 0xe9, 0xef, 0xd7, 0xa8, 0x56, 0x20, 0x4b, 0xe4, 0x58, 0xcd, 0xe5, 0x07, 0xbd, 0xab, 0xe0, 0x57, 0x1b, 0xda, 0x2f, 0xe6, 0xaf, 0xd2, 0xe8, 0x77, 0x42, 0xf7, 0x2a, 0x1a, 0x19},
},
{
addYX: fp.Elt{0x6a, 0x6d, 0x6d, 0xd1, 0xfa, 0xf5, 0x03, 0x30, 0xbd, 0x6d, 0xc2, 0xc8, 0xf5, 0x38, 0x80, 0x4f, 0xb2, 0xbe, 0xa1, 0x76, 0x50, 0x1a, 0x73, 0xf2, 0x78, 0x2b, 0x8e, 0x3a, 0x1e, 0x34, 0x47, 0x7b},
subYX: fp.Elt{0xc3, 0x2c, 0x36, 0xdc, 0xc5, 0x45, 0xbc, 0xef, 0x1b, 0x64, 0xd6, 0x65, 0x28, 0xe9, 0xda, 0x84, 0x13, 0xbe, 0x27, 0x8e, 0x3f, 0x98, 0x2a, 0x37, 0xee, 0x78, 0x97, 0xd6, 0xc0, 0x6f, 0xb4, 0x53},
dt2: fp.Elt{0x58, 0x5d, 0xa7, 0xa3, 0x68, 0xbb, 0x20, 0x30, 0x2e, 0x03, 0xe9, 0xb1, 0xd4, 0x90, 0x72, 0xe3, 0x71, 0xb2, 0x36, 0x3e, 0x73, 0xa0, 0x2e, 0x3d, 0xd1, 0x85, 0x33, 0x62, 0x4e, 0xa7, 0x7b, 0x31},
},
{
addYX: fp.Elt{0xbf, 0xc4, 0x38, 0x53, 0xfb, 0x68, 0xa9, 0x77, 0xce, 0x55, 0xf9, 0x05, 0xcb, 0xeb, 0xfb, 0x8c, 0x46, 0xc2, 0x32, 0x7c, 0xf0, 0xdb, 0xd7, 0x2c, 0x62, 0x8e, 0xdd, 0x54, 0x75, 0xcf, 0x3f, 0x33},
subYX: fp.Elt{0x49, 0x50, 0x1f, 0x4e, 0x6e, 0x55, 0x55, 0xde, 0x8c, 0x4e, 0x77, 0x96, 0x38, 0x3b, 0xfe, 0xb6, 0x43, 0x3c, 0x86, 0x69, 0xc2, 0x72, 0x66, 0x1f, 0x6b, 0xf9, 0x87, 0xbc, 0x4f, 0x37, 0x3e, 0x3c},
dt2: fp.Elt{0xd2, 0x2f, 0x06, 0x6b, 0x08, 0x07, 0x69, 0x77, 0xc0, 0x94, 0xcc, 0xae, 0x43, 0x00, 0x59, 0x6e, 0xa3, 0x63, 0xa8, 0xdd, 0xfa, 0x24, 0x18, 0xd0, 0x35, 0xc7, 0x78, 0xf7, 0x0d, 0xd4, 0x5a, 0x1e},
},
{
addYX: fp.Elt{0x45, 0xc1, 0x17, 0x51, 0xf8, 0xed, 0x7e, 0xc7, 0xa9, 0x1a, 0x11, 0x6e, 0x2d, 0xef, 0x0b, 0xd5, 0x3f, 0x98, 0xb0, 0xa3, 0x9d, 0x65, 0xf1, 0xcd, 0x53, 0x4a, 0x8a, 0x18, 0x70, 0x0a, 0x7f, 0x23},
subYX: fp.Elt{0xdd, 0xef, 0xbe, 0x3a, 0x31, 0xe0, 0xbc, 0xbe, 0x6d, 0x5d, 0x79, 0x87, 0xd6, 0xbe, 0x68, 0xe3, 0x59, 0x76, 0x8c, 0x86, 0x0e, 0x7a, 0x92, 0x13, 0x14, 0x8f, 0x67, 0xb3, 0xcb, 0x1a, 0x76, 0x76},
dt2: fp.Elt{0x56, 0x7a, 0x1c, 0x9d, 0xca, 0x96, 0xf9, 0xf9, 0x03, 0x21, 0xd4, 0xe8, 0xb3, 0xd5, 0xe9, 0x52, 0xc8, 0x54, 0x1e, 0x1b, 0x13, 0xb6, 0xfd, 0x47, 0x7d, 0x02, 0x32, 0x33, 0x27, 0xe2, 0x1f, 0x19},
},
},
}
var tabVerif = [1 << (omegaFix - 2)]pointR3{
{ /* 1P */
addYX: fp.Elt{0x85, 0x3b, 0x8c, 0xf5, 0xc6, 0x93, 0xbc, 0x2f, 0x19, 0x0e, 0x8c, 0xfb, 0xc6, 0x2d, 0x93, 0xcf, 0xc2, 0x42, 0x3d, 0x64, 0x98, 0x48, 0x0b, 0x27, 0x65, 0xba, 0xd4, 0x33, 0x3a, 0x9d, 0xcf, 0x07},
subYX: fp.Elt{0x3e, 0x91, 0x40, 0xd7, 0x05, 0x39, 0x10, 0x9d, 0xb3, 0xbe, 0x40, 0xd1, 0x05, 0x9f, 0x39, 0xfd, 0x09, 0x8a, 0x8f, 0x68, 0x34, 0x84, 0xc1, 0xa5, 0x67, 0x12, 0xf8, 0x98, 0x92, 0x2f, 0xfd, 0x44},
dt2: fp.Elt{0x68, 0xaa, 0x7a, 0x87, 0x05, 0x12, 0xc9, 0xab, 0x9e, 0xc4, 0xaa, 0xcc, 0x23, 0xe8, 0xd9, 0x26, 0x8c, 0x59, 0x43, 0xdd, 0xcb, 0x7d, 0x1b, 0x5a, 0xa8, 0x65, 0x0c, 0x9f, 0x68, 0x7b, 0x11, 0x6f},
},
{ /* 3P */
addYX: fp.Elt{0x30, 0x97, 0xee, 0x4c, 0xa8, 0xb0, 0x25, 0xaf, 0x8a, 0x4b, 0x86, 0xe8, 0x30, 0x84, 0x5a, 0x02, 0x32, 0x67, 0x01, 0x9f, 0x02, 0x50, 0x1b, 0xc1, 0xf4, 0xf8, 0x80, 0x9a, 0x1b, 0x4e, 0x16, 0x7a},
subYX: fp.Elt{0x65, 0xd2, 0xfc, 0xa4, 0xe8, 0x1f, 0x61, 0x56, 0x7d, 0xba, 0xc1, 0xe5, 0xfd, 0x53, 0xd3, 0x3b, 0xbd, 0xd6, 0x4b, 0x21, 0x1a, 0xf3, 0x31, 0x81, 0x62, 0xda, 0x5b, 0x55, 0x87, 0x15, 0xb9, 0x2a},
dt2: fp.Elt{0x89, 0xd8, 0xd0, 0x0d, 0x3f, 0x93, 0xae, 0x14, 0x62, 0xda, 0x35, 0x1c, 0x22, 0x23, 0x94, 0x58, 0x4c, 0xdb, 0xf2, 0x8c, 0x45, 0xe5, 0x70, 0xd1, 0xc6, 0xb4, 0xb9, 0x12, 0xaf, 0x26, 0x28, 0x5a},
},
{ /* 5P */
addYX: fp.Elt{0x33, 0xbb, 0xa5, 0x08, 0x44, 0xbc, 0x12, 0xa2, 0x02, 0xed, 0x5e, 0xc7, 0xc3, 0x48, 0x50, 0x8d, 0x44, 0xec, 0xbf, 0x5a, 0x0c, 0xeb, 0x1b, 0xdd, 0xeb, 0x06, 0xe2, 0x46, 0xf1, 0xcc, 0x45, 0x29},
subYX: fp.Elt{0xba, 0xd6, 0x47, 0xa4, 0xc3, 0x82, 0x91, 0x7f, 0xb7, 0x29, 0x27, 0x4b, 0xd1, 0x14, 0x00, 0xd5, 0x87, 0xa0, 0x64, 0xb8, 0x1c, 0xf1, 0x3c, 0xe3, 0xf3, 0x55, 0x1b, 0xeb, 0x73, 0x7e, 0x4a, 0x15},
dt2: fp.Elt{0x85, 0x82, 0x2a, 0x81, 0xf1, 0xdb, 0xbb, 0xbc, 0xfc, 0xd1, 0xbd, 0xd0, 0x07, 0x08, 0x0e, 0x27, 0x2d, 0xa7, 0xbd, 0x1b, 0x0b, 0x67, 0x1b, 0xb4, 0x9a, 0xb6, 0x3b, 0x6b, 0x69, 0xbe, 0xaa, 0x43},
},
{ /* 7P */
addYX: fp.Elt{0xbf, 0xa3, 0x4e, 0x94, 0xd0, 0x5c, 0x1a, 0x6b, 0xd2, 0xc0, 0x9d, 0xb3, 0x3a, 0x35, 0x70, 0x74, 0x49, 0x2e, 0x54, 0x28, 0x82, 0x52, 0xb2, 0x71, 0x7e, 0x92, 0x3c, 0x28, 0x69, 0xea, 0x1b, 0x46},
subYX: fp.Elt{0xb1, 0x21, 0x32, 0xaa, 0x9a, 0x2c, 0x6f, 0xba, 0xa7, 0x23, 0xba, 0x3b, 0x53, 0x21, 0xa0, 0x6c, 0x3a, 0x2c, 0x19, 0x92, 0x4f, 0x76, 0xea, 0x9d, 0xe0, 0x17, 0x53, 0x2e, 0x5d, 0xdd, 0x6e, 0x1d},
dt2: fp.Elt{0xa2, 0xb3, 0xb8, 0x01, 0xc8, 0x6d, 0x83, 0xf1, 0x9a, 0xa4, 0x3e, 0x05, 0x47, 0x5f, 0x03, 0xb3, 0xf3, 0xad, 0x77, 0x58, 0xba, 0x41, 0x9c, 0x52, 0xa7, 0x90, 0x0f, 0x6a, 0x1c, 0xbb, 0x9f, 0x7a},
},
{ /* 9P */
addYX: fp.Elt{0x2f, 0x63, 0xa8, 0xa6, 0x8a, 0x67, 0x2e, 0x9b, 0xc5, 0x46, 0xbc, 0x51, 0x6f, 0x9e, 0x50, 0xa6, 0xb5, 0xf5, 0x86, 0xc6, 0xc9, 0x33, 0xb2, 0xce, 0x59, 0x7f, 0xdd, 0x8a, 0x33, 0xed, 0xb9, 0x34},
subYX: fp.Elt{0x64, 0x80, 0x9d, 0x03, 0x7e, 0x21, 0x6e, 0xf3, 0x9b, 0x41, 0x20, 0xf5, 0xb6, 0x81, 0xa0, 0x98, 0x44, 0xb0, 0x5e, 0xe7, 0x08, 0xc6, 0xcb, 0x96, 0x8f, 0x9c, 0xdc, 0xfa, 0x51, 0x5a, 0xc0, 0x49},
dt2: fp.Elt{0x1b, 0xaf, 0x45, 0x90, 0xbf, 0xe8, 0xb4, 0x06, 0x2f, 0xd2, 0x19, 0xa7, 0xe8, 0x83, 0xff, 0xe2, 0x16, 0xcf, 0xd4, 0x93, 0x29, 0xfc, 0xf6, 0xaa, 0x06, 0x8b, 0x00, 0x1b, 0x02, 0x72, 0xc1, 0x73},
},
{ /* 11P */
addYX: fp.Elt{0xde, 0x2a, 0x80, 0x8a, 0x84, 0x00, 0xbf, 0x2f, 0x27, 0x2e, 0x30, 0x02, 0xcf, 0xfe, 0xd9, 0xe5, 0x06, 0x34, 0x70, 0x17, 0x71, 0x84, 0x3e, 0x11, 0xaf, 0x8f, 0x6d, 0x54, 0xe2, 0xaa, 0x75, 0x42},
subYX: fp.Elt{0x48, 0x43, 0x86, 0x49, 0x02, 0x5b, 0x5f, 0x31, 0x81, 0x83, 0x08, 0x77, 0x69, 0xb3, 0xd6, 0x3e, 0x95, 0xeb, 0x8d, 0x6a, 0x55, 0x75, 0xa0, 0xa3, 0x7f, 0xc7, 0xd5, 0x29, 0x80, 0x59, 0xab, 0x18},
dt2: fp.Elt{0xe9, 0x89, 0x60, 0xfd, 0xc5, 0x2c, 0x2b, 0xd8, 0xa4, 0xe4, 0x82, 0x32, 0xa1, 0xb4, 0x1e, 0x03, 0x22, 0x86, 0x1a, 0xb5, 0x99, 0x11, 0x31, 0x44, 0x48, 0xf9, 0x3d, 0xb5, 0x22, 0x55, 0xc6, 0x3d},
},
{ /* 13P */
addYX: fp.Elt{0x6d, 0x7f, 0x00, 0xa2, 0x22, 0xc2, 0x70, 0xbf, 0xdb, 0xde, 0xbc, 0xb5, 0x9a, 0xb3, 0x84, 0xbf, 0x07, 0xba, 0x07, 0xfb, 0x12, 0x0e, 0x7a, 0x53, 0x41, 0xf2, 0x46, 0xc3, 0xee, 0xd7, 0x4f, 0x23},
subYX: fp.Elt{0x93, 0xbf, 0x7f, 0x32, 0x3b, 0x01, 0x6f, 0x50, 0x6b, 0x6f, 0x77, 0x9b, 0xc9, 0xeb, 0xfc, 0xae, 0x68, 0x59, 0xad, 0xaa, 0x32, 0xb2, 0x12, 0x9d, 0xa7, 0x24, 0x60, 0x17, 0x2d, 0x88, 0x67, 0x02},
dt2: fp.Elt{0x78, 0xa3, 0x2e, 0x73, 0x19, 0xa1, 0x60, 0x53, 0x71, 0xd4, 0x8d, 0xdf, 0xb1, 0xe6, 0x37, 0x24, 0x33, 0xe5, 0xa7, 0x91, 0xf8, 0x37, 0xef, 0xa2, 0x63, 0x78, 0x09, 0xaa, 0xfd, 0xa6, 0x7b, 0x49},
},
{ /* 15P */
addYX: fp.Elt{0xa0, 0xea, 0xcf, 0x13, 0x03, 0xcc, 0xce, 0x24, 0x6d, 0x24, 0x9c, 0x18, 0x8d, 0xc2, 0x48, 0x86, 0xd0, 0xd4, 0xf2, 0xc1, 0xfa, 0xbd, 0xbd, 0x2d, 0x2b, 0xe7, 0x2d, 0xf1, 0x17, 0x29, 0xe2, 0x61},
subYX: fp.Elt{0x0b, 0xcf, 0x8c, 0x46, 0x86, 0xcd, 0x0b, 0x04, 0xd6, 0x10, 0x99, 0x2a, 0xa4, 0x9b, 0x82, 0xd3, 0x92, 0x51, 0xb2, 0x07, 0x08, 0x30, 0x08, 0x75, 0xbf, 0x5e, 0xd0, 0x18, 0x42, 0xcd, 0xb5, 0x43},
dt2: fp.Elt{0x16, 0xb5, 0xd0, 0x9b, 0x2f, 0x76, 0x9a, 0x5d, 0xee, 0xde, 0x3f, 0x37, 0x4e, 0xaf, 0x38, 0xeb, 0x70, 0x42, 0xd6, 0x93, 0x7d, 0x5a, 0x2e, 0x03, 0x42, 0xd8, 0xe4, 0x0a, 0x21, 0x61, 0x1d, 0x51},
},
{ /* 17P */
addYX: fp.Elt{0x81, 0x9d, 0x0e, 0x95, 0xef, 0x76, 0xc6, 0x92, 0x4f, 0x04, 0xd7, 0xc0, 0xcd, 0x20, 0x46, 0xa5, 0x48, 0x12, 0x8f, 0x6f, 0x64, 0x36, 0x9b, 0xaa, 0xe3, 0x55, 0xb8, 0xdd, 0x24, 0x59, 0x32, 0x6d},
subYX: fp.Elt{0x87, 0xde, 0x20, 0x44, 0x48, 0x86, 0x13, 0x08, 0xb4, 0xed, 0x92, 0xb5, 0x16, 0xf0, 0x1c, 0x8a, 0x25, 0x2d, 0x94, 0x29, 0x27, 0x4e, 0xfa, 0x39, 0x10, 0x28, 0x48, 0xe2, 0x6f, 0xfe, 0xa7, 0x71},
dt2: fp.Elt{0x54, 0xc8, 0xc8, 0xa5, 0xb8, 0x82, 0x71, 0x6c, 0x03, 0x2a, 0x5f, 0xfe, 0x79, 0x14, 0xfd, 0x33, 0x0c, 0x8d, 0x77, 0x83, 0x18, 0x59, 0xcf, 0x72, 0xa9, 0xea, 0x9e, 0x55, 0xb6, 0xc4, 0x46, 0x47},
},
{ /* 19P */
addYX: fp.Elt{0x2b, 0x9a, 0xc6, 0x6d, 0x3c, 0x7b, 0x77, 0xd3, 0x17, 0xf6, 0x89, 0x6f, 0x27, 0xb2, 0xfa, 0xde, 0xb5, 0x16, 0x3a, 0xb5, 0xf7, 0x1c, 0x65, 0x45, 0xb7, 0x9f, 0xfe, 0x34, 0xde, 0x51, 0x9a, 0x5c},
subYX: fp.Elt{0x47, 0x11, 0x74, 0x64, 0xc8, 0x46, 0x85, 0x34, 0x49, 0xc8, 0xfc, 0x0e, 0xdd, 0xae, 0x35, 0x7d, 0x32, 0xa3, 0x72, 0x06, 0x76, 0x9a, 0x93, 0xff, 0xd6, 0xe6, 0xb5, 0x7d, 0x49, 0x63, 0x96, 0x21},
dt2: fp.Elt{0x67, 0x0e, 0xf1, 0x79, 0xcf, 0xf1, 0x10, 0xf5, 0x5b, 0x51, 0x58, 0xe6, 0xa1, 0xda, 0xdd, 0xff, 0x77, 0x22, 0x14, 0x10, 0x17, 0xa7, 0xc3, 0x09, 0xbb, 0x23, 0x82, 0x60, 0x3c, 0x50, 0x04, 0x48},
},
{ /* 21P */
addYX: fp.Elt{0xc7, 0x7f, 0xa3, 0x2c, 0xd0, 0x9e, 0x24, 0xc4, 0xab, 0xac, 0x15, 0xa6, 0xe3, 0xa0, 0x59, 0xa0, 0x23, 0x0e, 0x6e, 0xc9, 0xd7, 0x6e, 0xa9, 0x88, 0x6d, 0x69, 0x50, 0x16, 0xa5, 0x98, 0x33, 0x55},
subYX: fp.Elt{0x75, 0xd1, 0x36, 0x3a, 0xd2, 0x21, 0x68, 0x3b, 0x32, 0x9e, 0x9b, 0xe9, 0xa7, 0x0a, 0xb4, 0xbb, 0x47, 0x8a, 0x83, 0x20, 0xe4, 0x5c, 0x9e, 0x5d, 0x5e, 0x4c, 0xde, 0x58, 0x88, 0x09, 0x1e, 0x77},
dt2: fp.Elt{0xdf, 0x1e, 0x45, 0x78, 0xd2, 0xf5, 0x12, 0x9a, 0xcb, 0x9c, 0x89, 0x85, 0x79, 0x5d, 0xda, 0x3a, 0x08, 0x95, 0xa5, 0x9f, 0x2d, 0x4a, 0x7f, 0x47, 0x11, 0xa6, 0xf5, 0x8f, 0xd6, 0xd1, 0x5e, 0x5a},
},
{ /* 23P */
addYX: fp.Elt{0x83, 0x0e, 0x15, 0xfe, 0x2a, 0x12, 0x95, 0x11, 0xd8, 0x35, 0x4b, 0x7e, 0x25, 0x9a, 0x20, 0xcf, 0x20, 0x1e, 0x71, 0x1e, 0x29, 0xf8, 0x87, 0x73, 0xf0, 0x92, 0xbf, 0xd8, 0x97, 0xb8, 0xac, 0x44},
subYX: fp.Elt{0x59, 0x73, 0x52, 0x58, 0xc5, 0xe0, 0xe5, 0xba, 0x7e, 0x9d, 0xdb, 0xca, 0x19, 0x5c, 0x2e, 0x39, 0xe9, 0xab, 0x1c, 0xda, 0x1e, 0x3c, 0x65, 0x28, 0x44, 0xdc, 0xef, 0x5f, 0x13, 0x60, 0x9b, 0x01},
dt2: fp.Elt{0x83, 0x4b, 0x13, 0x5e, 0x14, 0x68, 0x60, 0x1e, 0x16, 0x4c, 0x30, 0x24, 0x4f, 0xe6, 0xf5, 0xc4, 0xd7, 0x3e, 0x1a, 0xfc, 0xa8, 0x88, 0x6e, 0x50, 0x92, 0x2f, 0xad, 0xe6, 0xfd, 0x49, 0x0c, 0x15},
},
{ /* 25P */
addYX: fp.Elt{0x38, 0x11, 0x47, 0x09, 0x95, 0xf2, 0x7b, 0x8e, 0x51, 0xa6, 0x75, 0x4f, 0x39, 0xef, 0x6f, 0x5d, 0xad, 0x08, 0xa7, 0x25, 0xc4, 0x79, 0xaf, 0x10, 0x22, 0x99, 0xb9, 0x5b, 0x07, 0x5a, 0x2b, 0x6b},
subYX: fp.Elt{0x68, 0xa8, 0xdc, 0x9c, 0x3c, 0x86, 0x49, 0xb8, 0xd0, 0x4a, 0x71, 0xb8, 0xdb, 0x44, 0x3f, 0xc8, 0x8d, 0x16, 0x36, 0x0c, 0x56, 0xe3, 0x3e, 0xfe, 0xc1, 0xfb, 0x05, 0x1e, 0x79, 0xd7, 0xa6, 0x78},
dt2: fp.Elt{0x76, 0xb9, 0xa0, 0x47, 0x4b, 0x70, 0xbf, 0x58, 0xd5, 0x48, 0x17, 0x74, 0x55, 0xb3, 0x01, 0xa6, 0x90, 0xf5, 0x42, 0xd5, 0xb1, 0x1f, 0x2b, 0xaa, 0x00, 0x5d, 0xd5, 0x4a, 0xfc, 0x7f, 0x5c, 0x72},
},
{ /* 27P */
addYX: fp.Elt{0xb2, 0x99, 0xcf, 0xd1, 0x15, 0x67, 0x42, 0xe4, 0x34, 0x0d, 0xa2, 0x02, 0x11, 0xd5, 0x52, 0x73, 0x9f, 0x10, 0x12, 0x8b, 0x7b, 0x15, 0xd1, 0x23, 0xa3, 0xf3, 0xb1, 0x7c, 0x27, 0xc9, 0x4c, 0x79},
subYX: fp.Elt{0xc0, 0x98, 0xd0, 0x1c, 0xf7, 0x2b, 0x80, 0x91, 0x66, 0x63, 0x5e, 0xed, 0xa4, 0x6c, 0x41, 0xfe, 0x4c, 0x99, 0x02, 0x49, 0x71, 0x5d, 0x58, 0xdf, 0xe7, 0xfa, 0x55, 0xf8, 0x25, 0x46, 0xd5, 0x4c},
dt2: fp.Elt{0x53, 0x50, 0xac, 0xc2, 0x26, 0xc4, 0xf6, 0x4a, 0x58, 0x72, 0xf6, 0x32, 0xad, 0xed, 0x9a, 0xbc, 0x21, 0x10, 0x31, 0x0a, 0xf1, 0x32, 0xd0, 0x2a, 0x85, 0x8e, 0xcc, 0x6f, 0x7b, 0x35, 0x08, 0x70},
},
{ /* 29P */
addYX: fp.Elt{0x01, 0x3f, 0x77, 0x38, 0x27, 0x67, 0x88, 0x0b, 0xfb, 0xcc, 0xfb, 0x95, 0xfa, 0xc8, 0xcc, 0xb8, 0xb6, 0x29, 0xad, 0xb9, 0xa3, 0xd5, 0x2d, 0x8d, 0x6a, 0x0f, 0xad, 0x51, 0x98, 0x7e, 0xef, 0x06},
subYX: fp.Elt{0x34, 0x4a, 0x58, 0x82, 0xbb, 0x9f, 0x1b, 0xd0, 0x2b, 0x79, 0xb4, 0xd2, 0x63, 0x64, 0xab, 0x47, 0x02, 0x62, 0x53, 0x48, 0x9c, 0x63, 0x31, 0xb6, 0x28, 0xd4, 0xd6, 0x69, 0x36, 0x2a, 0xa9, 0x13},
dt2: fp.Elt{0xe5, 0x7d, 0x57, 0xc0, 0x1c, 0x77, 0x93, 0xca, 0x5c, 0xdc, 0x35, 0x50, 0x1e, 0xe4, 0x40, 0x75, 0x71, 0xe0, 0x02, 0xd8, 0x01, 0x0f, 0x68, 0x24, 0x6a, 0xf8, 0x2a, 0x8a, 0xdf, 0x6d, 0x29, 0x3c},
},
{ /* 31P */
addYX: fp.Elt{0x13, 0xa7, 0x14, 0xd9, 0xf9, 0x15, 0xad, 0xae, 0x12, 0xf9, 0x8f, 0x8c, 0xf9, 0x7b, 0x2f, 0xa9, 0x30, 0xd7, 0x53, 0x9f, 0x17, 0x23, 0xf8, 0xaf, 0xba, 0x77, 0x0c, 0x49, 0x93, 0xd3, 0x99, 0x7a},
subYX: fp.Elt{0x41, 0x25, 0x1f, 0xbb, 0x2e, 0x4d, 0xeb, 0xfc, 0x1f, 0xb9, 0xad, 0x40, 0xc7, 0x10, 0x95, 0xb8, 0x05, 0xad, 0xa1, 0xd0, 0x7d, 0xa3, 0x71, 0xfc, 0x7b, 0x71, 0x47, 0x07, 0x70, 0x2c, 0x89, 0x0a},
dt2: fp.Elt{0xe8, 0xa3, 0xbd, 0x36, 0x24, 0xed, 0x52, 0x8f, 0x94, 0x07, 0xe8, 0x57, 0x41, 0xc8, 0xa8, 0x77, 0xe0, 0x9c, 0x2f, 0x26, 0x63, 0x65, 0xa9, 0xa5, 0xd2, 0xf7, 0x02, 0x83, 0xd2, 0x62, 0x67, 0x28},
},
{ /* 33P */
addYX: fp.Elt{0x25, 0x5b, 0xe3, 0x3c, 0x09, 0x36, 0x78, 0x4e, 0x97, 0xaa, 0x6b, 0xb2, 0x1d, 0x18, 0xe1, 0x82, 0x3f, 0xb8, 0xc7, 0xcb, 0xd3, 0x92, 0xc1, 0x0c, 0x3a, 0x9d, 0x9d, 0x6a, 0x04, 0xda, 0xf1, 0x32},
subYX: fp.Elt{0xbd, 0xf5, 0x2e, 0xce, 0x2b, 0x8e, 0x55, 0x7c, 0x63, 0xbc, 0x47, 0x67, 0xb4, 0x6c, 0x98, 0xe4, 0xb8, 0x89, 0xbb, 0x3b, 0x9f, 0x17, 0x4a, 0x15, 0x7a, 0x76, 0xf1, 0xd6, 0xa3, 0xf2, 0x86, 0x76},
dt2: fp.Elt{0x6a, 0x7c, 0x59, 0x6d, 0xa6, 0x12, 0x8d, 0xaa, 0x2b, 0x85, 0xd3, 0x04, 0x03, 0x93, 0x11, 0x8f, 0x22, 0xb0, 0x09, 0xc2, 0x73, 0xdc, 0x91, 0x3f, 0xa6, 0x28, 0xad, 0xa9, 0xf8, 0x05, 0x13, 0x56},
},
{ /* 35P */
addYX: fp.Elt{0xd1, 0xae, 0x92, 0xec, 0x8d, 0x97, 0x0c, 0x10, 0xe5, 0x73, 0x6d, 0x4d, 0x43, 0xd5, 0x43, 0xca, 0x48, 0xba, 0x47, 0xd8, 0x22, 0x1b, 0x13, 0x83, 0x2c, 0x4d, 0x5d, 0xe3, 0x53, 0xec, 0xaa},
subYX: fp.Elt{0xd5, 0xc0, 0xb0, 0xe7, 0x28, 0xcc, 0x22, 0x67, 0x53, 0x5c, 0x07, 0xdb, 0xbb, 0xe9, 0x9d, 0x70, 0x61, 0x0a, 0x01, 0xd7, 0xa7, 0x8d, 0xf6, 0xca, 0x6c, 0xcc, 0x57, 0x2c, 0xef, 0x1a, 0x0a, 0x03},
dt2: fp.Elt{0xaa, 0xd2, 0x3a, 0x00, 0x73, 0xf7, 0xb1, 0x7b, 0x08, 0x66, 0x21, 0x2b, 0x80, 0x29, 0x3f, 0x0b, 0x3e, 0xd2, 0x0e, 0x52, 0x86, 0xdc, 0x21, 0x78, 0x80, 0x54, 0x06, 0x24, 0x1c, 0x9c, 0xbe, 0x20},
},
{ /* 37P */
addYX: fp.Elt{0xa6, 0x73, 0x96, 0x24, 0xd8, 0x87, 0x53, 0xe1, 0x93, 0xe4, 0x46, 0xf5, 0x2d, 0xbc, 0x43, 0x59, 0xb5, 0x63, 0x6f, 0xc3, 0x81, 0x9a, 0x7f, 0x1c, 0xde, 0xc1, 0x0a, 0x1f, 0x36, 0xb3, 0x0a, 0x75},
subYX: fp.Elt{0x60, 0x5e, 0x02, 0xe2, 0x4a, 0xe4, 0xe0, 0x20, 0x38, 0xb9, 0xdc, 0xcb, 0x2f, 0x3b, 0x3b, 0xb0, 0x1c, 0x0d, 0x5a, 0xf9, 0x9c, 0x63, 0x5d, 0x10, 0x11, 0xe3, 0x67, 0x50, 0x54, 0x4c, 0x76, 0x69},
dt2: fp.Elt{0x37, 0x10, 0xf8, 0xa2, 0x83, 0x32, 0x8a, 0x1e, 0xf1, 0xcb, 0x7f, 0xbd, 0x23, 0xda, 0x2e, 0x6f, 0x63, 0x25, 0x2e, 0xac, 0x5b, 0xd1, 0x2f, 0xb7, 0x40, 0x50, 0x07, 0xb7, 0x3f, 0x6b, 0xf9, 0x54},
},
{ /* 39P */
addYX: fp.Elt{0x79, 0x92, 0x66, 0x29, 0x04, 0xf2, 0xad, 0x0f, 0x4a, 0x72, 0x7d, 0x7d, 0x04, 0xa2, 0xdd, 0x3a, 0xf1, 0x60, 0x57, 0x8c, 0x82, 0x94, 0x3d, 0x6f, 0x9e, 0x53, 0xb7, 0x2b, 0xc5, 0xe9, 0x7f, 0x3d},
subYX: fp.Elt{0xcd, 0x1e, 0xb1, 0x16, 0xc6, 0xaf, 0x7d, 0x17, 0x79, 0x64, 0x57, 0xfa, 0x9c, 0x4b, 0x76, 0x89, 0x85, 0xe7, 0xec, 0xe6, 0x10, 0xa1, 0xa8, 0xb7, 0xf0, 0xdb, 0x85, 0xbe, 0x9f, 0x83, 0xe6, 0x78},
dt2: fp.Elt{0x6b, 0x85, 0xb8, 0x37, 0xf7, 0x2d, 0x33, 0x70, 0x8a, 0x17, 0x1a, 0x04, 0x43, 0x5d, 0xd0, 0x75, 0x22, 0x9e, 0xe5, 0xa0, 0x4a, 0xf7, 0x0f, 0x32, 0x42, 0x82, 0x08, 0x50, 0xf3, 0x68, 0xf2, 0x70},
},
{ /* 41P */
addYX: fp.Elt{0x47, 0x5f, 0x80, 0xb1, 0x83, 0x45, 0x86, 0x66, 0x19, 0x7c, 0xdd, 0x60, 0xd1, 0xc5, 0x35, 0xf5, 0x06, 0xb0, 0x4c, 0x1e, 0xb7, 0x4e, 0x87, 0xe9, 0xd9, 0x89, 0xd8, 0xfa, 0x5c, 0x34, 0x0d, 0x7c},
subYX: fp.Elt{0x55, 0xf3, 0xdc, 0x70, 0x20, 0x11, 0x24, 0x23, 0x17, 0xe1, 0xfc, 0xe7, 0x7e, 0xc9, 0x0c, 0x38, 0x98, 0xb6, 0x52, 0x35, 0xed, 0xde, 0x1d, 0xb3, 0xb9, 0xc4, 0xb8, 0x39, 0xc0, 0x56, 0x4e, 0x40},
dt2: fp.Elt{0x8a, 0x33, 0x78, 0x8c, 0x4b, 0x1f, 0x1f, 0x59, 0xe1, 0xb5, 0xe0, 0x67, 0xb1, 0x6a, 0x36, 0xa0, 0x44, 0x3d, 0x5f, 0xb4, 0x52, 0x41, 0xbc, 0x5c, 0x77, 0xc7, 0xae, 0x2a, 0x76, 0x54, 0xd7, 0x20},
},
{ /* 43P */
addYX: fp.Elt{0x58, 0xb7, 0x3b, 0xc7, 0x6f, 0xc3, 0x8f, 0x5e, 0x9a, 0xbb, 0x3c, 0x36, 0xa5, 0x43, 0xe5, 0xac, 0x22, 0xc9, 0x3b, 0x90, 0x7d, 0x4a, 0x93, 0xa9, 0x62, 0xec, 0xce, 0xf3, 0x46, 0x1e, 0x8f, 0x2b},
subYX: fp.Elt{0x43, 0xf5, 0xb9, 0x35, 0xb1, 0xfe, 0x74, 0x9d, 0x6c, 0x95, 0x8c, 0xde, 0xf1, 0x7d, 0xb3, 0x84, 0xa9, 0x8b, 0x13, 0x57, 0x07, 0x2b, 0x32, 0xe9, 0xe1, 0x4c, 0x0b, 0x79, 0xa8, 0xad, 0xb8, 0x38},
dt2: fp.Elt{0x5d, 0xf9, 0x51, 0xdf, 0x9c, 0x4a, 0xc0, 0xb5, 0xac, 0xde, 0x1f, 0xcb, 0xae, 0x52, 0x39, 0x2b, 0xda, 0x66, 0x8b, 0x32, 0x8b, 0x6d, 0x10, 0x1d, 0x53, 0x19, 0xba, 0xce, 0x32, 0xeb, 0x9a, 0x04},
},
{ /* 45P */
addYX: fp.Elt{0x31, 0x79, 0xfc, 0x75, 0x0b, 0x7d, 0x50, 0xaa, 0xd3, 0x25, 0x67, 0x7a, 0x4b, 0x92, 0xef, 0x0f, 0x30, 0x39, 0x6b, 0x39, 0x2b, 0x54, 0x82, 0x1d, 0xfc, 0x74, 0xf6, 0x30, 0x75, 0xe1, 0x5e, 0x79},
subYX: fp.Elt{0x7e, 0xfe, 0xdc, 0x63, 0x3c, 0x7d, 0x76, 0xd7, 0x40, 0x6e, 0x85, 0x97, 0x48, 0x59, 0x9c, 0x20, 0x13, 0x7c, 0x4f, 0xe1, 0x61, 0x68, 0x67, 0xb6, 0xfc, 0x25, 0xd6, 0xc8, 0xe0, 0x65, 0xc6, 0x51},
dt2: fp.Elt{0x81, 0xbd, 0xec, 0x52, 0x0a, 0x5b, 0x4a, 0x25, 0xe7, 0xaf, 0x34, 0xe0, 0x6e, 0x1f, 0x41, 0x5d, 0x31, 0x4a, 0xee, 0xca, 0x0d, 0x4d, 0xa2, 0xe6, 0x77, 0x44, 0xc5, 0x9d, 0xf4, 0x9b, 0xd1, 0x6c},
},
{ /* 47P */
addYX: fp.Elt{0x86, 0xc3, 0xaf, 0x65, 0x21, 0x61, 0xfe, 0x1f, 0x10, 0x1b, 0xd5, 0xb8, 0x88, 0x2a, 0x2a, 0x08, 0xaa, 0x0b, 0x99, 0x20, 0x7e, 0x62, 0xf6, 0x76, 0xe7, 0x43, 0x9e, 0x42, 0xa7, 0xb3, 0x01, 0x5e},
subYX: fp.Elt{0xa3, 0x9c, 0x17, 0x52, 0x90, 0x61, 0x87, 0x7e, 0x85, 0x9f, 0x2c, 0x0b, 0x06, 0x0a, 0x1d, 0x57, 0x1e, 0x71, 0x99, 0x84, 0xa8, 0xba, 0xa2, 0x80, 0x38, 0xe6, 0xb2, 0x40, 0xdb, 0xf3, 0x20, 0x75},
dt2: fp.Elt{0xa1, 0x57, 0x93, 0xd3, 0xe3, 0x0b, 0xb5, 0x3d, 0xa5, 0x94, 0x9e, 0x59, 0xdd, 0x6c, 0x7b, 0x96, 0x6e, 0x1e, 0x31, 0xdf, 0x64, 0x9a, 0x30, 0x1a, 0x86, 0xc9, 0xf3, 0xce, 0x9c, 0x2c, 0x09, 0x71},
},
{ /* 49P */
addYX: fp.Elt{0xcf, 0x1d, 0x05, 0x74, 0xac, 0xd8, 0x6b, 0x85, 0x1e, 0xaa, 0xb7, 0x55, 0x08, 0xa4, 0xf6, 0x03, 0xeb, 0x3c, 0x74, 0xc9, 0xcb, 0xe7, 0x4a, 0x3a, 0xde, 0xab, 0x37, 0x71, 0xbb, 0xa5, 0x73, 0x41},
subYX: fp.Elt{0x8c, 0x91, 0x64, 0x03, 0x3f, 0x52, 0xd8, 0x53, 0x1c, 0x6b, 0xab, 0x3f, 0xf4, 0x04, 0xb4, 0xa2, 0xa4, 0xe5, 0x81, 0x66, 0x9e, 0x4a, 0x0b, 0x08, 0xa7, 0x7b, 0x25, 0xd0, 0x03, 0x5b, 0xa1, 0x0e},
dt2: fp.Elt{0x8a, 0x21, 0xf9, 0xf0, 0x31, 0x6e, 0xc5, 0x17, 0x08, 0x47, 0xfc, 0x1a, 0x2b, 0x6e, 0x69, 0x5a, 0x76, 0xf1, 0xb2, 0xf4, 0x68, 0x16, 0x93, 0xf7, 0x67, 0x3a, 0x4e, 0x4a, 0x61, 0x65, 0xc5, 0x5f},
},
{ /* 51P */
addYX: fp.Elt{0x8e, 0x98, 0x90, 0x77, 0xe6, 0xe1, 0x92, 0x48, 0x22, 0xd7, 0x5c, 0x1c, 0x0f, 0x95, 0xd5, 0x01, 0xed, 0x3e, 0x92, 0xe5, 0x9a, 0x81, 0xb0, 0xe3, 0x1b, 0x65, 0x46, 0x9d, 0x40, 0xc7, 0x14, 0x32},
subYX: fp.Elt{0xe5, 0x7a, 0x6d, 0xc4, 0x0d, 0x57, 0x6e, 0x13, 0x8f, 0xdc, 0xf8, 0x54, 0xcc, 0xaa, 0xd0, 0x0f, 0x86, 0xad, 0x0d, 0x31, 0x03, 0x9f, 0x54, 0x59, 0xa1, 0x4a, 0x45, 0x4c, 0x41, 0x1c, 0x71, 0x62},
dt2: fp.Elt{0x70, 0x17, 0x65, 0x06, 0x74, 0x82, 0x29, 0x13, 0x36, 0x94, 0x27, 0x8a, 0x66, 0xa0, 0xa4, 0x3b, 0x3c, 0x22, 0x5d, 0x18, 0xec, 0xb8, 0xb6, 0xd9, 0x3c, 0x83, 0xcb, 0x3e, 0x07, 0x94, 0xea, 0x5b},
},
{ /* 53P */
addYX: fp.Elt{0xf8, 0xd2, 0x43, 0xf3, 0x63, 0xce, 0x70, 0xb4, 0xf1, 0xe8, 0x43, 0x05, 0x8f, 0xba, 0x67, 0x00, 0x6f, 0x7b, 0x11, 0xa2, 0xa1, 0x51, 0xda, 0x35, 0x2f, 0xbd, 0xf1, 0x44, 0x59, 0x78, 0xd0, 0x4a},
subYX: fp.Elt{0xe4, 0x9b, 0xc8, 0x12, 0x09, 0xbf, 0x1d, 0x64, 0x9c, 0x57, 0x6e, 0x7d, 0x31, 0x8b, 0xf3, 0xac, 0x65, 0xb0, 0x97, 0xf6, 0x02, 0x9e, 0xfe, 0xab, 0xec, 0x1e, 0xf6, 0x48, 0xc1, 0xd5, 0xac, 0x3a},
dt2: fp.Elt{0x01, 0x83, 0x31, 0xc3, 0x34, 0x3b, 0x8e, 0x85, 0x26, 0x68, 0x31, 0x07, 0x47, 0xc0, 0x99, 0xdc, 0x8c, 0xa8, 0x9d, 0xd3, 0x2e, 0x5b, 0x08, 0x34, 0x3d, 0x85, 0x02, 0xd9, 0xb1, 0x0c, 0xff, 0x3a},
},
{ /* 55P */
addYX: fp.Elt{0x05, 0x35, 0xc5, 0xf4, 0x0b, 0x43, 0x26, 0x92, 0x83, 0x22, 0x1f, 0x26, 0x13, 0x9c, 0xe4, 0x68, 0xc6, 0x27, 0xd3, 0x8f, 0x78, 0x33, 0xef, 0x09, 0x7f, 0x9e, 0xd9, 0x2b, 0x73, 0x9f, 0xcf, 0x2c},
subYX: fp.Elt{0x5e, 0x40, 0x20, 0x3a, 0xeb, 0xc7, 0xc5, 0x87, 0xc9, 0x56, 0xad, 0xed, 0xef, 0x11, 0xe3, 0x8e, 0xf9, 0xd5, 0x29, 0xad, 0x48, 0x2e, 0x25, 0x29, 0x1d, 0x25, 0xcd, 0xf4, 0x86, 0x7e, 0x0e, 0x11},
dt2: fp.Elt{0xe4, 0xf5, 0x03, 0xd6, 0x9e, 0xd8, 0xc0, 0x57, 0x0c, 0x20, 0xb0, 0xf0, 0x28, 0x86, 0x88, 0x12, 0xb7, 0x3b, 0x2e, 0xa0, 0x09, 0x27, 0x17, 0x53, 0x37, 0x3a, 0x69, 0xb9, 0xe0, 0x57, 0xc5, 0x05},
},
{ /* 57P */
addYX: fp.Elt{0xb0, 0x0e, 0xc2, 0x89, 0xb0, 0xbb, 0x76, 0xf7, 0x5c, 0xd8, 0x0f, 0xfa, 0xf6, 0x5b, 0xf8, 0x61, 0xfb, 0x21, 0x44, 0x63, 0x4e, 0x3f, 0xb9, 0xb6, 0x05, 0x12, 0x86, 0x41, 0x08, 0xef, 0x9f, 0x28},
subYX: fp.Elt{0x6f, 0x7e, 0xc9, 0x1f, 0x31, 0xce, 0xf9, 0xd8, 0xae, 0xfd, 0xf9, 0x11, 0x30, 0x26, 0x3f, 0x7a, 0xdd, 0x25, 0xed, 0x8b, 0xa0, 0x7e, 0x5b, 0xe1, 0x5a, 0x87, 0xe9, 0x8f, 0x17, 0x4c, 0x15, 0x6e},
dt2: fp.Elt{0xbf, 0x9a, 0xd6, 0xfe, 0x36, 0x63, 0x61, 0xcf, 0x4f, 0xc9, 0x35, 0x83, 0xe7, 0xe4, 0x16, 0x9b, 0xe7, 0x7f, 0x3a, 0x75, 0x65, 0x97, 0x78, 0x13, 0x19, 0xa3, 0x5c, 0xa9, 0x42, 0xf6, 0xfb, 0x6a},
},
{ /* 59P */
addYX: fp.Elt{0xcc, 0xa8, 0x13, 0xf9, 0x70, 0x50, 0xe5, 0x5d, 0x61, 0xf5, 0x0c, 0x2b, 0x7b, 0x16, 0x1d, 0x7d, 0x89, 0xd4, 0xea, 0x90, 0xb6, 0x56, 0x29, 0xda, 0xd9, 0x1e, 0x80, 0xdb, 0xce, 0x93, 0xc0, 0x12},
subYX: fp.Elt{0xc1, 0xd2, 0xf5, 0x62, 0x0c, 0xde, 0xa8, 0x7d, 0x9a, 0x7b, 0x0e, 0xb0, 0xa4, 0x3d, 0xfc, 0x98, 0xe0, 0x70, 0xad, 0x0d, 0xda, 0x6a, 0xeb, 0x7d, 0xc4, 0x38, 0x50, 0xb9, 0x51, 0xb8, 0xb4, 0x0d},
dt2: fp.Elt{0x0f, 0x19, 0xb8, 0x08, 0x93, 0x7f, 0x14, 0xfc, 0x10, 0xe3, 0x1a, 0xa1, 0xa0, 0x9d, 0x96, 0x06, 0xfd, 0xd7, 0xc7, 0xda, 0x72, 0x55, 0xe7, 0xce, 0xe6, 0x5c, 0x63, 0xc6, 0x99, 0x87, 0xaa, 0x33},
},
{ /* 61P */
addYX: fp.Elt{0xb1, 0x6c, 0x15, 0xfc, 0x88, 0xf5, 0x48, 0x83, 0x27, 0x6d, 0x0a, 0x1a, 0x9b, 0xba, 0xa2, 0x6d, 0xb6, 0x5a, 0xca, 0x87, 0x5c, 0x2d, 0x26, 0xe2, 0xa6, 0x89, 0xd5, 0xc8, 0xc1, 0xd0, 0x2c, 0x21},
subYX: fp.Elt{0xf2, 0x5c, 0x08, 0xbd, 0x1e, 0xf5, 0x0f, 0xaf, 0x1f, 0x3f, 0xd3, 0x67, 0x89, 0x1a, 0xf5, 0x78, 0x3c, 0x03, 0x60, 0x50, 0xe1, 0xbf, 0xc2, 0x6e, 0x86, 0x1a, 0xe2, 0xe8, 0x29, 0x6f, 0x3c, 0x23},
dt2: fp.Elt{0x81, 0xc7, 0x18, 0x7f, 0x10, 0xd5, 0xf4, 0xd2, 0x28, 0x9d, 0x7e, 0x52, 0xf2, 0xcd, 0x2e, 0x12, 0x41, 0x33, 0x3d, 0x3d, 0x2a, 0x86, 0x0a, 0xa7, 0xe3, 0x4c, 0x91, 0x11, 0x89, 0x77, 0xb7, 0x1d},
},
{ /* 63P */
addYX: fp.Elt{0xb6, 0x1a, 0x70, 0xdd, 0x69, 0x47, 0x39, 0xb3, 0xa5, 0x8d, 0xcf, 0x19, 0xd4, 0xde, 0xb8, 0xe2, 0x52, 0xc8, 0x2a, 0xfd, 0x61, 0x41, 0xdf, 0x15, 0xbe, 0x24, 0x7d, 0x01, 0x8a, 0xca, 0xe2, 0x7a},
subYX: fp.Elt{0x6f, 0xc2, 0x6b, 0x7c, 0x39, 0x52, 0xf3, 0xdd, 0x13, 0x01, 0xd5, 0x53, 0xcc, 0xe2, 0x97, 0x7a, 0x30, 0xa3, 0x79, 0xbf, 0x3a, 0xf4, 0x74, 0x7c, 0xfc, 0xad, 0xe2, 0x26, 0xad, 0x97, 0xad, 0x31},
dt2: fp.Elt{0x62, 0xb9, 0x20, 0x09, 0xed, 0x17, 0xe8, 0xb7, 0x9d, 0xda, 0x19, 0x3f, 0xcc, 0x18, 0x85, 0x1e, 0x64, 0x0a, 0x56, 0x25, 0x4f, 0xc1, 0x91, 0xe4, 0x83, 0x2c, 0x62, 0xa6, 0x53, 0xfc, 0xd1, 0x1e},
},
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed448/ed448.go
================================================
// Package ed448 implements Ed448 signature scheme as described in RFC-8032.
//
// This package implements two signature variants.
//
// | Scheme Name | Sign Function | Verification | Context |
// |-------------|-------------------|---------------|-------------------|
// | Ed448 | Sign | Verify | Yes, can be empty |
// | Ed448Ph | SignPh | VerifyPh | Yes, can be empty |
// | All above | (PrivateKey).Sign | VerifyAny | As above |
//
// Specific functions for sign and verify are defined. A generic signing
// function for all schemes is available through the crypto.Signer interface,
// which is implemented by the PrivateKey type. A correspond all-in-one
// verification method is provided by the VerifyAny function.
//
// Both schemes require a context string for domain separation. This parameter
// is passed using a SignerOptions struct defined in this package.
//
// References:
//
// - RFC8032: https://rfc-editor.org/rfc/rfc8032.txt
// - EdDSA for more curves: https://eprint.iacr.org/2015/677
// - High-speed high-security signatures: https://doi.org/10.1007/s13389-012-0027-1
package ed448
import (
"bytes"
"crypto"
cryptoRand "crypto/rand"
"crypto/subtle"
"errors"
"fmt"
"io"
"strconv"
"github.com/cloudflare/circl/ecc/goldilocks"
"github.com/cloudflare/circl/internal/sha3"
"github.com/cloudflare/circl/sign"
)
const (
// ContextMaxSize is the maximum length (in bytes) allowed for context.
ContextMaxSize = 255
// PublicKeySize is the length in bytes of Ed448 public keys.
PublicKeySize = 57
// PrivateKeySize is the length in bytes of Ed448 private keys.
PrivateKeySize = 114
// SignatureSize is the length in bytes of signatures.
SignatureSize = 114
// SeedSize is the size, in bytes, of private key seeds. These are the private key representations used by RFC 8032.
SeedSize = 57
)
const (
paramB = 456 / 8 // Size of keys in bytes.
hashSize = 2 * paramB // Size of the hash function's output.
)
// SignerOptions implements crypto.SignerOpts and augments with parameters
// that are specific to the Ed448 signature schemes.
type SignerOptions struct {
// Hash must be crypto.Hash(0) for both Ed448 and Ed448Ph.
crypto.Hash
// Context is an optional domain separation string for signing.
// Its length must be less or equal than 255 bytes.
Context string
// Scheme is an identifier for choosing a signature scheme.
Scheme SchemeID
}
// SchemeID is an identifier for each signature scheme.
type SchemeID uint
const (
ED448 SchemeID = iota
ED448Ph
)
// PublicKey is the type of Ed448 public keys.
type PublicKey []byte
// Equal reports whether pub and x have the same value.
func (pub PublicKey) Equal(x crypto.PublicKey) bool {
xx, ok := x.(PublicKey)
return ok && bytes.Equal(pub, xx)
}
// PrivateKey is the type of Ed448 private keys. It implements crypto.Signer.
type PrivateKey []byte
// Equal reports whether priv and x have the same value.
func (priv PrivateKey) Equal(x crypto.PrivateKey) bool {
xx, ok := x.(PrivateKey)
return ok && subtle.ConstantTimeCompare(priv, xx) == 1
}
// Public returns the PublicKey corresponding to priv.
func (priv PrivateKey) Public() crypto.PublicKey {
publicKey := make([]byte, PublicKeySize)
copy(publicKey, priv[SeedSize:])
return PublicKey(publicKey)
}
// Seed returns the private key seed corresponding to priv. It is provided for
// interoperability with RFC 8032. RFC 8032's private keys correspond to seeds
// in this package.
func (priv PrivateKey) Seed() []byte {
seed := make([]byte, SeedSize)
copy(seed, priv[:SeedSize])
return seed
}
func (priv PrivateKey) Scheme() sign.Scheme { return sch }
func (pub PublicKey) Scheme() sign.Scheme { return sch }
func (priv PrivateKey) MarshalBinary() (data []byte, err error) {
privateKey := make(PrivateKey, PrivateKeySize)
copy(privateKey, priv)
return privateKey, nil
}
func (pub PublicKey) MarshalBinary() (data []byte, err error) {
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, pub)
return publicKey, nil
}
// Sign creates a signature of a message given a key pair.
// This function supports all the two signature variants defined in RFC-8032,
// namely Ed448 (or pure EdDSA) and Ed448Ph.
// The opts.HashFunc() must return zero to the specify Ed448 variant. This can
// be achieved by passing crypto.Hash(0) as the value for opts.
// Use an Options struct to pass a bool indicating that the ed448Ph variant
// should be used.
// The struct can also be optionally used to pass a context string for signing.
func (priv PrivateKey) Sign(
rand io.Reader,
message []byte,
opts crypto.SignerOpts,
) (signature []byte, err error) {
var ctx string
var scheme SchemeID
if o, ok := opts.(SignerOptions); ok {
ctx = o.Context
scheme = o.Scheme
}
switch true {
case scheme == ED448 && opts.HashFunc() == crypto.Hash(0):
return Sign(priv, message, ctx), nil
case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0):
return SignPh(priv, message, ctx), nil
default:
return nil, errors.New("ed448: bad hash algorithm")
}
}
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, crypto/rand.Reader will be used.
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptoRand.Reader
}
seed := make(PrivateKey, SeedSize)
if _, err := io.ReadFull(rand, seed); err != nil {
return nil, nil, err
}
privateKey := NewKeyFromSeed(seed)
publicKey := make([]byte, PublicKeySize)
copy(publicKey, privateKey[SeedSize:])
return publicKey, privateKey, nil
}
// NewKeyFromSeed calculates a private key from a seed. It will panic if
// len(seed) is not SeedSize. This function is provided for interoperability
// with RFC 8032. RFC 8032's private keys correspond to seeds in this
// package.
func NewKeyFromSeed(seed []byte) PrivateKey {
privateKey := make([]byte, PrivateKeySize)
newKeyFromSeed(privateKey, seed)
return privateKey
}
func newKeyFromSeed(privateKey, seed []byte) {
if l := len(seed); l != SeedSize {
panic("ed448: bad seed length: " + strconv.Itoa(l))
}
var h [hashSize]byte
H := sha3.NewShake256()
_, _ = H.Write(seed)
_, _ = H.Read(h[:])
s := &goldilocks.Scalar{}
deriveSecretScalar(s, h[:paramB])
copy(privateKey[:SeedSize], seed)
_ = goldilocks.Curve{}.ScalarBaseMult(s).ToBytes(privateKey[SeedSize:])
}
func signAll(signature []byte, privateKey PrivateKey, message, ctx []byte, preHash bool) {
if len(ctx) > ContextMaxSize {
panic(fmt.Errorf("ed448: bad context length: " + strconv.Itoa(len(ctx))))
}
H := sha3.NewShake256()
var PHM []byte
if preHash {
var h [64]byte
_, _ = H.Write(message)
_, _ = H.Read(h[:])
PHM = h[:]
H.Reset()
} else {
PHM = message
}
// 1. Hash the 57-byte private key using SHAKE256(x, 114).
var h [hashSize]byte
_, _ = H.Write(privateKey[:SeedSize])
_, _ = H.Read(h[:])
s := &goldilocks.Scalar{}
deriveSecretScalar(s, h[:paramB])
prefix := h[paramB:]
// 2. Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114).
var rPM [hashSize]byte
H.Reset()
writeDom(&H, ctx, preHash)
_, _ = H.Write(prefix)
_, _ = H.Write(PHM)
_, _ = H.Read(rPM[:])
// 3. Compute the point [r]B.
r := &goldilocks.Scalar{}
r.FromBytes(rPM[:])
R := (&[paramB]byte{})[:]
if err := (goldilocks.Curve{}.ScalarBaseMult(r).ToBytes(R)); err != nil {
panic(err)
}
// 4. Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114)
var hRAM [hashSize]byte
H.Reset()
writeDom(&H, ctx, preHash)
_, _ = H.Write(R)
_, _ = H.Write(privateKey[SeedSize:])
_, _ = H.Write(PHM)
_, _ = H.Read(hRAM[:])
// 5. Compute S = (r + k * s) mod order.
k := &goldilocks.Scalar{}
k.FromBytes(hRAM[:])
S := &goldilocks.Scalar{}
S.Mul(k, s)
S.Add(S, r)
// 6. The signature is the concatenation of R and S.
copy(signature[:paramB], R[:])
copy(signature[paramB:], S[:])
}
// Sign signs the message with privateKey and returns a signature.
// This function supports the signature variant defined in RFC-8032: Ed448,
// also known as the pure version of EdDSA.
// It will panic if len(privateKey) is not PrivateKeySize.
func Sign(priv PrivateKey, message []byte, ctx string) []byte {
signature := make([]byte, SignatureSize)
signAll(signature, priv, message, []byte(ctx), false)
return signature
}
// SignPh creates a signature of a message given a keypair.
// This function supports the signature variant defined in RFC-8032: Ed448ph,
// meaning it internally hashes the message using SHAKE-256.
// Context could be passed to this function, which length should be no more than
// 255. It can be empty.
func SignPh(priv PrivateKey, message []byte, ctx string) []byte {
signature := make([]byte, SignatureSize)
signAll(signature, priv, message, []byte(ctx), true)
return signature
}
func verify(public PublicKey, message, signature, ctx []byte, preHash bool) bool {
if len(public) != PublicKeySize ||
len(signature) != SignatureSize ||
len(ctx) > ContextMaxSize ||
!isLessThanOrder(signature[paramB:]) {
return false
}
P, err := goldilocks.FromBytes(public)
if err != nil {
return false
}
H := sha3.NewShake256()
var PHM []byte
if preHash {
var h [64]byte
_, _ = H.Write(message)
_, _ = H.Read(h[:])
PHM = h[:]
H.Reset()
} else {
PHM = message
}
var hRAM [hashSize]byte
R := signature[:paramB]
writeDom(&H, ctx, preHash)
_, _ = H.Write(R)
_, _ = H.Write(public)
_, _ = H.Write(PHM)
_, _ = H.Read(hRAM[:])
k := &goldilocks.Scalar{}
k.FromBytes(hRAM[:])
S := &goldilocks.Scalar{}
S.FromBytes(signature[paramB:])
encR := (&[paramB]byte{})[:]
P.Neg()
_ = goldilocks.Curve{}.CombinedMult(S, k, P).ToBytes(encR)
return bytes.Equal(R, encR)
}
// VerifyAny returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports all the two signature variants defined in RFC-8032,
// namely Ed448 (or pure EdDSA) and Ed448Ph.
// The opts.HashFunc() must return zero, this can be achieved by passing
// crypto.Hash(0) as the value for opts.
// Use a SignerOptions struct to pass a context string for signing.
func VerifyAny(public PublicKey, message, signature []byte, opts crypto.SignerOpts) bool {
var ctx string
var scheme SchemeID
if o, ok := opts.(SignerOptions); ok {
ctx = o.Context
scheme = o.Scheme
}
switch true {
case scheme == ED448 && opts.HashFunc() == crypto.Hash(0):
return Verify(public, message, signature, ctx)
case scheme == ED448Ph && opts.HashFunc() == crypto.Hash(0):
return VerifyPh(public, message, signature, ctx)
default:
return false
}
}
// Verify returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports the signature variant defined in RFC-8032: Ed448,
// also known as the pure version of EdDSA.
func Verify(public PublicKey, message, signature []byte, ctx string) bool {
return verify(public, message, signature, []byte(ctx), false)
}
// VerifyPh returns true if the signature is valid. Failure cases are invalid
// signature, or when the public key cannot be decoded.
// This function supports the signature variant defined in RFC-8032: Ed448ph,
// meaning it internally hashes the message using SHAKE-256.
// Context could be passed to this function, which length should be no more than
// 255. It can be empty.
func VerifyPh(public PublicKey, message, signature []byte, ctx string) bool {
return verify(public, message, signature, []byte(ctx), true)
}
func deriveSecretScalar(s *goldilocks.Scalar, h []byte) {
h[0] &= 0xFC // The two least significant bits of the first octet are cleared,
h[paramB-1] = 0x00 // all eight bits the last octet are cleared, and
h[paramB-2] |= 0x80 // the highest bit of the second to last octet is set.
s.FromBytes(h[:paramB])
}
// isLessThanOrder returns true if 0 <= x < order and if the last byte of x is zero.
func isLessThanOrder(x []byte) bool {
order := goldilocks.Curve{}.Order()
i := len(order) - 1
for i > 0 && x[i] == order[i] {
i--
}
return x[paramB-1] == 0 && x[i] < order[i]
}
func writeDom(h io.Writer, ctx []byte, preHash bool) {
dom4 := "SigEd448"
_, _ = h.Write([]byte(dom4))
if preHash {
_, _ = h.Write([]byte{byte(0x01), byte(len(ctx))})
} else {
_, _ = h.Write([]byte{byte(0x00), byte(len(ctx))})
}
_, _ = h.Write(ctx)
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/ed448/signapi.go
================================================
package ed448
import (
"crypto/rand"
"encoding/asn1"
"github.com/cloudflare/circl/sign"
)
var sch sign.Scheme = &scheme{}
// Scheme returns a signature interface.
func Scheme() sign.Scheme { return sch }
type scheme struct{}
func (*scheme) Name() string { return "Ed448" }
func (*scheme) PublicKeySize() int { return PublicKeySize }
func (*scheme) PrivateKeySize() int { return PrivateKeySize }
func (*scheme) SignatureSize() int { return SignatureSize }
func (*scheme) SeedSize() int { return SeedSize }
func (*scheme) TLSIdentifier() uint { return 0x0808 }
func (*scheme) SupportsContext() bool { return true }
func (*scheme) Oid() asn1.ObjectIdentifier {
return asn1.ObjectIdentifier{1, 3, 101, 113}
}
func (*scheme) GenerateKey() (sign.PublicKey, sign.PrivateKey, error) {
return GenerateKey(rand.Reader)
}
func (*scheme) Sign(
sk sign.PrivateKey,
message []byte,
opts *sign.SignatureOpts,
) []byte {
priv, ok := sk.(PrivateKey)
if !ok {
panic(sign.ErrTypeMismatch)
}
ctx := ""
if opts != nil {
ctx = opts.Context
}
return Sign(priv, message, ctx)
}
func (*scheme) Verify(
pk sign.PublicKey,
message, signature []byte,
opts *sign.SignatureOpts,
) bool {
pub, ok := pk.(PublicKey)
if !ok {
panic(sign.ErrTypeMismatch)
}
ctx := ""
if opts != nil {
ctx = opts.Context
}
return Verify(pub, message, signature, ctx)
}
func (*scheme) DeriveKey(seed []byte) (sign.PublicKey, sign.PrivateKey) {
privateKey := NewKeyFromSeed(seed)
publicKey := make(PublicKey, PublicKeySize)
copy(publicKey, privateKey[SeedSize:])
return publicKey, privateKey
}
func (*scheme) UnmarshalBinaryPublicKey(buf []byte) (sign.PublicKey, error) {
if len(buf) < PublicKeySize {
return nil, sign.ErrPubKeySize
}
pub := make(PublicKey, PublicKeySize)
copy(pub, buf[:PublicKeySize])
return pub, nil
}
func (*scheme) UnmarshalBinaryPrivateKey(buf []byte) (sign.PrivateKey, error) {
if len(buf) < PrivateKeySize {
return nil, sign.ErrPrivKeySize
}
priv := make(PrivateKey, PrivateKeySize)
copy(priv, buf[:PrivateKeySize])
return priv, nil
}
================================================
FILE: vendor/github.com/cloudflare/circl/sign/sign.go
================================================
// Package sign provides unified interfaces for signature schemes.
//
// A register of schemes is available in the package
//
// github.com/cloudflare/circl/sign/schemes
package sign
import (
"crypto"
"encoding"
"errors"
)
type SignatureOpts struct {
// If non-empty, includes the given context in the signature if supported
// and will cause an error during signing otherwise.
Context string
}
// A public key is used to verify a signature set by the corresponding private
// key.
type PublicKey interface {
// Returns the signature scheme for this public key.
Scheme() Scheme
Equal(crypto.PublicKey) bool
encoding.BinaryMarshaler
crypto.PublicKey
}
// A private key allows one to create signatures.
type PrivateKey interface {
// Returns the signature scheme for this private key.
Scheme() Scheme
Equal(crypto.PrivateKey) bool
// For compatibility with Go standard library
crypto.Signer
crypto.PrivateKey
encoding.BinaryMarshaler
}
// A Scheme represents a specific instance of a signature scheme.
type Scheme interface {
// Name of the scheme.
Name() string
// GenerateKey creates a new key-pair.
GenerateKey() (PublicKey, PrivateKey, error)
// Creates a signature using the PrivateKey on the given message and
// returns the signature. opts are additional options which can be nil.
//
// Panics if key is nil or wrong type or opts context is not supported.
Sign(sk PrivateKey, message []byte, opts *SignatureOpts) []byte
// Checks whether the given signature is a valid signature set by
// the private key corresponding to the given public key on the
// given message. opts are additional options which can be nil.
//
// Panics if key is nil or wrong type or opts context is not supported.
Verify(pk PublicKey, message []byte, signature []byte, opts *SignatureOpts) bool
// Deterministically derives a keypair from a seed. If you're unsure,
// you're better off using GenerateKey().
//
// Panics if seed is not of length SeedSize().
DeriveKey(seed []byte) (PublicKey, PrivateKey)
// Unmarshals a PublicKey from the provided buffer.
UnmarshalBinaryPublicKey([]byte) (PublicKey, error)
// Unmarshals a PublicKey from the provided buffer.
UnmarshalBinaryPrivateKey([]byte) (PrivateKey, error)
// Size of binary marshalled public keys.
PublicKeySize() int
// Size of binary marshalled public keys.
PrivateKeySize() int
// Size of signatures.
SignatureSize() int
// Size of seeds.
SeedSize() int
// Returns whether contexts are supported.
SupportsContext() bool
}
var (
// ErrTypeMismatch is the error used if types of, for instance, private
// and public keys don't match.
ErrTypeMismatch = errors.New("types mismatch")
// ErrSeedSize is the error used if the provided seed is of the wrong
// size.
ErrSeedSize = errors.New("wrong seed size")
// ErrPubKeySize is the error used if the provided public key is of
// the wrong size.
ErrPubKeySize = errors.New("wrong size for public key")
// ErrPrivKeySize is the error used if the provided private key is of
// the wrong size.
ErrPrivKeySize = errors.New("wrong size for private key")
// ErrContextNotSupported is the error used if a context is not
// supported.
ErrContextNotSupported = errors.New("context not supported")
)
================================================
FILE: vendor/github.com/cosiner/argv/.travis.yml
================================================
language: go
sudo: false
go:
- 1.8
- 1.7.5
- 1.7.4
- 1.7.3
- 1.7.2
- 1.7.1
- 1.7
- tip
- 1.6.4
- 1.6.3
- 1.6.2
- 1.6.1
- 1.6
- 1.5.4
- 1.5.3
- 1.5.2
- 1.5.1
- 1.5
- 1.4.3
- 1.4.2
- 1.4.1
- 1.4
- 1.3.3
- 1.3.2
- 1.3.1
- 1.3
- 1.2.2
- 1.2.1
- 1.2
- 1.1.2
- 1.1.1
- 1.1
before_install:
- go get github.com/mattn/goveralls
script:
- $HOME/gopath/bin/goveralls -service=travis-ci
notifications:
email:
on_success: never
matrix:
fast_finish: true
allow_failures:
- go: tip
- go: 1.6.4
- go: 1.6.3
- go: 1.6.2
- go: 1.6.1
- go: 1.6
- go: 1.5.4
- go: 1.5.3
- go: 1.5.2
- go: 1.5.1
- go: 1.5
- go: 1.4.3
- go: 1.4.2
- go: 1.4.1
- go: 1.4
- go: 1.3.3
- go: 1.3.2
- go: 1.3.1
- go: 1.3
- go: 1.2.2
- go: 1.2.1
- go: 1.2
- go: 1.1.2
- go: 1.1.1
- go: 1.1
================================================
FILE: vendor/github.com/cosiner/argv/LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2017 aihui zhu
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/cosiner/argv/README.md
================================================
# Argv
[](https://godoc.org/github.com/cosiner/argv)
[](https://travis-ci.org/cosiner/argv)
[](https://coveralls.io/github/cosiner/argv)
[](https://goreportcard.com/report/github.com/cosiner/argv)
Argv is a library for [Go](https://golang.org) to split command line string into arguments array.
# Documentation
Documentation can be found at [Godoc](https://godoc.org/github.com/cosiner/argv)
# Example
```Go
func TestArgv(t *testing.T) {
args, err := Argv(" ls `echo /` | wc -l ", func(backquoted string) (string, error) {
return backquoted, nil
}, nil)
if err != nil {
t.Fatal(err)
}
expects := [][]string{
[]string{"ls", "echo /"},
[]string{"wc", "-l"},
}
if !reflect.DeepEqual(args, expects) {
t.Fatal(args)
}
}
```
# LICENSE
MIT.
================================================
FILE: vendor/github.com/cosiner/argv/argv.go
================================================
// Package argv parse command line string into arguments array using the bash syntax.
package argv
// Argv split cmdline string as array of argument array by the '|' character.
//
// The parsing rules is same as bash. The environment variable will be replaced
// and string surround by '`' will be passed to reverse quote parser.
func Argv(cmdline string, backquoteExpander, stringExpander Expander) ([][]string, error) {
return NewParser(NewScanner(cmdline), backquoteExpander, stringExpander).Parse()
}
================================================
FILE: vendor/github.com/cosiner/argv/cmd.go
================================================
package argv
import (
"errors"
"io"
"os"
"os/exec"
)
func Cmds(args ...[]string) ([]*exec.Cmd, error) {
var cmds []*exec.Cmd
for _, argv := range args {
if len(argv) == 0 {
return nil, errors.New("invalid cmd")
}
cmds = append(cmds, exec.Command(argv[0], argv[1:]...))
}
return cmds, nil
}
func Start(stdin io.Reader, stdout, stderr io.Writer, cmds ...*exec.Cmd) error {
if stdin == nil {
stdin = os.Stdin
}
if stdout == nil {
stdout = os.Stdout
}
if stderr == nil {
stderr = os.Stderr
}
l := len(cmds)
if l == 0 {
return nil
}
var err error
for i := 0; i < l; i++ {
if i == 0 {
cmds[i].Stdin = stdin
} else {
cmds[i].Stdin, err = cmds[i-1].StdoutPipe()
if stderr != nil {
break
}
}
cmds[i].Stderr = stderr
if i == l-1 {
cmds[i].Stdout = stdout
}
}
if err != nil {
return err
}
for i := range cmds {
err = cmds[i].Start()
if err != nil {
return err
}
}
return nil
}
func Pipe(stdin io.Reader, stdout, stderr io.Writer, cmds ...*exec.Cmd) error {
err := Start(stdin, stdout, stderr, cmds...)
if err != nil {
return err
}
for i := range cmds {
err = cmds[i].Wait()
if err != nil {
return err
}
}
return nil
}
================================================
FILE: vendor/github.com/cosiner/argv/parser.go
================================================
package argv
import (
"errors"
"fmt"
"os"
)
type (
Expander func(string) (string, error)
// Parser take tokens from Scanner, and do syntax checking, and generate the splitted arguments array.
Parser struct {
s *Scanner
tokbuf []Token
backQuoteExpander Expander
stringExpander Expander
sections [][]string
currSection []string
currStrValid bool
currStr []rune
}
)
// NewParser create a cmdline string parser.
func NewParser(s *Scanner, backQuoteExpander, stringExpander Expander) *Parser {
if backQuoteExpander == nil {
backQuoteExpander = func(r string) (string, error) {
return r, fmt.Errorf("back quote doesn't allowed")
}
}
if stringExpander == nil {
stringExpander = func(runes string) (string, error) {
s := os.ExpandEnv(string(runes))
return s, nil
}
}
return &Parser{
s: s,
backQuoteExpander: backQuoteExpander,
stringExpander: stringExpander,
}
}
func (p *Parser) nextToken() (Token, error) {
if l := len(p.tokbuf); l > 0 {
tok := p.tokbuf[l-1]
p.tokbuf = p.tokbuf[:l-1]
return tok, nil
}
return p.s.Next()
}
var (
// ErrInvalidSyntax was reported if there is a syntax error in command line string.
ErrInvalidSyntax = errors.New("invalid syntax")
)
func (p *Parser) unreadToken(tok Token) {
p.tokbuf = append(p.tokbuf, tok)
}
// Parse split command line string into arguments array.
//
// EBNF:
// Cmdline = Section [ Pipe Cmdline ]
// Section = [Space] SpacedSection { SpacedSection }
// SpacedSection = MultipleUnit [Space]
// MultipleUnit = Unit {Unit}
// Unit = String | BackQuote | SingleQuote | DoubleQuote
func (p *Parser) Parse() ([][]string, error) {
err := p.cmdline()
if err != nil {
return nil, err
}
return p.sections, nil
}
func (p *Parser) cmdline() error {
err := p.section()
if err != nil {
return err
}
p.endSection()
tok, err := p.nextToken()
if err != nil {
return err
}
if tok.Type == TokEOF {
return nil
}
if !p.accept(tok.Type, TokPipe) {
return ErrInvalidSyntax
}
return p.cmdline()
}
func (p *Parser) section() error {
leftSpace, err := p.optional(TokSpace)
if err != nil {
return err
}
var hasUnit bool
for {
unit, ok, err := p.spacedSection()
if err != nil {
return err
}
if !ok {
break
}
hasUnit = true
err = p.appendUnit(leftSpace, unit)
if err != nil {
return err
}
leftSpace = unit.rightSpace
}
if !hasUnit {
return ErrInvalidSyntax
}
return nil
}
type unit struct {
rightSpace bool
toks []Token
}
func (p *Parser) spacedSection() (u unit, ok bool, err error) {
u.toks, ok, err = p.multipleUnit()
if err != nil {
return
}
if !ok {
return u, false, nil
}
u.rightSpace, err = p.optional(TokSpace)
return
}
func (p *Parser) multipleUnit() ([]Token, bool, error) {
var (
toks []Token
)
for {
tok, ok, err := p.unit()
if err != nil {
return nil, false, err
}
if !ok {
break
}
toks = append(toks, tok)
}
return toks, len(toks) > 0, nil
}
func (p *Parser) unit() (Token, bool, error) {
tok, err := p.nextToken()
if err != nil {
return tok, false, err
}
if p.accept(tok.Type, TokString, TokStringSingleQuote, TokStringDoubleQuote, TokBackQuote) {
return tok, true, nil
}
p.unreadToken(tok)
return tok, false, nil
}
func (p *Parser) optional(typ TokenType) (bool, error) {
tok, err := p.nextToken()
if err != nil {
return false, err
}
var ok bool
if ok = p.accept(tok.Type, typ); !ok {
p.unreadToken(tok)
}
return ok, nil
}
func (p *Parser) accept(t TokenType, types ...TokenType) bool {
for _, typ := range types {
if t == typ {
return true
}
}
return false
}
func (p *Parser) appendUnit(leftSpace bool, u unit) error {
if leftSpace {
p.currStr = p.currStr[:0]
}
for _, tok := range u.toks {
switch tok.Type {
case TokBackQuote:
expanded, err := p.backQuoteExpander(string(tok.Value))
if err != nil {
return fmt.Errorf("expand string back quoted failed: %s, %w", string(tok.Value), err)
}
p.currStr = append(p.currStr, []rune(expanded)...)
case TokString:
expanded, err := p.stringExpander(string(tok.Value))
if err != nil {
return fmt.Errorf("expand string failed: %s, %w", string(tok.Value), err)
}
p.currStr = append(p.currStr, []rune(expanded)...)
case TokStringSingleQuote:
p.currStr = append(p.currStr, tok.Value...)
case TokStringDoubleQuote:
expanded, err := p.stringExpander(string(tok.Value))
if err != nil {
return fmt.Errorf("expand string double quoted failed: %s, %w", string(tok.Value), err)
}
p.currStr = append(p.currStr, []rune(expanded)...)
}
}
p.currStrValid = true
if u.rightSpace {
p.currSection = append(p.currSection, string(p.currStr))
p.currStr = p.currStr[:0]
p.currStrValid = false
}
return nil
}
func (p *Parser) endSection() {
if p.currStrValid {
p.currSection = append(p.currSection, string(p.currStr))
}
p.currStr = p.currStr[:0]
p.currStrValid = false
if len(p.currSection) > 0 {
p.sections = append(p.sections, p.currSection)
p.currSection = nil
}
}
================================================
FILE: vendor/github.com/cosiner/argv/scanner.go
================================================
package argv
import (
"unicode"
)
// Scanner is a cmdline string scanner.
//
// It split cmdline string to tokens: space, string, pipe, reverse quote string.
type Scanner struct {
text []rune
rpos int
}
// NewScanner create a scanner and init it's internal states.
func NewScanner(text string) *Scanner {
return &Scanner{
text: []rune(text),
}
}
const _RuneEOF = 0
func (s *Scanner) nextRune() rune {
if s.rpos >= len(s.text) {
return _RuneEOF
}
r := s.text[s.rpos]
s.rpos++
return r
}
func (s *Scanner) unreadRune(r rune) {
if r != _RuneEOF {
s.rpos--
}
}
func (s *Scanner) isEscapeChars(r rune) (rune, bool) {
switch r {
case 'a':
return '\a', true
case 'b':
return '\b', true
case 'f':
return '\f', true
case 'n':
return '\n', true
case 'r':
return '\r', true
case 't':
return '\t', true
case 'v':
return '\v', true
case '\\':
return '\\', true
case '$':
return '$', true
}
return r, false
}
// TokenType is the type of tokens recognized by the scanner.
type TokenType uint32
// Token is generated by the scanner with a type and value.
type Token struct {
Type TokenType
Value []rune
}
const (
// TokString for string
TokString TokenType = iota + 1
TokStringSingleQuote
TokStringDoubleQuote
// TokPipe is the '|' character
TokPipe
// TokBackQuote is reverse quoted string
TokBackQuote
// TokSpace represent space character sequence
TokSpace
// TokEOF means the input end.
TokEOF
)
// Next return next token, if it reach the end, TOK_EOF will be returned.
//
// Error is returned for invalid syntax such as unpaired quotes.
func (s *Scanner) Next() (Token, error) {
const (
Initial = iota + 1
Space
BackQuote
String
StringSingleQuote
StringDoubleQuote
)
var (
tok Token
state uint8 = Initial
)
for {
r := s.nextRune()
switch state {
case Initial:
switch {
case r == _RuneEOF:
tok.Type = TokEOF
return tok, nil
case r == '|':
tok.Type = TokPipe
return tok, nil
case r == '`':
state = BackQuote
case unicode.IsSpace(r):
state = Space
s.unreadRune(r)
case r == '\'':
state = StringSingleQuote
case r == '"':
state = StringDoubleQuote
default:
state = String
s.unreadRune(r)
}
case Space:
if r == _RuneEOF || !unicode.IsSpace(r) {
s.unreadRune(r)
tok.Type = TokSpace
return tok, nil
}
case BackQuote:
switch r {
case _RuneEOF:
return tok, ErrInvalidSyntax
case '`':
tok.Type = TokBackQuote
return tok, nil
default:
tok.Value = append(tok.Value, r)
}
case String:
switch {
case r == _RuneEOF, r == '|', r == '`', r == '\'', r == '"', unicode.IsSpace(r):
tok.Type = TokString
s.unreadRune(r)
return tok, nil
case r == '\\':
nr := s.nextRune()
if nr == _RuneEOF {
return tok, ErrInvalidSyntax
}
tok.Value = append(tok.Value, nr)
default:
tok.Value = append(tok.Value, r)
}
case StringSingleQuote, StringDoubleQuote:
switch r {
case _RuneEOF:
return tok, ErrInvalidSyntax
case '\'', '"':
if singleQuote := state == StringSingleQuote; singleQuote == (r == '\'') {
if singleQuote {
tok.Type = TokStringSingleQuote
} else {
tok.Type = TokStringDoubleQuote
}
return tok, nil
} else {
tok.Value = append(tok.Value, r)
}
case '\\':
nr := s.nextRune()
if escape, ok := s.isEscapeChars(nr); ok {
tok.Value = append(tok.Value, escape)
} else {
tok.Value = append(tok.Value, r)
s.unreadRune(nr)
}
default:
tok.Value = append(tok.Value, r)
}
}
}
}
// Scan is a utility function help split input text as tokens.
func Scan(text string) ([]Token, error) {
s := NewScanner(text)
var tokens []Token
for {
tok, err := s.Next()
if err != nil {
return nil, err
}
tokens = append(tokens, tok)
if tok.Type == TokEOF {
break
}
}
return tokens, nil
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/CHANGELOG.md
================================================
# Changelog #
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased] ##
## [0.3.6] - 2024-12-17 ##
### Compatibility ###
- The minimum Go version requirement for `filepath-securejoin` is now Go 1.18
(we use generics internally).
For reference, `filepath-securejoin@v0.3.0` somewhat-arbitrarily bumped the
Go version requirement to 1.21.
While we did make some use of Go 1.21 stdlib features (and in principle Go
versions <= 1.21 are no longer even supported by upstream anymore), some
downstreams have complained that the version bump has meant that they have to
do workarounds when backporting fixes that use the new `filepath-securejoin`
API onto old branches. This is not an ideal situation, but since using this
library is probably better for most downstreams than a hand-rolled
workaround, we now have compatibility shims that allow us to build on older
Go versions.
- Lower minimum version requirement for `golang.org/x/sys` to `v0.18.0` (we
need the wrappers for `fsconfig(2)`), which should also make backporting
patches to older branches easier.
## [0.3.5] - 2024-12-06 ##
### Fixed ###
- `MkdirAll` will now no longer return an `EEXIST` error if two racing
processes are creating the same directory. We will still verify that the path
is a directory, but this will avoid spurious errors when multiple threads or
programs are trying to `MkdirAll` the same path. opencontainers/runc#4543
## [0.3.4] - 2024-10-09 ##
### Fixed ###
- Previously, some testing mocks we had resulted in us doing `import "testing"`
in non-`_test.go` code, which made some downstreams like Kubernetes unhappy.
This has been fixed. (#32)
## [0.3.3] - 2024-09-30 ##
### Fixed ###
- The mode and owner verification logic in `MkdirAll` has been removed. This
was originally intended to protect against some theoretical attacks but upon
further consideration these protections don't actually buy us anything and
they were causing spurious errors with more complicated filesystem setups.
- The "is the created directory empty" logic in `MkdirAll` has also been
removed. This was not causing us issues yet, but some pseudofilesystems (such
as `cgroup`) create non-empty directories and so this logic would've been
wrong for such cases.
## [0.3.2] - 2024-09-13 ##
### Changed ###
- Passing the `S_ISUID` or `S_ISGID` modes to `MkdirAllInRoot` will now return
an explicit error saying that those bits are ignored by `mkdirat(2)`. In the
past a different error was returned, but since the silent ignoring behaviour
is codified in the man pages a more explicit error seems apt. While silently
ignoring these bits would be the most compatible option, it could lead to
users thinking their code sets these bits when it doesn't. Programs that need
to deal with compatibility can mask the bits themselves. (#23, #25)
### Fixed ###
- If a directory has `S_ISGID` set, then all child directories will have
`S_ISGID` set when created and a different gid will be used for any inode
created under the directory. Previously, the "expected owner and mode"
validation in `securejoin.MkdirAll` did not correctly handle this. We now
correctly handle this case. (#24, #25)
## [0.3.1] - 2024-07-23 ##
### Changed ###
- By allowing `Open(at)InRoot` to opt-out of the extra work done by `MkdirAll`
to do the necessary "partial lookups", `Open(at)InRoot` now does less work
for both implementations (resulting in a many-fold decrease in the number of
operations for `openat2`, and a modest improvement for non-`openat2`) and is
far more guaranteed to match the correct `openat2(RESOLVE_IN_ROOT)`
behaviour.
- We now use `readlinkat(fd, "")` where possible. For `Open(at)InRoot` this
effectively just means that we no longer risk getting spurious errors during
rename races. However, for our hardened procfs handler, this in theory should
prevent mount attacks from tricking us when doing magic-link readlinks (even
when using the unsafe host `/proc` handle). Unfortunately `Reopen` is still
potentially vulnerable to those kinds of somewhat-esoteric attacks.
Technically this [will only work on post-2.6.39 kernels][linux-readlinkat-emptypath]
but it seems incredibly unlikely anyone is using `filepath-securejoin` on a
pre-2011 kernel.
### Fixed ###
- Several improvements were made to the errors returned by `Open(at)InRoot` and
`MkdirAll` when dealing with invalid paths under the emulated (ie.
non-`openat2`) implementation. Previously, some paths would return the wrong
error (`ENOENT` when the last component was a non-directory), and other paths
would be returned as though they were acceptable (trailing-slash components
after a non-directory would be ignored by `Open(at)InRoot`).
These changes were done to match `openat2`'s behaviour and purely is a
consistency fix (most users are going to be using `openat2` anyway).
[linux-readlinkat-emptypath]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=65cfc6722361570bfe255698d9cd4dccaf47570d
## [0.3.0] - 2024-07-11 ##
### Added ###
- A new set of `*os.File`-based APIs have been added. These are adapted from
[libpathrs][] and we strongly suggest using them if possible (as they provide
far more protection against attacks than `SecureJoin`):
- `Open(at)InRoot` resolves a path inside a rootfs and returns an `*os.File`
handle to the path. Note that the handle returned is an `O_PATH` handle,
which cannot be used for reading or writing (as well as some other
operations -- [see open(2) for more details][open.2])
- `Reopen` takes an `O_PATH` file handle and safely re-opens it to upgrade
it to a regular handle. This can also be used with non-`O_PATH` handles,
but `O_PATH` is the most obvious application.
- `MkdirAll` is an implementation of `os.MkdirAll` that is safe to use to
create a directory tree within a rootfs.
As these are new APIs, they may change in the future. However, they should be
safe to start migrating to as we have extensive tests ensuring they behave
correctly and are safe against various races and other attacks.
[libpathrs]: https://github.com/openSUSE/libpathrs
[open.2]: https://www.man7.org/linux/man-pages/man2/open.2.html
## [0.2.5] - 2024-05-03 ##
### Changed ###
- Some minor changes were made to how lexical components (like `..` and `.`)
are handled during path generation in `SecureJoin`. There is no behaviour
change as a result of this fix (the resulting paths are the same).
### Fixed ###
- The error returned when we hit a symlink loop now references the correct
path. (#10)
## [0.2.4] - 2023-09-06 ##
### Security ###
- This release fixes a potential security issue in filepath-securejoin when
used on Windows ([GHSA-6xv5-86q9-7xr8][], which could be used to generate
paths outside of the provided rootfs in certain cases), as well as improving
the overall behaviour of filepath-securejoin when dealing with Windows paths
that contain volume names. Thanks to Paulo Gomes for discovering and fixing
these issues.
### Fixed ###
- Switch to GitHub Actions for CI so we can test on Windows as well as Linux
and MacOS.
[GHSA-6xv5-86q9-7xr8]: https://github.com/advisories/GHSA-6xv5-86q9-7xr8
## [0.2.3] - 2021-06-04 ##
### Changed ###
- Switch to Go 1.13-style `%w` error wrapping, letting us drop the dependency
on `github.com/pkg/errors`.
## [0.2.2] - 2018-09-05 ##
### Changed ###
- Use `syscall.ELOOP` as the base error for symlink loops, rather than our own
(internal) error. This allows callers to more easily use `errors.Is` to check
for this case.
## [0.2.1] - 2018-09-05 ##
### Fixed ###
- Use our own `IsNotExist` implementation, which lets us handle `ENOTDIR`
properly within `SecureJoin`.
## [0.2.0] - 2017-07-19 ##
We now have 100% test coverage!
### Added ###
- Add a `SecureJoinVFS` API that can be used for mocking (as we do in our new
tests) or for implementing custom handling of lookup operations (such as for
rootless containers, where work is necessary to access directories with weird
modes because we don't have `CAP_DAC_READ_SEARCH` or `CAP_DAC_OVERRIDE`).
## 0.1.0 - 2017-07-19
This is our first release of `github.com/cyphar/filepath-securejoin`,
containing a full implementation with a coverage of 93.5% (the only missing
cases are the error cases, which are hard to mocktest at the moment).
[Unreleased]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.6...HEAD
[0.3.6]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.5...v0.3.6
[0.3.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.4...v0.3.5
[0.3.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.3...v0.3.4
[0.3.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.2...v0.3.3
[0.3.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.5...v0.3.0
[0.2.5]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.4...v0.2.5
[0.2.4]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4
[0.2.3]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.2...v0.2.3
[0.2.2]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/cyphar/filepath-securejoin/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/cyphar/filepath-securejoin/compare/v0.1.0...v0.2.0
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/LICENSE
================================================
Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
Copyright (C) 2017-2024 SUSE LLC. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/README.md
================================================
## `filepath-securejoin` ##
[](https://pkg.go.dev/github.com/cyphar/filepath-securejoin)
[](https://github.com/cyphar/filepath-securejoin/actions/workflows/ci.yml)
### Old API ###
This library was originally just an implementation of `SecureJoin` which was
[intended to be included in the Go standard library][go#20126] as a safer
`filepath.Join` that would restrict the path lookup to be inside a root
directory.
The implementation was based on code that existed in several container
runtimes. Unfortunately, this API is **fundamentally unsafe** against attackers
that can modify path components after `SecureJoin` returns and before the
caller uses the path, allowing for some fairly trivial TOCTOU attacks.
`SecureJoin` (and `SecureJoinVFS`) are still provided by this library to
support legacy users, but new users are strongly suggested to avoid using
`SecureJoin` and instead use the [new api](#new-api) or switch to
[libpathrs][libpathrs].
With the above limitations in mind, this library guarantees the following:
* If no error is set, the resulting string **must** be a child path of
`root` and will not contain any symlink path components (they will all be
expanded).
* When expanding symlinks, all symlink path components **must** be resolved
relative to the provided root. In particular, this can be considered a
userspace implementation of how `chroot(2)` operates on file paths. Note that
these symlinks will **not** be expanded lexically (`filepath.Clean` is not
called on the input before processing).
* Non-existent path components are unaffected by `SecureJoin` (similar to
`filepath.EvalSymlinks`'s semantics).
* The returned path will always be `filepath.Clean`ed and thus not contain any
`..` components.
A (trivial) implementation of this function on GNU/Linux systems could be done
with the following (note that this requires root privileges and is far more
opaque than the implementation in this library, and also requires that
`readlink` is inside the `root` path and is trustworthy):
```go
package securejoin
import (
"os/exec"
"path/filepath"
)
func SecureJoin(root, unsafePath string) (string, error) {
unsafePath = string(filepath.Separator) + unsafePath
cmd := exec.Command("chroot", root,
"readlink", "--canonicalize-missing", "--no-newline", unsafePath)
output, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
expanded := string(output)
return filepath.Join(root, expanded), nil
}
```
[libpathrs]: https://github.com/openSUSE/libpathrs
[go#20126]: https://github.com/golang/go/issues/20126
### New API ###
While we recommend users switch to [libpathrs][libpathrs] as soon as it has a
stable release, some methods implemented by libpathrs have been ported to this
library to ease the transition. These APIs are only supported on Linux.
These APIs are implemented such that `filepath-securejoin` will
opportunistically use certain newer kernel APIs that make these operations far
more secure. In particular:
* All of the lookup operations will use [`openat2`][openat2.2] on new enough
kernels (Linux 5.6 or later) to restrict lookups through magic-links and
bind-mounts (for certain operations) and to make use of `RESOLVE_IN_ROOT` to
efficiently resolve symlinks within a rootfs.
* The APIs provide hardening against a malicious `/proc` mount to either detect
or avoid being tricked by a `/proc` that is not legitimate. This is done
using [`openat2`][openat2.2] for all users, and privileged users will also be
further protected by using [`fsopen`][fsopen.2] and [`open_tree`][open_tree.2]
(Linux 5.2 or later).
[openat2.2]: https://www.man7.org/linux/man-pages/man2/openat2.2.html
[fsopen.2]: https://github.com/brauner/man-pages-md/blob/main/fsopen.md
[open_tree.2]: https://github.com/brauner/man-pages-md/blob/main/open_tree.md
#### `OpenInRoot` ####
```go
func OpenInRoot(root, unsafePath string) (*os.File, error)
func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error)
func Reopen(handle *os.File, flags int) (*os.File, error)
```
`OpenInRoot` is a much safer version of
```go
path, err := securejoin.SecureJoin(root, unsafePath)
file, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)
```
that protects against various race attacks that could lead to serious security
issues, depending on the application. Note that the returned `*os.File` is an
`O_PATH` file descriptor, which is quite restricted. Callers will probably need
to use `Reopen` to get a more usable handle (this split is done to provide
useful features like PTY spawning and to avoid users accidentally opening bad
inodes that could cause a DoS).
Callers need to be careful in how they use the returned `*os.File`. Usually it
is only safe to operate on the handle directly, and it is very easy to create a
security issue. [libpathrs][libpathrs] provides far more helpers to make using
these handles safer -- there is currently no plan to port them to
`filepath-securejoin`.
`OpenatInRoot` is like `OpenInRoot` except that the root is provided using an
`*os.File`. This allows you to ensure that multiple `OpenatInRoot` (or
`MkdirAllHandle`) calls are operating on the same rootfs.
> **NOTE**: Unlike `SecureJoin`, `OpenInRoot` will error out as soon as it hits
> a dangling symlink or non-existent path. This is in contrast to `SecureJoin`
> which treated non-existent components as though they were real directories,
> and would allow for partial resolution of dangling symlinks. These behaviours
> are at odds with how Linux treats non-existent paths and dangling symlinks,
> and so these are no longer allowed.
#### `MkdirAll` ####
```go
func MkdirAll(root, unsafePath string, mode int) error
func MkdirAllHandle(root *os.File, unsafePath string, mode int) (*os.File, error)
```
`MkdirAll` is a much safer version of
```go
path, err := securejoin.SecureJoin(root, unsafePath)
err = os.MkdirAll(path, mode)
```
that protects against the same kinds of races that `OpenInRoot` protects
against.
`MkdirAllHandle` is like `MkdirAll` except that the root is provided using an
`*os.File` (the reason for this is the same as with `OpenatInRoot`) and an
`*os.File` of the final created directory is returned (this directory is
guaranteed to be effectively identical to the directory created by
`MkdirAllHandle`, which is not possible to ensure by just using `OpenatInRoot`
after `MkdirAll`).
> **NOTE**: Unlike `SecureJoin`, `MkdirAll` will error out as soon as it hits
> a dangling symlink or non-existent path. This is in contrast to `SecureJoin`
> which treated non-existent components as though they were real directories,
> and would allow for partial resolution of dangling symlinks. These behaviours
> are at odds with how Linux treats non-existent paths and dangling symlinks,
> and so these are no longer allowed. This means that `MkdirAll` will not
> create non-existent directories referenced by a dangling symlink.
### License ###
The license of this project is the same as Go, which is a BSD 3-clause license
available in the `LICENSE` file.
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/VERSION
================================================
0.3.6
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/doc.go
================================================
// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
// Copyright (C) 2017-2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package securejoin implements a set of helpers to make it easier to write Go
// code that is safe against symlink-related escape attacks. The primary idea
// is to let you resolve a path within a rootfs directory as if the rootfs was
// a chroot.
//
// securejoin has two APIs, a "legacy" API and a "modern" API.
//
// The legacy API is [SecureJoin] and [SecureJoinVFS]. These methods are
// **not** safe against race conditions where an attacker changes the
// filesystem after (or during) the [SecureJoin] operation.
//
// The new API is made up of [OpenInRoot] and [MkdirAll] (and derived
// functions). These are safe against racing attackers and have several other
// protections that are not provided by the legacy API. There are many more
// operations that most programs expect to be able to do safely, but we do not
// provide explicit support for them because we want to encourage users to
// switch to [libpathrs](https://github.com/openSUSE/libpathrs) which is a
// cross-language next-generation library that is entirely designed around
// operating on paths safely.
//
// securejoin has been used by several container runtimes (Docker, runc,
// Kubernetes, etc) for quite a few years as a de-facto standard for operating
// on container filesystem paths "safely". However, most users still use the
// legacy API which is unsafe against various attacks (there is a fairly long
// history of CVEs in dependent as a result). Users should switch to the modern
// API as soon as possible (or even better, switch to libpathrs).
//
// This project was initially intended to be included in the Go standard
// library, but [it was rejected](https://go.dev/issue/20126). There is now a
// [new Go proposal](https://go.dev/issue/67002) for a safe path resolution API
// that shares some of the goals of filepath-securejoin. However, that design
// is intended to work like `openat2(RESOLVE_BENEATH)` which does not fit the
// usecase of container runtimes and most system tools.
package securejoin
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_go120.go
================================================
//go:build linux && go1.20
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"fmt"
)
// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
// is only guaranteed to give you baseErr.
func wrapBaseError(baseErr, extraErr error) error {
return fmt.Errorf("%w: %w", extraErr, baseErr)
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/gocompat_errors_unsupported.go
================================================
//go:build linux && !go1.20
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"fmt"
)
type wrappedError struct {
inner error
isError error
}
func (err wrappedError) Is(target error) bool {
return err.isError == target
}
func (err wrappedError) Unwrap() error {
return err.inner
}
func (err wrappedError) Error() string {
return fmt.Sprintf("%v: %v", err.isError, err.inner)
}
// wrapBaseError is a helper that is equivalent to fmt.Errorf("%w: %w"), except
// that on pre-1.20 Go versions only errors.Is() works properly (errors.Unwrap)
// is only guaranteed to give you baseErr.
func wrapBaseError(baseErr, extraErr error) error {
return wrappedError{
inner: baseErr,
isError: extraErr,
}
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_go121.go
================================================
//go:build linux && go1.21
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"slices"
"sync"
)
func slices_DeleteFunc[S ~[]E, E any](slice S, delFn func(E) bool) S {
return slices.DeleteFunc(slice, delFn)
}
func slices_Contains[S ~[]E, E comparable](slice S, val E) bool {
return slices.Contains(slice, val)
}
func slices_Clone[S ~[]E, E any](slice S) S {
return slices.Clone(slice)
}
func sync_OnceValue[T any](f func() T) func() T {
return sync.OnceValue(f)
}
func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
return sync.OnceValues(f)
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/gocompat_generics_unsupported.go
================================================
//go:build linux && !go1.21
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"sync"
)
// These are very minimal implementations of functions that appear in Go 1.21's
// stdlib, included so that we can build on older Go versions. Most are
// borrowed directly from the stdlib, and a few are modified to be "obviously
// correct" without needing to copy too many other helpers.
// clearSlice is equivalent to the builtin clear from Go 1.21.
// Copied from the Go 1.24 stdlib implementation.
func clearSlice[S ~[]E, E any](slice S) {
var zero E
for i := range slice {
slice[i] = zero
}
}
// Copied from the Go 1.24 stdlib implementation.
func slices_IndexFunc[S ~[]E, E any](s S, f func(E) bool) int {
for i := range s {
if f(s[i]) {
return i
}
}
return -1
}
// Copied from the Go 1.24 stdlib implementation.
func slices_DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
i := slices_IndexFunc(s, del)
if i == -1 {
return s
}
// Don't start copying elements until we find one to delete.
for j := i + 1; j < len(s); j++ {
if v := s[j]; !del(v) {
s[i] = v
i++
}
}
clearSlice(s[i:]) // zero/nil out the obsolete elements, for GC
return s[:i]
}
// Similar to the stdlib slices.Contains, except that we don't have
// slices.Index so we need to use slices.IndexFunc for this non-Func helper.
func slices_Contains[S ~[]E, E comparable](s S, v E) bool {
return slices_IndexFunc(s, func(e E) bool { return e == v }) >= 0
}
// Copied from the Go 1.24 stdlib implementation.
func slices_Clone[S ~[]E, E any](s S) S {
// Preserve nil in case it matters.
if s == nil {
return nil
}
return append(S([]E{}), s...)
}
// Copied from the Go 1.24 stdlib implementation.
func sync_OnceValue[T any](f func() T) func() T {
var (
once sync.Once
valid bool
p any
result T
)
g := func() {
defer func() {
p = recover()
if !valid {
panic(p)
}
}()
result = f()
f = nil
valid = true
}
return func() T {
once.Do(g)
if !valid {
panic(p)
}
return result
}
}
// Copied from the Go 1.24 stdlib implementation.
func sync_OnceValues[T1, T2 any](f func() (T1, T2)) func() (T1, T2) {
var (
once sync.Once
valid bool
p any
r1 T1
r2 T2
)
g := func() {
defer func() {
p = recover()
if !valid {
panic(p)
}
}()
r1, r2 = f()
f = nil
valid = true
}
return func() (T1, T2) {
once.Do(g)
if !valid {
panic(p)
}
return r1, r2
}
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/join.go
================================================
// Copyright (C) 2014-2015 Docker Inc & Go Authors. All rights reserved.
// Copyright (C) 2017-2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"errors"
"os"
"path/filepath"
"strings"
"syscall"
)
const maxSymlinkLimit = 255
// IsNotExist tells you if err is an error that implies that either the path
// accessed does not exist (or path components don't exist). This is
// effectively a more broad version of [os.IsNotExist].
func IsNotExist(err error) bool {
// Check that it's not actually an ENOTDIR, which in some cases is a more
// convoluted case of ENOENT (usually involving weird paths).
return errors.Is(err, os.ErrNotExist) || errors.Is(err, syscall.ENOTDIR) || errors.Is(err, syscall.ENOENT)
}
// SecureJoinVFS joins the two given path components (similar to [filepath.Join]) except
// that the returned path is guaranteed to be scoped inside the provided root
// path (when evaluated). Any symbolic links in the path are evaluated with the
// given root treated as the root of the filesystem, similar to a chroot. The
// filesystem state is evaluated through the given [VFS] interface (if nil, the
// standard [os].* family of functions are used).
//
// Note that the guarantees provided by this function only apply if the path
// components in the returned string are not modified (in other words are not
// replaced with symlinks on the filesystem) after this function has returned.
// Such a symlink race is necessarily out-of-scope of SecureJoinVFS.
//
// NOTE: Due to the above limitation, Linux users are strongly encouraged to
// use [OpenInRoot] instead, which does safely protect against these kinds of
// attacks. There is no way to solve this problem with SecureJoinVFS because
// the API is fundamentally wrong (you cannot return a "safe" path string and
// guarantee it won't be modified afterwards).
//
// Volume names in unsafePath are always discarded, regardless if they are
// provided via direct input or when evaluating symlinks. Therefore:
//
// "C:\Temp" + "D:\path\to\file.txt" results in "C:\Temp\path\to\file.txt"
func SecureJoinVFS(root, unsafePath string, vfs VFS) (string, error) {
// Use the os.* VFS implementation if none was specified.
if vfs == nil {
vfs = osVFS{}
}
unsafePath = filepath.FromSlash(unsafePath)
var (
currentPath string
remainingPath = unsafePath
linksWalked int
)
for remainingPath != "" {
if v := filepath.VolumeName(remainingPath); v != "" {
remainingPath = remainingPath[len(v):]
}
// Get the next path component.
var part string
if i := strings.IndexRune(remainingPath, filepath.Separator); i == -1 {
part, remainingPath = remainingPath, ""
} else {
part, remainingPath = remainingPath[:i], remainingPath[i+1:]
}
// Apply the component lexically to the path we are building.
// currentPath does not contain any symlinks, and we are lexically
// dealing with a single component, so it's okay to do a filepath.Clean
// here.
nextPath := filepath.Join(string(filepath.Separator), currentPath, part)
if nextPath == string(filepath.Separator) {
currentPath = ""
continue
}
fullPath := root + string(filepath.Separator) + nextPath
// Figure out whether the path is a symlink.
fi, err := vfs.Lstat(fullPath)
if err != nil && !IsNotExist(err) {
return "", err
}
// Treat non-existent path components the same as non-symlinks (we
// can't do any better here).
if IsNotExist(err) || fi.Mode()&os.ModeSymlink == 0 {
currentPath = nextPath
continue
}
// It's a symlink, so get its contents and expand it by prepending it
// to the yet-unparsed path.
linksWalked++
if linksWalked > maxSymlinkLimit {
return "", &os.PathError{Op: "SecureJoin", Path: root + string(filepath.Separator) + unsafePath, Err: syscall.ELOOP}
}
dest, err := vfs.Readlink(fullPath)
if err != nil {
return "", err
}
remainingPath = dest + string(filepath.Separator) + remainingPath
// Absolute symlinks reset any work we've already done.
if filepath.IsAbs(dest) {
currentPath = ""
}
}
// There should be no lexical components like ".." left in the path here,
// but for safety clean up the path before joining it to the root.
finalPath := filepath.Join(string(filepath.Separator), currentPath)
return filepath.Join(root, finalPath), nil
}
// SecureJoin is a wrapper around [SecureJoinVFS] that just uses the [os].* library
// of functions as the [VFS]. If in doubt, use this function over [SecureJoinVFS].
func SecureJoin(root, unsafePath string) (string, error) {
return SecureJoinVFS(root, unsafePath, nil)
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/lookup_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"errors"
"fmt"
"os"
"path"
"path/filepath"
"strings"
"golang.org/x/sys/unix"
)
type symlinkStackEntry struct {
// (dir, remainingPath) is what we would've returned if the link didn't
// exist. This matches what openat2(RESOLVE_IN_ROOT) would return in
// this case.
dir *os.File
remainingPath string
// linkUnwalked is the remaining path components from the original
// Readlink which we have yet to walk. When this slice is empty, we
// drop the link from the stack.
linkUnwalked []string
}
func (se symlinkStackEntry) String() string {
return fmt.Sprintf("<%s>/%s [->%s]", se.dir.Name(), se.remainingPath, strings.Join(se.linkUnwalked, "/"))
}
func (se symlinkStackEntry) Close() {
_ = se.dir.Close()
}
type symlinkStack []*symlinkStackEntry
func (s *symlinkStack) IsEmpty() bool {
return s == nil || len(*s) == 0
}
func (s *symlinkStack) Close() {
if s != nil {
for _, link := range *s {
link.Close()
}
// TODO: Switch to clear once we switch to Go 1.21.
*s = nil
}
}
var (
errEmptyStack = errors.New("[internal] stack is empty")
errBrokenSymlinkStack = errors.New("[internal error] broken symlink stack")
)
func (s *symlinkStack) popPart(part string) error {
if s == nil || s.IsEmpty() {
// If there is nothing in the symlink stack, then the part was from the
// real path provided by the user, and this is a no-op.
return errEmptyStack
}
if part == "." {
// "." components are no-ops -- we drop them when doing SwapLink.
return nil
}
tailEntry := (*s)[len(*s)-1]
// Double-check that we are popping the component we expect.
if len(tailEntry.linkUnwalked) == 0 {
return fmt.Errorf("%w: trying to pop component %q of empty stack entry %s", errBrokenSymlinkStack, part, tailEntry)
}
headPart := tailEntry.linkUnwalked[0]
if headPart != part {
return fmt.Errorf("%w: trying to pop component %q but the last stack entry is %s (%q)", errBrokenSymlinkStack, part, tailEntry, headPart)
}
// Drop the component, but keep the entry around in case we are dealing
// with a "tail-chained" symlink.
tailEntry.linkUnwalked = tailEntry.linkUnwalked[1:]
return nil
}
func (s *symlinkStack) PopPart(part string) error {
if err := s.popPart(part); err != nil {
if errors.Is(err, errEmptyStack) {
// Skip empty stacks.
err = nil
}
return err
}
// Clean up any of the trailing stack entries that are empty.
for lastGood := len(*s) - 1; lastGood >= 0; lastGood-- {
entry := (*s)[lastGood]
if len(entry.linkUnwalked) > 0 {
break
}
entry.Close()
(*s) = (*s)[:lastGood]
}
return nil
}
func (s *symlinkStack) push(dir *os.File, remainingPath, linkTarget string) error {
if s == nil {
return nil
}
// Split the link target and clean up any "" parts.
linkTargetParts := slices_DeleteFunc(
strings.Split(linkTarget, "/"),
func(part string) bool { return part == "" || part == "." })
// Copy the directory so the caller doesn't close our copy.
dirCopy, err := dupFile(dir)
if err != nil {
return err
}
// Add to the stack.
*s = append(*s, &symlinkStackEntry{
dir: dirCopy,
remainingPath: remainingPath,
linkUnwalked: linkTargetParts,
})
return nil
}
func (s *symlinkStack) SwapLink(linkPart string, dir *os.File, remainingPath, linkTarget string) error {
// If we are currently inside a symlink resolution, remove the symlink
// component from the last symlink entry, but don't remove the entry even
// if it's empty. If we are a "tail-chained" symlink (a trailing symlink we
// hit during a symlink resolution) we need to keep the old symlink until
// we finish the resolution.
if err := s.popPart(linkPart); err != nil {
if !errors.Is(err, errEmptyStack) {
return err
}
// Push the component regardless of whether the stack was empty.
}
return s.push(dir, remainingPath, linkTarget)
}
func (s *symlinkStack) PopTopSymlink() (*os.File, string, bool) {
if s == nil || s.IsEmpty() {
return nil, "", false
}
tailEntry := (*s)[0]
*s = (*s)[1:]
return tailEntry.dir, tailEntry.remainingPath, true
}
// partialLookupInRoot tries to lookup as much of the request path as possible
// within the provided root (a-la RESOLVE_IN_ROOT) and opens the final existing
// component of the requested path, returning a file handle to the final
// existing component and a string containing the remaining path components.
func partialLookupInRoot(root *os.File, unsafePath string) (*os.File, string, error) {
return lookupInRoot(root, unsafePath, true)
}
func completeLookupInRoot(root *os.File, unsafePath string) (*os.File, error) {
handle, remainingPath, err := lookupInRoot(root, unsafePath, false)
if remainingPath != "" && err == nil {
// should never happen
err = fmt.Errorf("[bug] non-empty remaining path when doing a non-partial lookup: %q", remainingPath)
}
// lookupInRoot(partial=false) will always close the handle if an error is
// returned, so no need to double-check here.
return handle, err
}
func lookupInRoot(root *os.File, unsafePath string, partial bool) (Handle *os.File, _ string, _ error) {
unsafePath = filepath.ToSlash(unsafePath) // noop
// This is very similar to SecureJoin, except that we operate on the
// components using file descriptors. We then return the last component we
// managed open, along with the remaining path components not opened.
// Try to use openat2 if possible.
if hasOpenat2() {
return lookupOpenat2(root, unsafePath, partial)
}
// Get the "actual" root path from /proc/self/fd. This is necessary if the
// root is some magic-link like /proc/$pid/root, in which case we want to
// make sure when we do checkProcSelfFdPath that we are using the correct
// root path.
logicalRootPath, err := procSelfFdReadlink(root)
if err != nil {
return nil, "", fmt.Errorf("get real root path: %w", err)
}
currentDir, err := dupFile(root)
if err != nil {
return nil, "", fmt.Errorf("clone root fd: %w", err)
}
defer func() {
// If a handle is not returned, close the internal handle.
if Handle == nil {
_ = currentDir.Close()
}
}()
// symlinkStack is used to emulate how openat2(RESOLVE_IN_ROOT) treats
// dangling symlinks. If we hit a non-existent path while resolving a
// symlink, we need to return the (dir, remainingPath) that we had when we
// hit the symlink (treating the symlink as though it were a regular file).
// The set of (dir, remainingPath) sets is stored within the symlinkStack
// and we add and remove parts when we hit symlink and non-symlink
// components respectively. We need a stack because of recursive symlinks
// (symlinks that contain symlink components in their target).
//
// Note that the stack is ONLY used for book-keeping. All of the actual
// path walking logic is still based on currentPath/remainingPath and
// currentDir (as in SecureJoin).
var symStack *symlinkStack
if partial {
symStack = new(symlinkStack)
defer symStack.Close()
}
var (
linksWalked int
currentPath string
remainingPath = unsafePath
)
for remainingPath != "" {
// Save the current remaining path so if the part is not real we can
// return the path including the component.
oldRemainingPath := remainingPath
// Get the next path component.
var part string
if i := strings.IndexByte(remainingPath, '/'); i == -1 {
part, remainingPath = remainingPath, ""
} else {
part, remainingPath = remainingPath[:i], remainingPath[i+1:]
}
// If we hit an empty component, we need to treat it as though it is
// "." so that trailing "/" and "//" components on a non-directory
// correctly return the right error code.
if part == "" {
part = "."
}
// Apply the component lexically to the path we are building.
// currentPath does not contain any symlinks, and we are lexically
// dealing with a single component, so it's okay to do a filepath.Clean
// here.
nextPath := path.Join("/", currentPath, part)
// If we logically hit the root, just clone the root rather than
// opening the part and doing all of the other checks.
if nextPath == "/" {
if err := symStack.PopPart(part); err != nil {
return nil, "", fmt.Errorf("walking into root with part %q failed: %w", part, err)
}
// Jump to root.
rootClone, err := dupFile(root)
if err != nil {
return nil, "", fmt.Errorf("clone root fd: %w", err)
}
_ = currentDir.Close()
currentDir = rootClone
currentPath = nextPath
continue
}
// Try to open the next component.
nextDir, err := openatFile(currentDir, part, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
switch {
case err == nil:
st, err := nextDir.Stat()
if err != nil {
_ = nextDir.Close()
return nil, "", fmt.Errorf("stat component %q: %w", part, err)
}
switch st.Mode() & os.ModeType {
case os.ModeSymlink:
// readlinkat implies AT_EMPTY_PATH since Linux 2.6.39. See
// Linux commit 65cfc6722361 ("readlinkat(), fchownat() and
// fstatat() with empty relative pathnames").
linkDest, err := readlinkatFile(nextDir, "")
// We don't need the handle anymore.
_ = nextDir.Close()
if err != nil {
return nil, "", err
}
linksWalked++
if linksWalked > maxSymlinkLimit {
return nil, "", &os.PathError{Op: "securejoin.lookupInRoot", Path: logicalRootPath + "/" + unsafePath, Err: unix.ELOOP}
}
// Swap out the symlink's component for the link entry itself.
if err := symStack.SwapLink(part, currentDir, oldRemainingPath, linkDest); err != nil {
return nil, "", fmt.Errorf("walking into symlink %q failed: push symlink: %w", part, err)
}
// Update our logical remaining path.
remainingPath = linkDest + "/" + remainingPath
// Absolute symlinks reset any work we've already done.
if path.IsAbs(linkDest) {
// Jump to root.
rootClone, err := dupFile(root)
if err != nil {
return nil, "", fmt.Errorf("clone root fd: %w", err)
}
_ = currentDir.Close()
currentDir = rootClone
currentPath = "/"
}
default:
// If we are dealing with a directory, simply walk into it.
_ = currentDir.Close()
currentDir = nextDir
currentPath = nextPath
// The part was real, so drop it from the symlink stack.
if err := symStack.PopPart(part); err != nil {
return nil, "", fmt.Errorf("walking into directory %q failed: %w", part, err)
}
// If we are operating on a .., make sure we haven't escaped.
// We only have to check for ".." here because walking down
// into a regular component component cannot cause you to
// escape. This mirrors the logic in RESOLVE_IN_ROOT, except we
// have to check every ".." rather than only checking after a
// rename or mount on the system.
if part == ".." {
// Make sure the root hasn't moved.
if err := checkProcSelfFdPath(logicalRootPath, root); err != nil {
return nil, "", fmt.Errorf("root path moved during lookup: %w", err)
}
// Make sure the path is what we expect.
fullPath := logicalRootPath + nextPath
if err := checkProcSelfFdPath(fullPath, currentDir); err != nil {
return nil, "", fmt.Errorf("walking into %q had unexpected result: %w", part, err)
}
}
}
default:
if !partial {
return nil, "", err
}
// If there are any remaining components in the symlink stack, we
// are still within a symlink resolution and thus we hit a dangling
// symlink. So pretend that the first symlink in the stack we hit
// was an ENOENT (to match openat2).
if oldDir, remainingPath, ok := symStack.PopTopSymlink(); ok {
_ = currentDir.Close()
return oldDir, remainingPath, err
}
// We have hit a final component that doesn't exist, so we have our
// partial open result. Note that we have to use the OLD remaining
// path, since the lookup failed.
return currentDir, oldRemainingPath, err
}
}
// If the unsafePath had a trailing slash, we need to make sure we try to
// do a relative "." open so that we will correctly return an error when
// the final component is a non-directory (to match openat2). In the
// context of openat2, a trailing slash and a trailing "/." are completely
// equivalent.
if strings.HasSuffix(unsafePath, "/") {
nextDir, err := openatFile(currentDir, ".", unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
if err != nil {
if !partial {
_ = currentDir.Close()
currentDir = nil
}
return currentDir, "", err
}
_ = currentDir.Close()
currentDir = nextDir
}
// All of the components existed!
return currentDir, "", nil
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/mkdir_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"golang.org/x/sys/unix"
)
var (
errInvalidMode = errors.New("invalid permission mode")
errPossibleAttack = errors.New("possible attack detected")
)
// MkdirAllHandle is equivalent to [MkdirAll], except that it is safer to use
// in two respects:
//
// - The caller provides the root directory as an *[os.File] (preferably O_PATH)
// handle. This means that the caller can be sure which root directory is
// being used. Note that this can be emulated by using /proc/self/fd/... as
// the root path with [os.MkdirAll].
//
// - Once all of the directories have been created, an *[os.File] O_PATH handle
// to the directory at unsafePath is returned to the caller. This is done in
// an effectively-race-free way (an attacker would only be able to swap the
// final directory component), which is not possible to emulate with
// [MkdirAll].
//
// In addition, the returned handle is obtained far more efficiently than doing
// a brand new lookup of unsafePath (such as with [SecureJoin] or openat2) after
// doing [MkdirAll]. If you intend to open the directory after creating it, you
// should use MkdirAllHandle.
func MkdirAllHandle(root *os.File, unsafePath string, mode int) (_ *os.File, Err error) {
// Make sure there are no os.FileMode bits set.
if mode&^0o7777 != 0 {
return nil, fmt.Errorf("%w for mkdir 0o%.3o", errInvalidMode, mode)
}
// On Linux, mkdirat(2) (and os.Mkdir) silently ignore the suid and sgid
// bits. We could also silently ignore them but since we have very few
// users it seems more prudent to return an error so users notice that
// these bits will not be set.
if mode&^0o1777 != 0 {
return nil, fmt.Errorf("%w for mkdir 0o%.3o: suid and sgid are ignored by mkdir", errInvalidMode, mode)
}
// Try to open as much of the path as possible.
currentDir, remainingPath, err := partialLookupInRoot(root, unsafePath)
defer func() {
if Err != nil {
_ = currentDir.Close()
}
}()
if err != nil && !errors.Is(err, unix.ENOENT) {
return nil, fmt.Errorf("find existing subpath of %q: %w", unsafePath, err)
}
// If there is an attacker deleting directories as we walk into them,
// detect this proactively. Note this is guaranteed to detect if the
// attacker deleted any part of the tree up to currentDir.
//
// Once we walk into a dead directory, partialLookupInRoot would not be
// able to walk further down the tree (directories must be empty before
// they are deleted), and if the attacker has removed the entire tree we
// can be sure that anything that was originally inside a dead directory
// must also be deleted and thus is a dead directory in its own right.
//
// This is mostly a quality-of-life check, because mkdir will simply fail
// later if the attacker deletes the tree after this check.
if err := isDeadInode(currentDir); err != nil {
return nil, fmt.Errorf("finding existing subpath of %q: %w", unsafePath, err)
}
// Re-open the path to match the O_DIRECTORY reopen loop later (so that we
// always return a non-O_PATH handle). We also check that we actually got a
// directory.
if reopenDir, err := Reopen(currentDir, unix.O_DIRECTORY|unix.O_CLOEXEC); errors.Is(err, unix.ENOTDIR) {
return nil, fmt.Errorf("cannot create subdirectories in %q: %w", currentDir.Name(), unix.ENOTDIR)
} else if err != nil {
return nil, fmt.Errorf("re-opening handle to %q: %w", currentDir.Name(), err)
} else {
_ = currentDir.Close()
currentDir = reopenDir
}
remainingParts := strings.Split(remainingPath, string(filepath.Separator))
if slices_Contains(remainingParts, "..") {
// The path contained ".." components after the end of the "real"
// components. We could try to safely resolve ".." here but that would
// add a bunch of extra logic for something that it's not clear even
// needs to be supported. So just return an error.
//
// If we do filepath.Clean(remainingPath) then we end up with the
// problem that ".." can erase a trailing dangling symlink and produce
// a path that doesn't quite match what the user asked for.
return nil, fmt.Errorf("%w: yet-to-be-created path %q contains '..' components", unix.ENOENT, remainingPath)
}
// Make sure the mode doesn't have any type bits.
mode &^= unix.S_IFMT
// Create the remaining components.
for _, part := range remainingParts {
switch part {
case "", ".":
// Skip over no-op paths.
continue
}
// NOTE: mkdir(2) will not follow trailing symlinks, so we can safely
// create the final component without worrying about symlink-exchange
// attacks.
//
// If we get -EEXIST, it's possible that another program created the
// directory at the same time as us. In that case, just continue on as
// if we created it (if the created inode is not a directory, the
// following open call will fail).
if err := unix.Mkdirat(int(currentDir.Fd()), part, uint32(mode)); err != nil && !errors.Is(err, unix.EEXIST) {
err = &os.PathError{Op: "mkdirat", Path: currentDir.Name() + "/" + part, Err: err}
// Make the error a bit nicer if the directory is dead.
if deadErr := isDeadInode(currentDir); deadErr != nil {
// TODO: Once we bump the minimum Go version to 1.20, we can use
// multiple %w verbs for this wrapping. For now we need to use a
// compatibility shim for older Go versions.
//err = fmt.Errorf("%w (%w)", err, deadErr)
err = wrapBaseError(err, deadErr)
}
return nil, err
}
// Get a handle to the next component. O_DIRECTORY means we don't need
// to use O_PATH.
var nextDir *os.File
if hasOpenat2() {
nextDir, err = openat2File(currentDir, part, &unix.OpenHow{
Flags: unix.O_NOFOLLOW | unix.O_DIRECTORY | unix.O_CLOEXEC,
Resolve: unix.RESOLVE_BENEATH | unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_NO_XDEV,
})
} else {
nextDir, err = openatFile(currentDir, part, unix.O_NOFOLLOW|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
}
if err != nil {
return nil, err
}
_ = currentDir.Close()
currentDir = nextDir
// It's possible that the directory we just opened was swapped by an
// attacker. Unfortunately there isn't much we can do to protect
// against this, and MkdirAll's behaviour is that we will reuse
// existing directories anyway so the need to protect against this is
// incredibly limited (and arguably doesn't even deserve mention here).
//
// Ideally we might want to check that the owner and mode match what we
// would've created -- unfortunately, it is non-trivial to verify that
// the owner and mode of the created directory match. While plain Unix
// DAC rules seem simple enough to emulate, there are a bunch of other
// factors that can change the mode or owner of created directories
// (default POSIX ACLs, mount options like uid=1,gid=2,umask=0 on
// filesystems like vfat, etc etc). We used to try to verify this but
// it just lead to a series of spurious errors.
//
// We could also check that the directory is non-empty, but
// unfortunately some pseduofilesystems (like cgroupfs) create
// non-empty directories, which would result in different spurious
// errors.
}
return currentDir, nil
}
// MkdirAll is a race-safe alternative to the [os.MkdirAll] function,
// where the new directory is guaranteed to be within the root directory (if an
// attacker can move directories from inside the root to outside the root, the
// created directory tree might be outside of the root but the key constraint
// is that at no point will we walk outside of the directory tree we are
// creating).
//
// Effectively, MkdirAll(root, unsafePath, mode) is equivalent to
//
// path, _ := securejoin.SecureJoin(root, unsafePath)
// err := os.MkdirAll(path, mode)
//
// But is much safer. The above implementation is unsafe because if an attacker
// can modify the filesystem tree between [SecureJoin] and [os.MkdirAll], it is
// possible for MkdirAll to resolve unsafe symlink components and create
// directories outside of the root.
//
// If you plan to open the directory after you have created it or want to use
// an open directory handle as the root, you should use [MkdirAllHandle] instead.
// This function is a wrapper around [MkdirAllHandle].
//
// NOTE: The mode argument must be set the unix mode bits (unix.S_I...), not
// the Go generic mode bits ([os.FileMode]...).
func MkdirAll(root, unsafePath string, mode int) error {
rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
if err != nil {
return err
}
defer rootDir.Close()
f, err := MkdirAllHandle(rootDir, unsafePath, mode)
if err != nil {
return err
}
_ = f.Close()
return nil
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/open_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"fmt"
"os"
"strconv"
"golang.org/x/sys/unix"
)
// OpenatInRoot is equivalent to [OpenInRoot], except that the root is provided
// using an *[os.File] handle, to ensure that the correct root directory is used.
func OpenatInRoot(root *os.File, unsafePath string) (*os.File, error) {
handle, err := completeLookupInRoot(root, unsafePath)
if err != nil {
return nil, &os.PathError{Op: "securejoin.OpenInRoot", Path: unsafePath, Err: err}
}
return handle, nil
}
// OpenInRoot safely opens the provided unsafePath within the root.
// Effectively, OpenInRoot(root, unsafePath) is equivalent to
//
// path, _ := securejoin.SecureJoin(root, unsafePath)
// handle, err := os.OpenFile(path, unix.O_PATH|unix.O_CLOEXEC)
//
// But is much safer. The above implementation is unsafe because if an attacker
// can modify the filesystem tree between [SecureJoin] and [os.OpenFile], it is
// possible for the returned file to be outside of the root.
//
// Note that the returned handle is an O_PATH handle, meaning that only a very
// limited set of operations will work on the handle. This is done to avoid
// accidentally opening an untrusted file that could cause issues (such as a
// disconnected TTY that could cause a DoS, or some other issue). In order to
// use the returned handle, you can "upgrade" it to a proper handle using
// [Reopen].
func OpenInRoot(root, unsafePath string) (*os.File, error) {
rootDir, err := os.OpenFile(root, unix.O_PATH|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
if err != nil {
return nil, err
}
defer rootDir.Close()
return OpenatInRoot(rootDir, unsafePath)
}
// Reopen takes an *[os.File] handle and re-opens it through /proc/self/fd.
// Reopen(file, flags) is effectively equivalent to
//
// fdPath := fmt.Sprintf("/proc/self/fd/%d", file.Fd())
// os.OpenFile(fdPath, flags|unix.O_CLOEXEC)
//
// But with some extra hardenings to ensure that we are not tricked by a
// maliciously-configured /proc mount. While this attack scenario is not
// common, in container runtimes it is possible for higher-level runtimes to be
// tricked into configuring an unsafe /proc that can be used to attack file
// operations. See [CVE-2019-19921] for more details.
//
// [CVE-2019-19921]: https://github.com/advisories/GHSA-fh74-hm69-rqjw
func Reopen(handle *os.File, flags int) (*os.File, error) {
procRoot, err := getProcRoot()
if err != nil {
return nil, err
}
// We can't operate on /proc/thread-self/fd/$n directly when doing a
// re-open, so we need to open /proc/thread-self/fd and then open a single
// final component.
procFdDir, closer, err := procThreadSelf(procRoot, "fd/")
if err != nil {
return nil, fmt.Errorf("get safe /proc/thread-self/fd handle: %w", err)
}
defer procFdDir.Close()
defer closer()
// Try to detect if there is a mount on top of the magic-link we are about
// to open. If we are using unsafeHostProcRoot(), this could change after
// we check it (and there's nothing we can do about that) but for
// privateProcRoot() this should be guaranteed to be safe (at least since
// Linux 5.12[1], when anonymous mount namespaces were completely isolated
// from external mounts including mount propagation events).
//
// [1]: Linux commit ee2e3f50629f ("mount: fix mounting of detached mounts
// onto targets that reside on shared mounts").
fdStr := strconv.Itoa(int(handle.Fd()))
if err := checkSymlinkOvermount(procRoot, procFdDir, fdStr); err != nil {
return nil, fmt.Errorf("check safety of /proc/thread-self/fd/%s magiclink: %w", fdStr, err)
}
flags |= unix.O_CLOEXEC
// Rather than just wrapping openatFile, open-code it so we can copy
// handle.Name().
reopenFd, err := unix.Openat(int(procFdDir.Fd()), fdStr, flags, 0)
if err != nil {
return nil, fmt.Errorf("reopen fd %d: %w", handle.Fd(), err)
}
return os.NewFile(uintptr(reopenFd), handle.Name()), nil
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/openat2_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"golang.org/x/sys/unix"
)
var hasOpenat2 = sync_OnceValue(func() bool {
fd, err := unix.Openat2(unix.AT_FDCWD, ".", &unix.OpenHow{
Flags: unix.O_PATH | unix.O_CLOEXEC,
Resolve: unix.RESOLVE_NO_SYMLINKS | unix.RESOLVE_IN_ROOT,
})
if err != nil {
return false
}
_ = unix.Close(fd)
return true
})
func scopedLookupShouldRetry(how *unix.OpenHow, err error) bool {
// RESOLVE_IN_ROOT (and RESOLVE_BENEATH) can return -EAGAIN if we resolve
// ".." while a mount or rename occurs anywhere on the system. This could
// happen spuriously, or as the result of an attacker trying to mess with
// us during lookup.
//
// In addition, scoped lookups have a "safety check" at the end of
// complete_walk which will return -EXDEV if the final path is not in the
// root.
return how.Resolve&(unix.RESOLVE_IN_ROOT|unix.RESOLVE_BENEATH) != 0 &&
(errors.Is(err, unix.EAGAIN) || errors.Is(err, unix.EXDEV))
}
const scopedLookupMaxRetries = 10
func openat2File(dir *os.File, path string, how *unix.OpenHow) (*os.File, error) {
fullPath := dir.Name() + "/" + path
// Make sure we always set O_CLOEXEC.
how.Flags |= unix.O_CLOEXEC
var tries int
for tries < scopedLookupMaxRetries {
fd, err := unix.Openat2(int(dir.Fd()), path, how)
if err != nil {
if scopedLookupShouldRetry(how, err) {
// We retry a couple of times to avoid the spurious errors, and
// if we are being attacked then returning -EAGAIN is the best
// we can do.
tries++
continue
}
return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: err}
}
// If we are using RESOLVE_IN_ROOT, the name we generated may be wrong.
// NOTE: The procRoot code MUST NOT use RESOLVE_IN_ROOT, otherwise
// you'll get infinite recursion here.
if how.Resolve&unix.RESOLVE_IN_ROOT == unix.RESOLVE_IN_ROOT {
if actualPath, err := rawProcSelfFdReadlink(fd); err == nil {
fullPath = actualPath
}
}
return os.NewFile(uintptr(fd), fullPath), nil
}
return nil, &os.PathError{Op: "openat2", Path: fullPath, Err: errPossibleAttack}
}
func lookupOpenat2(root *os.File, unsafePath string, partial bool) (*os.File, string, error) {
if !partial {
file, err := openat2File(root, unsafePath, &unix.OpenHow{
Flags: unix.O_PATH | unix.O_CLOEXEC,
Resolve: unix.RESOLVE_IN_ROOT | unix.RESOLVE_NO_MAGICLINKS,
})
return file, "", err
}
return partialLookupOpenat2(root, unsafePath)
}
// partialLookupOpenat2 is an alternative implementation of
// partialLookupInRoot, using openat2(RESOLVE_IN_ROOT) to more safely get a
// handle to the deepest existing child of the requested path within the root.
func partialLookupOpenat2(root *os.File, unsafePath string) (*os.File, string, error) {
// TODO: Implement this as a git-bisect-like binary search.
unsafePath = filepath.ToSlash(unsafePath) // noop
endIdx := len(unsafePath)
var lastError error
for endIdx > 0 {
subpath := unsafePath[:endIdx]
handle, err := openat2File(root, subpath, &unix.OpenHow{
Flags: unix.O_PATH | unix.O_CLOEXEC,
Resolve: unix.RESOLVE_IN_ROOT | unix.RESOLVE_NO_MAGICLINKS,
})
if err == nil {
// Jump over the slash if we have a non-"" remainingPath.
if endIdx < len(unsafePath) {
endIdx += 1
}
// We found a subpath!
return handle, unsafePath[endIdx:], lastError
}
if errors.Is(err, unix.ENOENT) || errors.Is(err, unix.ENOTDIR) {
// That path doesn't exist, let's try the next directory up.
endIdx = strings.LastIndexByte(subpath, '/')
lastError = err
continue
}
return nil, "", fmt.Errorf("open subpath: %w", err)
}
// If we couldn't open anything, the whole subpath is missing. Return a
// copy of the root fd so that the caller doesn't close this one by
// accident.
rootClone, err := dupFile(root)
if err != nil {
return nil, "", err
}
return rootClone, unsafePath, lastError
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/openat_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"os"
"path/filepath"
"golang.org/x/sys/unix"
)
func dupFile(f *os.File) (*os.File, error) {
fd, err := unix.FcntlInt(f.Fd(), unix.F_DUPFD_CLOEXEC, 0)
if err != nil {
return nil, os.NewSyscallError("fcntl(F_DUPFD_CLOEXEC)", err)
}
return os.NewFile(uintptr(fd), f.Name()), nil
}
func openatFile(dir *os.File, path string, flags int, mode int) (*os.File, error) {
// Make sure we always set O_CLOEXEC.
flags |= unix.O_CLOEXEC
fd, err := unix.Openat(int(dir.Fd()), path, flags, uint32(mode))
if err != nil {
return nil, &os.PathError{Op: "openat", Path: dir.Name() + "/" + path, Err: err}
}
// All of the paths we use with openatFile(2) are guaranteed to be
// lexically safe, so we can use path.Join here.
fullPath := filepath.Join(dir.Name(), path)
return os.NewFile(uintptr(fd), fullPath), nil
}
func fstatatFile(dir *os.File, path string, flags int) (unix.Stat_t, error) {
var stat unix.Stat_t
if err := unix.Fstatat(int(dir.Fd()), path, &stat, flags); err != nil {
return stat, &os.PathError{Op: "fstatat", Path: dir.Name() + "/" + path, Err: err}
}
return stat, nil
}
func readlinkatFile(dir *os.File, path string) (string, error) {
size := 4096
for {
linkBuf := make([]byte, size)
n, err := unix.Readlinkat(int(dir.Fd()), path, linkBuf)
if err != nil {
return "", &os.PathError{Op: "readlinkat", Path: dir.Name() + "/" + path, Err: err}
}
if n != size {
return string(linkBuf[:n]), nil
}
// Possible truncation, resize the buffer.
size *= 2
}
}
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/procfs_linux.go
================================================
//go:build linux
// Copyright (C) 2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import (
"errors"
"fmt"
"os"
"runtime"
"strconv"
"golang.org/x/sys/unix"
)
func fstat(f *os.File) (unix.Stat_t, error) {
var stat unix.Stat_t
if err := unix.Fstat(int(f.Fd()), &stat); err != nil {
return stat, &os.PathError{Op: "fstat", Path: f.Name(), Err: err}
}
return stat, nil
}
func fstatfs(f *os.File) (unix.Statfs_t, error) {
var statfs unix.Statfs_t
if err := unix.Fstatfs(int(f.Fd()), &statfs); err != nil {
return statfs, &os.PathError{Op: "fstatfs", Path: f.Name(), Err: err}
}
return statfs, nil
}
// The kernel guarantees that the root inode of a procfs mount has an
// f_type of PROC_SUPER_MAGIC and st_ino of PROC_ROOT_INO.
const (
procSuperMagic = 0x9fa0 // PROC_SUPER_MAGIC
procRootIno = 1 // PROC_ROOT_INO
)
func verifyProcRoot(procRoot *os.File) error {
if statfs, err := fstatfs(procRoot); err != nil {
return err
} else if statfs.Type != procSuperMagic {
return fmt.Errorf("%w: incorrect procfs root filesystem type 0x%x", errUnsafeProcfs, statfs.Type)
}
if stat, err := fstat(procRoot); err != nil {
return err
} else if stat.Ino != procRootIno {
return fmt.Errorf("%w: incorrect procfs root inode number %d", errUnsafeProcfs, stat.Ino)
}
return nil
}
var hasNewMountApi = sync_OnceValue(func() bool {
// All of the pieces of the new mount API we use (fsopen, fsconfig,
// fsmount, open_tree) were added together in Linux 5.1[1,2], so we can
// just check for one of the syscalls and the others should also be
// available.
//
// Just try to use open_tree(2) to open a file without OPEN_TREE_CLONE.
// This is equivalent to openat(2), but tells us if open_tree is
// available (and thus all of the other basic new mount API syscalls).
// open_tree(2) is most light-weight syscall to test here.
//
// [1]: merge commit 400913252d09
// [2]:
fd, err := unix.OpenTree(-int(unix.EBADF), "/", unix.OPEN_TREE_CLOEXEC)
if err != nil {
return false
}
_ = unix.Close(fd)
return true
})
func fsopen(fsName string, flags int) (*os.File, error) {
// Make sure we always set O_CLOEXEC.
flags |= unix.FSOPEN_CLOEXEC
fd, err := unix.Fsopen(fsName, flags)
if err != nil {
return nil, os.NewSyscallError("fsopen "+fsName, err)
}
return os.NewFile(uintptr(fd), "fscontext:"+fsName), nil
}
func fsmount(ctx *os.File, flags, mountAttrs int) (*os.File, error) {
// Make sure we always set O_CLOEXEC.
flags |= unix.FSMOUNT_CLOEXEC
fd, err := unix.Fsmount(int(ctx.Fd()), flags, mountAttrs)
if err != nil {
return nil, os.NewSyscallError("fsmount "+ctx.Name(), err)
}
return os.NewFile(uintptr(fd), "fsmount:"+ctx.Name()), nil
}
func newPrivateProcMount() (*os.File, error) {
procfsCtx, err := fsopen("proc", unix.FSOPEN_CLOEXEC)
if err != nil {
return nil, err
}
defer procfsCtx.Close()
// Try to configure hidepid=ptraceable,subset=pid if possible, but ignore errors.
_ = unix.FsconfigSetString(int(procfsCtx.Fd()), "hidepid", "ptraceable")
_ = unix.FsconfigSetString(int(procfsCtx.Fd()), "subset", "pid")
// Get an actual handle.
if err := unix.FsconfigCreate(int(procfsCtx.Fd())); err != nil {
return nil, os.NewSyscallError("fsconfig create procfs", err)
}
return fsmount(procfsCtx, unix.FSMOUNT_CLOEXEC, unix.MS_RDONLY|unix.MS_NODEV|unix.MS_NOEXEC|unix.MS_NOSUID)
}
func openTree(dir *os.File, path string, flags uint) (*os.File, error) {
dirFd := -int(unix.EBADF)
dirName := "."
if dir != nil {
dirFd = int(dir.Fd())
dirName = dir.Name()
}
// Make sure we always set O_CLOEXEC.
flags |= unix.OPEN_TREE_CLOEXEC
fd, err := unix.OpenTree(dirFd, path, flags)
if err != nil {
return nil, &os.PathError{Op: "open_tree", Path: path, Err: err}
}
return os.NewFile(uintptr(fd), dirName+"/"+path), nil
}
func clonePrivateProcMount() (_ *os.File, Err error) {
// Try to make a clone without using AT_RECURSIVE if we can. If this works,
// we can be sure there are no over-mounts and so if the root is valid then
// we're golden. Otherwise, we have to deal with over-mounts.
procfsHandle, err := openTree(nil, "/proc", unix.OPEN_TREE_CLONE)
if err != nil || hookForcePrivateProcRootOpenTreeAtRecursive(procfsHandle) {
procfsHandle, err = openTree(nil, "/proc", unix.OPEN_TREE_CLONE|unix.AT_RECURSIVE)
}
if err != nil {
return nil, fmt.Errorf("creating a detached procfs clone: %w", err)
}
defer func() {
if Err != nil {
_ = procfsHandle.Close()
}
}()
if err := verifyProcRoot(procfsHandle); err != nil {
return nil, err
}
return procfsHandle, nil
}
func privateProcRoot() (*os.File, error) {
if !hasNewMountApi() || hookForceGetProcRootUnsafe() {
return nil, fmt.Errorf("new mount api: %w", unix.ENOTSUP)
}
// Try to create a new procfs mount from scratch if we can. This ensures we
// can get a procfs mount even if /proc is fake (for whatever reason).
procRoot, err := newPrivateProcMount()
if err != nil || hookForcePrivateProcRootOpenTree(procRoot) {
// Try to clone /proc then...
procRoot, err = clonePrivateProcMount()
}
return procRoot, err
}
func unsafeHostProcRoot() (_ *os.File, Err error) {
procRoot, err := os.OpenFile("/proc", unix.O_PATH|unix.O_NOFOLLOW|unix.O_DIRECTORY|unix.O_CLOEXEC, 0)
if err != nil {
return nil, err
}
defer func() {
if Err != nil {
_ = procRoot.Close()
}
}()
if err := verifyProcRoot(procRoot); err != nil {
return nil, err
}
return procRoot, nil
}
func doGetProcRoot() (*os.File, error) {
procRoot, err := privateProcRoot()
if err != nil {
// Fall back to using a /proc handle if making a private mount failed.
// If we have openat2, at least we can avoid some kinds of over-mount
// attacks, but without openat2 there's not much we can do.
procRoot, err = unsafeHostProcRoot()
}
return procRoot, err
}
var getProcRoot = sync_OnceValues(func() (*os.File, error) {
return doGetProcRoot()
})
var hasProcThreadSelf = sync_OnceValue(func() bool {
return unix.Access("/proc/thread-self/", unix.F_OK) == nil
})
var errUnsafeProcfs = errors.New("unsafe procfs detected")
type procThreadSelfCloser func()
// procThreadSelf returns a handle to /proc/thread-self/ (or an
// equivalent handle on older kernels where /proc/thread-self doesn't exist).
// Once finished with the handle, you must call the returned closer function
// (runtime.UnlockOSThread). You must not pass the returned *os.File to other
// Go threads or use the handle after calling the closer.
//
// This is similar to ProcThreadSelf from runc, but with extra hardening
// applied and using *os.File.
func procThreadSelf(procRoot *os.File, subpath string) (_ *os.File, _ procThreadSelfCloser, Err error) {
// We need to lock our thread until the caller is done with the handle
// because between getting the handle and using it we could get interrupted
// by the Go runtime and hit the case where the underlying thread is
// swapped out and the original thread is killed, resulting in
// pull-your-hair-out-hard-to-debug issues in the caller.
runtime.LockOSThread()
defer func() {
if Err != nil {
runtime.UnlockOSThread()
}
}()
// Figure out what prefix we want to use.
threadSelf := "thread-self/"
if !hasProcThreadSelf() || hookForceProcSelfTask() {
/// Pre-3.17 kernels don't have /proc/thread-self, so do it manually.
threadSelf = "self/task/" + strconv.Itoa(unix.Gettid()) + "/"
if _, err := fstatatFile(procRoot, threadSelf, unix.AT_SYMLINK_NOFOLLOW); err != nil || hookForceProcSelf() {
// In this case, we running in a pid namespace that doesn't match
// the /proc mount we have. This can happen inside runc.
//
// Unfortunately, there is no nice way to get the correct TID to
// use here because of the age of the kernel, so we have to just
// use /proc/self and hope that it works.
threadSelf = "self/"
}
}
// Grab the handle.
var (
handle *os.File
err error
)
if hasOpenat2() {
// We prefer being able to use RESOLVE_NO_XDEV if we can, to be
// absolutely sure we are operating on a clean /proc handle that
// doesn't have any cheeky overmounts that could trick us (including
// symlink mounts on top of /proc/thread-self). RESOLVE_BENEATH isn't
// strictly needed, but just use it since we have it.
//
// NOTE: /proc/self is technically a magic-link (the contents of the
// symlink are generated dynamically), but it doesn't use
// nd_jump_link() so RESOLVE_NO_MAGICLINKS allows it.
//
// NOTE: We MUST NOT use RESOLVE_IN_ROOT here, as openat2File uses
// procSelfFdReadlink to clean up the returned f.Name() if we use
// RESOLVE_IN_ROOT (which would lead to an infinite recursion).
handle, err = openat2File(procRoot, threadSelf+subpath, &unix.OpenHow{
Flags: unix.O_PATH | unix.O_NOFOLLOW | unix.O_CLOEXEC,
Resolve: unix.RESOLVE_BENEATH | unix.RESOLVE_NO_XDEV | unix.RESOLVE_NO_MAGICLINKS,
})
if err != nil {
// TODO: Once we bump the minimum Go version to 1.20, we can use
// multiple %w verbs for this wrapping. For now we need to use a
// compatibility shim for older Go versions.
//err = fmt.Errorf("%w: %w", errUnsafeProcfs, err)
return nil, nil, wrapBaseError(err, errUnsafeProcfs)
}
} else {
handle, err = openatFile(procRoot, threadSelf+subpath, unix.O_PATH|unix.O_NOFOLLOW|unix.O_CLOEXEC, 0)
if err != nil {
// TODO: Once we bump the minimum Go version to 1.20, we can use
// multiple %w verbs for this wrapping. For now we need to use a
// compatibility shim for older Go versions.
//err = fmt.Errorf("%w: %w", errUnsafeProcfs, err)
return nil, nil, wrapBaseError(err, errUnsafeProcfs)
}
defer func() {
if Err != nil {
_ = handle.Close()
}
}()
// We can't detect bind-mounts of different parts of procfs on top of
// /proc (a-la RESOLVE_NO_XDEV), but we can at least be sure that we
// aren't on the wrong filesystem here.
if statfs, err := fstatfs(handle); err != nil {
return nil, nil, err
} else if statfs.Type != procSuperMagic {
return nil, nil, fmt.Errorf("%w: incorrect /proc/self/fd filesystem type 0x%x", errUnsafeProcfs, statfs.Type)
}
}
return handle, runtime.UnlockOSThread, nil
}
// STATX_MNT_ID_UNIQUE is provided in golang.org/x/sys@v0.20.0, but in order to
// avoid bumping the requirement for a single constant we can just define it
// ourselves.
const STATX_MNT_ID_UNIQUE = 0x4000
var hasStatxMountId = sync_OnceValue(func() bool {
var (
stx unix.Statx_t
// We don't care which mount ID we get. The kernel will give us the
// unique one if it is supported.
wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID
)
err := unix.Statx(-int(unix.EBADF), "/", 0, int(wantStxMask), &stx)
return err == nil && stx.Mask&wantStxMask != 0
})
func getMountId(dir *os.File, path string) (uint64, error) {
// If we don't have statx(STATX_MNT_ID*) support, we can't do anything.
if !hasStatxMountId() {
return 0, nil
}
var (
stx unix.Statx_t
// We don't care which mount ID we get. The kernel will give us the
// unique one if it is supported.
wantStxMask uint32 = STATX_MNT_ID_UNIQUE | unix.STATX_MNT_ID
)
err := unix.Statx(int(dir.Fd()), path, unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW, int(wantStxMask), &stx)
if stx.Mask&wantStxMask == 0 {
// It's not a kernel limitation, for some reason we couldn't get a
// mount ID. Assume it's some kind of attack.
err = fmt.Errorf("%w: could not get mount id", errUnsafeProcfs)
}
if err != nil {
return 0, &os.PathError{Op: "statx(STATX_MNT_ID_...)", Path: dir.Name() + "/" + path, Err: err}
}
return stx.Mnt_id, nil
}
func checkSymlinkOvermount(procRoot *os.File, dir *os.File, path string) error {
// Get the mntId of our procfs handle.
expectedMountId, err := getMountId(procRoot, "")
if err != nil {
return err
}
// Get the mntId of the target magic-link.
gotMountId, err := getMountId(dir, path)
if err != nil {
return err
}
// As long as the directory mount is alive, even with wrapping mount IDs,
// we would expect to see a different mount ID here. (Of course, if we're
// using unsafeHostProcRoot() then an attaker could change this after we
// did this check.)
if expectedMountId != gotMountId {
return fmt.Errorf("%w: symlink %s/%s has an overmount obscuring the real link (mount ids do not match %d != %d)", errUnsafeProcfs, dir.Name(), path, expectedMountId, gotMountId)
}
return nil
}
func doRawProcSelfFdReadlink(procRoot *os.File, fd int) (string, error) {
fdPath := fmt.Sprintf("fd/%d", fd)
procFdLink, closer, err := procThreadSelf(procRoot, fdPath)
if err != nil {
return "", fmt.Errorf("get safe /proc/thread-self/%s handle: %w", fdPath, err)
}
defer procFdLink.Close()
defer closer()
// Try to detect if there is a mount on top of the magic-link. Since we use the handle directly
// provide to the closure. If the closure uses the handle directly, this
// should be safe in general (a mount on top of the path afterwards would
// not affect the handle itself) and will definitely be safe if we are
// using privateProcRoot() (at least since Linux 5.12[1], when anonymous
// mount namespaces were completely isolated from external mounts including
// mount propagation events).
//
// [1]: Linux commit ee2e3f50629f ("mount: fix mounting of detached mounts
// onto targets that reside on shared mounts").
if err := checkSymlinkOvermount(procRoot, procFdLink, ""); err != nil {
return "", fmt.Errorf("check safety of /proc/thread-self/fd/%d magiclink: %w", fd, err)
}
// readlinkat implies AT_EMPTY_PATH since Linux 2.6.39. See Linux commit
// 65cfc6722361 ("readlinkat(), fchownat() and fstatat() with empty
// relative pathnames").
return readlinkatFile(procFdLink, "")
}
func rawProcSelfFdReadlink(fd int) (string, error) {
procRoot, err := getProcRoot()
if err != nil {
return "", err
}
return doRawProcSelfFdReadlink(procRoot, fd)
}
func procSelfFdReadlink(f *os.File) (string, error) {
return rawProcSelfFdReadlink(int(f.Fd()))
}
var (
errPossibleBreakout = errors.New("possible breakout detected")
errInvalidDirectory = errors.New("wandered into deleted directory")
errDeletedInode = errors.New("cannot verify path of deleted inode")
)
func isDeadInode(file *os.File) error {
// If the nlink of a file drops to 0, there is an attacker deleting
// directories during our walk, which could result in weird /proc values.
// It's better to error out in this case.
stat, err := fstat(file)
if err != nil {
return fmt.Errorf("check for dead inode: %w", err)
}
if stat.Nlink == 0 {
err := errDeletedInode
if stat.Mode&unix.S_IFMT == unix.S_IFDIR {
err = errInvalidDirectory
}
return fmt.Errorf("%w %q", err, file.Name())
}
return nil
}
func checkProcSelfFdPath(path string, file *os.File) error {
if err := isDeadInode(file); err != nil {
return err
}
actualPath, err := procSelfFdReadlink(file)
if err != nil {
return fmt.Errorf("get path of handle: %w", err)
}
if actualPath != path {
return fmt.Errorf("%w: handle path %q doesn't match expected path %q", errPossibleBreakout, actualPath, path)
}
return nil
}
// Test hooks used in the procfs tests to verify that the fallback logic works.
// See testing_mocks_linux_test.go and procfs_linux_test.go for more details.
var (
hookForcePrivateProcRootOpenTree = hookDummyFile
hookForcePrivateProcRootOpenTreeAtRecursive = hookDummyFile
hookForceGetProcRootUnsafe = hookDummy
hookForceProcSelfTask = hookDummy
hookForceProcSelf = hookDummy
)
func hookDummy() bool { return false }
func hookDummyFile(_ *os.File) bool { return false }
================================================
FILE: vendor/github.com/cyphar/filepath-securejoin/vfs.go
================================================
// Copyright (C) 2017-2024 SUSE LLC. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package securejoin
import "os"
// In future this should be moved into a separate package, because now there
// are several projects (umoci and go-mtree) that are using this sort of
// interface.
// VFS is the minimal interface necessary to use [SecureJoinVFS]. A nil VFS is
// equivalent to using the standard [os].* family of functions. This is mainly
// used for the purposes of mock testing, but also can be used to otherwise use
// [SecureJoinVFS] with VFS-like system.
type VFS interface {
// Lstat returns an [os.FileInfo] describing the named file. If the
// file is a symbolic link, the returned [os.FileInfo] describes the
// symbolic link. Lstat makes no attempt to follow the link.
// The semantics are identical to [os.Lstat].
Lstat(name string) (os.FileInfo, error)
// Readlink returns the destination of the named symbolic link.
// The semantics are identical to [os.Readlink].
Readlink(name string) (string, error)
}
// osVFS is the "nil" VFS, in that it just passes everything through to the os
// module.
type osVFS struct{}
func (o osVFS) Lstat(name string) (os.FileInfo, error) { return os.Lstat(name) }
func (o osVFS) Readlink(name string) (string, error) { return os.Readlink(name) }
================================================
FILE: vendor/github.com/davecgh/go-spew/LICENSE
================================================
ISC License
Copyright (c) 2012-2016 Dave Collins
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/bypass.go
================================================
// Copyright (c) 2015-2016 Dave Collins
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when the code is not running on Google App Engine, compiled by GopherJS, and
// "-tags safe" is not added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used.
// Go versions prior to 1.4 are disabled because they use a different layout
// for interfaces which make the implementation of unsafeReflectValue more complex.
// +build !js,!appengine,!safe,!disableunsafe,go1.4
package spew
import (
"reflect"
"unsafe"
)
const (
// UnsafeDisabled is a build-time constant which specifies whether or
// not access to the unsafe package is available.
UnsafeDisabled = false
// ptrSize is the size of a pointer on the current arch.
ptrSize = unsafe.Sizeof((*byte)(nil))
)
type flag uintptr
var (
// flagRO indicates whether the value field of a reflect.Value
// is read-only.
flagRO flag
// flagAddr indicates whether the address of the reflect.Value's
// value may be taken.
flagAddr flag
)
// flagKindMask holds the bits that make up the kind
// part of the flags field. In all the supported versions,
// it is in the lower 5 bits.
const flagKindMask = flag(0x1f)
// Different versions of Go have used different
// bit layouts for the flags type. This table
// records the known combinations.
var okFlags = []struct {
ro, addr flag
}{{
// From Go 1.4 to 1.5
ro: 1 << 5,
addr: 1 << 7,
}, {
// Up to Go tip.
ro: 1<<5 | 1<<6,
addr: 1 << 8,
}}
var flagValOffset = func() uintptr {
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
if !ok {
panic("reflect.Value has no flag field")
}
return field.Offset
}()
// flagField returns a pointer to the flag field of a reflect.Value.
func flagField(v *reflect.Value) *flag {
return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset))
}
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
// the typical safety restrictions preventing access to unaddressable and
// unexported data. It works by digging the raw pointer to the underlying
// value out of the protected value and generating a new unprotected (unsafe)
// reflect.Value to it.
//
// This allows us to check for implementations of the Stringer and error
// interfaces to be used for pretty printing ordinarily unaddressable and
// inaccessible values such as unexported struct fields.
func unsafeReflectValue(v reflect.Value) reflect.Value {
if !v.IsValid() || (v.CanInterface() && v.CanAddr()) {
return v
}
flagFieldPtr := flagField(&v)
*flagFieldPtr &^= flagRO
*flagFieldPtr |= flagAddr
return v
}
// Sanity checks against future reflect package changes
// to the type or semantics of the Value.flag field.
func init() {
field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag")
if !ok {
panic("reflect.Value has no flag field")
}
if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() {
panic("reflect.Value flag field has changed kind")
}
type t0 int
var t struct {
A t0
// t0 will have flagEmbedRO set.
t0
// a will have flagStickyRO set
a t0
}
vA := reflect.ValueOf(t).FieldByName("A")
va := reflect.ValueOf(t).FieldByName("a")
vt0 := reflect.ValueOf(t).FieldByName("t0")
// Infer flagRO from the difference between the flags
// for the (otherwise identical) fields in t.
flagPublic := *flagField(&vA)
flagWithRO := *flagField(&va) | *flagField(&vt0)
flagRO = flagPublic ^ flagWithRO
// Infer flagAddr from the difference between a value
// taken from a pointer and not.
vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A")
flagNoPtr := *flagField(&vA)
flagPtr := *flagField(&vPtrA)
flagAddr = flagNoPtr ^ flagPtr
// Check that the inferred flags tally with one of the known versions.
for _, f := range okFlags {
if flagRO == f.ro && flagAddr == f.addr {
return
}
}
panic("reflect.Value read-only flag has changed semantics")
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/bypasssafe.go
================================================
// Copyright (c) 2015-2016 Dave Collins
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when the code is running on Google App Engine, compiled by GopherJS, or
// "-tags safe" is added to the go build command line. The "disableunsafe"
// tag is deprecated and thus should not be used.
// +build js appengine safe disableunsafe !go1.4
package spew
import "reflect"
const (
// UnsafeDisabled is a build-time constant which specifies whether or
// not access to the unsafe package is available.
UnsafeDisabled = true
)
// unsafeReflectValue typically converts the passed reflect.Value into a one
// that bypasses the typical safety restrictions preventing access to
// unaddressable and unexported data. However, doing this relies on access to
// the unsafe package. This is a stub version which simply returns the passed
// reflect.Value when the unsafe package is not available.
func unsafeReflectValue(v reflect.Value) reflect.Value {
return v
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/common.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew
import (
"bytes"
"fmt"
"io"
"reflect"
"sort"
"strconv"
)
// Some constants in the form of bytes to avoid string overhead. This mirrors
// the technique used in the fmt package.
var (
panicBytes = []byte("(PANIC=")
plusBytes = []byte("+")
iBytes = []byte("i")
trueBytes = []byte("true")
falseBytes = []byte("false")
interfaceBytes = []byte("(interface {})")
commaNewlineBytes = []byte(",\n")
newlineBytes = []byte("\n")
openBraceBytes = []byte("{")
openBraceNewlineBytes = []byte("{\n")
closeBraceBytes = []byte("}")
asteriskBytes = []byte("*")
colonBytes = []byte(":")
colonSpaceBytes = []byte(": ")
openParenBytes = []byte("(")
closeParenBytes = []byte(")")
spaceBytes = []byte(" ")
pointerChainBytes = []byte("->")
nilAngleBytes = []byte("")
maxNewlineBytes = []byte("\n")
maxShortBytes = []byte("")
circularBytes = []byte("")
circularShortBytes = []byte("")
invalidAngleBytes = []byte("")
openBracketBytes = []byte("[")
closeBracketBytes = []byte("]")
percentBytes = []byte("%")
precisionBytes = []byte(".")
openAngleBytes = []byte("<")
closeAngleBytes = []byte(">")
openMapBytes = []byte("map[")
closeMapBytes = []byte("]")
lenEqualsBytes = []byte("len=")
capEqualsBytes = []byte("cap=")
)
// hexDigits is used to map a decimal value to a hex digit.
var hexDigits = "0123456789abcdef"
// catchPanic handles any panics that might occur during the handleMethods
// calls.
func catchPanic(w io.Writer, v reflect.Value) {
if err := recover(); err != nil {
w.Write(panicBytes)
fmt.Fprintf(w, "%v", err)
w.Write(closeParenBytes)
}
}
// handleMethods attempts to call the Error and String methods on the underlying
// type the passed reflect.Value represents and outputes the result to Writer w.
//
// It handles panics in any called methods by catching and displaying the error
// as the formatted value.
func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) {
// We need an interface to check if the type implements the error or
// Stringer interface. However, the reflect package won't give us an
// interface on certain things like unexported struct fields in order
// to enforce visibility rules. We use unsafe, when it's available,
// to bypass these restrictions since this package does not mutate the
// values.
if !v.CanInterface() {
if UnsafeDisabled {
return false
}
v = unsafeReflectValue(v)
}
// Choose whether or not to do error and Stringer interface lookups against
// the base type or a pointer to the base type depending on settings.
// Technically calling one of these methods with a pointer receiver can
// mutate the value, however, types which choose to satisify an error or
// Stringer interface with a pointer receiver should not be mutating their
// state inside these interface methods.
if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() {
v = unsafeReflectValue(v)
}
if v.CanAddr() {
v = v.Addr()
}
// Is it an error or Stringer?
switch iface := v.Interface().(type) {
case error:
defer catchPanic(w, v)
if cs.ContinueOnMethod {
w.Write(openParenBytes)
w.Write([]byte(iface.Error()))
w.Write(closeParenBytes)
w.Write(spaceBytes)
return false
}
w.Write([]byte(iface.Error()))
return true
case fmt.Stringer:
defer catchPanic(w, v)
if cs.ContinueOnMethod {
w.Write(openParenBytes)
w.Write([]byte(iface.String()))
w.Write(closeParenBytes)
w.Write(spaceBytes)
return false
}
w.Write([]byte(iface.String()))
return true
}
return false
}
// printBool outputs a boolean value as true or false to Writer w.
func printBool(w io.Writer, val bool) {
if val {
w.Write(trueBytes)
} else {
w.Write(falseBytes)
}
}
// printInt outputs a signed integer value to Writer w.
func printInt(w io.Writer, val int64, base int) {
w.Write([]byte(strconv.FormatInt(val, base)))
}
// printUint outputs an unsigned integer value to Writer w.
func printUint(w io.Writer, val uint64, base int) {
w.Write([]byte(strconv.FormatUint(val, base)))
}
// printFloat outputs a floating point value using the specified precision,
// which is expected to be 32 or 64bit, to Writer w.
func printFloat(w io.Writer, val float64, precision int) {
w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision)))
}
// printComplex outputs a complex value using the specified float precision
// for the real and imaginary parts to Writer w.
func printComplex(w io.Writer, c complex128, floatPrecision int) {
r := real(c)
w.Write(openParenBytes)
w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision)))
i := imag(c)
if i >= 0 {
w.Write(plusBytes)
}
w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision)))
w.Write(iBytes)
w.Write(closeParenBytes)
}
// printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x'
// prefix to Writer w.
func printHexPtr(w io.Writer, p uintptr) {
// Null pointer.
num := uint64(p)
if num == 0 {
w.Write(nilAngleBytes)
return
}
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
buf := make([]byte, 18)
// It's simpler to construct the hex string right to left.
base := uint64(16)
i := len(buf) - 1
for num >= base {
buf[i] = hexDigits[num%base]
num /= base
i--
}
buf[i] = hexDigits[num]
// Add '0x' prefix.
i--
buf[i] = 'x'
i--
buf[i] = '0'
// Strip unused leading bytes.
buf = buf[i:]
w.Write(buf)
}
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
// elements to be sorted.
type valuesSorter struct {
values []reflect.Value
strings []string // either nil or same len and values
cs *ConfigState
}
// newValuesSorter initializes a valuesSorter instance, which holds a set of
// surrogate keys on which the data should be sorted. It uses flags in
// ConfigState to decide if and how to populate those surrogate keys.
func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface {
vs := &valuesSorter{values: values, cs: cs}
if canSortSimply(vs.values[0].Kind()) {
return vs
}
if !cs.DisableMethods {
vs.strings = make([]string, len(values))
for i := range vs.values {
b := bytes.Buffer{}
if !handleMethods(cs, &b, vs.values[i]) {
vs.strings = nil
break
}
vs.strings[i] = b.String()
}
}
if vs.strings == nil && cs.SpewKeys {
vs.strings = make([]string, len(values))
for i := range vs.values {
vs.strings[i] = Sprintf("%#v", vs.values[i].Interface())
}
}
return vs
}
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
// directly, or whether it should be considered for sorting by surrogate keys
// (if the ConfigState allows it).
func canSortSimply(kind reflect.Kind) bool {
// This switch parallels valueSortLess, except for the default case.
switch kind {
case reflect.Bool:
return true
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return true
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return true
case reflect.Float32, reflect.Float64:
return true
case reflect.String:
return true
case reflect.Uintptr:
return true
case reflect.Array:
return true
}
return false
}
// Len returns the number of values in the slice. It is part of the
// sort.Interface implementation.
func (s *valuesSorter) Len() int {
return len(s.values)
}
// Swap swaps the values at the passed indices. It is part of the
// sort.Interface implementation.
func (s *valuesSorter) Swap(i, j int) {
s.values[i], s.values[j] = s.values[j], s.values[i]
if s.strings != nil {
s.strings[i], s.strings[j] = s.strings[j], s.strings[i]
}
}
// valueSortLess returns whether the first value should sort before the second
// value. It is used by valueSorter.Less as part of the sort.Interface
// implementation.
func valueSortLess(a, b reflect.Value) bool {
switch a.Kind() {
case reflect.Bool:
return !a.Bool() && b.Bool()
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
return a.Int() < b.Int()
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return a.Uint() < b.Uint()
case reflect.Float32, reflect.Float64:
return a.Float() < b.Float()
case reflect.String:
return a.String() < b.String()
case reflect.Uintptr:
return a.Uint() < b.Uint()
case reflect.Array:
// Compare the contents of both arrays.
l := a.Len()
for i := 0; i < l; i++ {
av := a.Index(i)
bv := b.Index(i)
if av.Interface() == bv.Interface() {
continue
}
return valueSortLess(av, bv)
}
}
return a.String() < b.String()
}
// Less returns whether the value at index i should sort before the
// value at index j. It is part of the sort.Interface implementation.
func (s *valuesSorter) Less(i, j int) bool {
if s.strings == nil {
return valueSortLess(s.values[i], s.values[j])
}
return s.strings[i] < s.strings[j]
}
// sortValues is a sort function that handles both native types and any type that
// can be converted to error or Stringer. Other inputs are sorted according to
// their Value.String() value to ensure display stability.
func sortValues(values []reflect.Value, cs *ConfigState) {
if len(values) == 0 {
return
}
sort.Sort(newValuesSorter(values, cs))
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/config.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew
import (
"bytes"
"fmt"
"io"
"os"
)
// ConfigState houses the configuration options used by spew to format and
// display values. There is a global instance, Config, that is used to control
// all top-level Formatter and Dump functionality. Each ConfigState instance
// provides methods equivalent to the top-level functions.
//
// The zero value for ConfigState provides no indentation. You would typically
// want to set it to a space or a tab.
//
// Alternatively, you can use NewDefaultConfig to get a ConfigState instance
// with default settings. See the documentation of NewDefaultConfig for default
// values.
type ConfigState struct {
// Indent specifies the string to use for each indentation level. The
// global config instance that all top-level functions use set this to a
// single space by default. If you would like more indentation, you might
// set this to a tab with "\t" or perhaps two spaces with " ".
Indent string
// MaxDepth controls the maximum number of levels to descend into nested
// data structures. The default, 0, means there is no limit.
//
// NOTE: Circular data structures are properly detected, so it is not
// necessary to set this value unless you specifically want to limit deeply
// nested data structures.
MaxDepth int
// DisableMethods specifies whether or not error and Stringer interfaces are
// invoked for types that implement them.
DisableMethods bool
// DisablePointerMethods specifies whether or not to check for and invoke
// error and Stringer interfaces on types which only accept a pointer
// receiver when the current type is not a pointer.
//
// NOTE: This might be an unsafe action since calling one of these methods
// with a pointer receiver could technically mutate the value, however,
// in practice, types which choose to satisify an error or Stringer
// interface with a pointer receiver should not be mutating their state
// inside these interface methods. As a result, this option relies on
// access to the unsafe package, so it will not have any effect when
// running in environments without access to the unsafe package such as
// Google App Engine or with the "safe" build tag specified.
DisablePointerMethods bool
// DisablePointerAddresses specifies whether to disable the printing of
// pointer addresses. This is useful when diffing data structures in tests.
DisablePointerAddresses bool
// DisableCapacities specifies whether to disable the printing of capacities
// for arrays, slices, maps and channels. This is useful when diffing
// data structures in tests.
DisableCapacities bool
// ContinueOnMethod specifies whether or not recursion should continue once
// a custom error or Stringer interface is invoked. The default, false,
// means it will print the results of invoking the custom error or Stringer
// interface and return immediately instead of continuing to recurse into
// the internals of the data type.
//
// NOTE: This flag does not have any effect if method invocation is disabled
// via the DisableMethods or DisablePointerMethods options.
ContinueOnMethod bool
// SortKeys specifies map keys should be sorted before being printed. Use
// this to have a more deterministic, diffable output. Note that only
// native types (bool, int, uint, floats, uintptr and string) and types
// that support the error or Stringer interfaces (if methods are
// enabled) are supported, with other types sorted according to the
// reflect.Value.String() output which guarantees display stability.
SortKeys bool
// SpewKeys specifies that, as a last resort attempt, map keys should
// be spewed to strings and sorted by those strings. This is only
// considered if SortKeys is true.
SpewKeys bool
}
// Config is the active configuration of the top-level functions.
// The configuration can be changed by modifying the contents of spew.Config.
var Config = ConfigState{Indent: " "}
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the formatted string as a value that satisfies error. See NewFormatter
// for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) {
return fmt.Errorf(format, c.convertArgs(a)...)
}
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprint(w, c.convertArgs(a)...)
}
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(w, format, c.convertArgs(a)...)
}
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
// passed with a Formatter interface returned by c.NewFormatter. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprintln(w, c.convertArgs(a)...)
}
// Print is a wrapper for fmt.Print that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Print(c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Print(a ...interface{}) (n int, err error) {
return fmt.Print(c.convertArgs(a)...)
}
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Printf(format, c.convertArgs(a)...)
}
// Println is a wrapper for fmt.Println that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Println(c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Println(a ...interface{}) (n int, err error) {
return fmt.Println(c.convertArgs(a)...)
}
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Sprint(a ...interface{}) string {
return fmt.Sprint(c.convertArgs(a)...)
}
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Sprintf(format string, a ...interface{}) string {
return fmt.Sprintf(format, c.convertArgs(a)...)
}
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
// were passed with a Formatter interface returned by c.NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
func (c *ConfigState) Sprintln(a ...interface{}) string {
return fmt.Sprintln(c.convertArgs(a)...)
}
/*
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
interface. As a result, it integrates cleanly with standard fmt package
printing functions. The formatter is useful for inline printing of smaller data
types similar to the standard %v format specifier.
The custom formatter only responds to the %v (most compact), %+v (adds pointer
addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb
combinations. Any other verbs such as %x and %q will be sent to the the
standard fmt package for formatting. In addition, the custom formatter ignores
the width and precision arguments (however they will still work on the format
specifiers not handled by the custom formatter).
Typically this function shouldn't be called directly. It is much easier to make
use of the custom formatter by calling one of the convenience functions such as
c.Printf, c.Println, or c.Printf.
*/
func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter {
return newFormatter(c, v)
}
// Fdump formats and displays the passed arguments to io.Writer w. It formats
// exactly the same as Dump.
func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) {
fdump(c, w, a...)
}
/*
Dump displays the passed parameters to standard out with newlines, customizable
indentation, and additional debug information such as complete types and all
pointer addresses used to indirect to the final value. It provides the
following features over the built-in printing facilities provided by the fmt
package:
* Pointers are dereferenced and followed
* Circular data structures are detected and handled properly
* Custom Stringer/error interfaces are optionally invoked, including
on unexported types
* Custom types which only implement the Stringer/error interfaces via
a pointer receiver are optionally invoked when passing non-pointer
variables
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output
The configuration options are controlled by modifying the public members
of c. See ConfigState for options documentation.
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
get the formatted result as a string.
*/
func (c *ConfigState) Dump(a ...interface{}) {
fdump(c, os.Stdout, a...)
}
// Sdump returns a string with the passed arguments formatted exactly the same
// as Dump.
func (c *ConfigState) Sdump(a ...interface{}) string {
var buf bytes.Buffer
fdump(c, &buf, a...)
return buf.String()
}
// convertArgs accepts a slice of arguments and returns a slice of the same
// length with each argument converted to a spew Formatter interface using
// the ConfigState associated with s.
func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) {
formatters = make([]interface{}, len(args))
for index, arg := range args {
formatters[index] = newFormatter(c, arg)
}
return formatters
}
// NewDefaultConfig returns a ConfigState with the following default settings.
//
// Indent: " "
// MaxDepth: 0
// DisableMethods: false
// DisablePointerMethods: false
// ContinueOnMethod: false
// SortKeys: false
func NewDefaultConfig() *ConfigState {
return &ConfigState{Indent: " "}
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/doc.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
Package spew implements a deep pretty printer for Go data structures to aid in
debugging.
A quick overview of the additional features spew provides over the built-in
printing facilities for Go data types are as follows:
* Pointers are dereferenced and followed
* Circular data structures are detected and handled properly
* Custom Stringer/error interfaces are optionally invoked, including
on unexported types
* Custom types which only implement the Stringer/error interfaces via
a pointer receiver are optionally invoked when passing non-pointer
variables
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output (only when using
Dump style)
There are two different approaches spew allows for dumping Go data structures:
* Dump style which prints with newlines, customizable indentation,
and additional debug information such as types and all pointer addresses
used to indirect to the final value
* A custom Formatter interface that integrates cleanly with the standard fmt
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
similar to the default %v while providing the additional functionality
outlined above and passing unsupported format verbs such as %x and %q
along to fmt
Quick Start
This section demonstrates how to quickly get started with spew. See the
sections below for further details on formatting and configuration options.
To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)
Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
%#+v (adds types and pointer addresses):
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
Configuration Options
Configuration of spew is handled by fields in the ConfigState type. For
convenience, all of the top-level functions use a global state available
via the spew.Config global.
It is also possible to create a ConfigState instance that provides methods
equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.
The following configuration options are available:
* Indent
String to use for each indentation level for Dump functions.
It is a single space by default. A popular alternative is "\t".
* MaxDepth
Maximum number of levels to descend into nested data structures.
There is no limit by default.
* DisableMethods
Disables invocation of error and Stringer interface methods.
Method invocation is enabled by default.
* DisablePointerMethods
Disables invocation of error and Stringer interface methods on types
which only accept pointer receivers from non-pointer variables.
Pointer method invocation is enabled by default.
* DisablePointerAddresses
DisablePointerAddresses specifies whether to disable the printing of
pointer addresses. This is useful when diffing data structures in tests.
* DisableCapacities
DisableCapacities specifies whether to disable the printing of
capacities for arrays, slices, maps and channels. This is useful when
diffing data structures in tests.
* ContinueOnMethod
Enables recursion into types after invoking error and Stringer interface
methods. Recursion after method invocation is disabled by default.
* SortKeys
Specifies map keys should be sorted before being printed. Use
this to have a more deterministic, diffable output. Note that
only native types (bool, int, uint, floats, uintptr and string)
and types which implement error or Stringer interfaces are
supported with other types sorted according to the
reflect.Value.String() output which guarantees display
stability. Natural map order is used by default.
* SpewKeys
Specifies that, as a last resort attempt, map keys should be
spewed to strings and sorted by those strings. This is only
considered if SortKeys is true.
Dump Usage
Simply call spew.Dump with a list of variables you want to dump:
spew.Dump(myVar1, myVar2, ...)
You may also call spew.Fdump if you would prefer to output to an arbitrary
io.Writer. For example, to dump to standard error:
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
A third option is to call spew.Sdump to get the formatted output as a string:
str := spew.Sdump(myVar1, myVar2, ...)
Sample Dump Output
See the Dump example for details on the setup of the types and variables being
shown here.
(main.Foo) {
unexportedField: (*main.Bar)(0xf84002e210)({
flag: (main.Flag) flagTwo,
data: (uintptr)
}),
ExportedField: (map[interface {}]interface {}) (len=1) {
(string) (len=3) "one": (bool) true
}
}
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
command as shown.
([]uint8) (len=32 cap=32) {
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
00000020 31 32 |12|
}
Custom Formatter
Spew provides a custom formatter that implements the fmt.Formatter interface
so that it integrates cleanly with standard fmt package printing functions. The
formatter is useful for inline printing of smaller data types similar to the
standard %v format specifier.
The custom formatter only responds to the %v (most compact), %+v (adds pointer
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
combinations. Any other verbs such as %x and %q will be sent to the the
standard fmt package for formatting. In addition, the custom formatter ignores
the width and precision arguments (however they will still work on the format
specifiers not handled by the custom formatter).
Custom Formatter Usage
The simplest way to make use of the spew custom formatter is to call one of the
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
functions have syntax you are most likely already familiar with:
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Println(myVar, myVar2)
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
See the Index for the full list convenience functions.
Sample Formatter Output
Double pointer to a uint8:
%v: <**>5
%+v: <**>(0xf8400420d0->0xf8400420c8)5
%#v: (**uint8)5
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
Pointer to circular struct with a uint8 field and a pointer to itself:
%v: <*>{1 <*>}
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)}
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)}
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)}
See the Printf example for details on the setup of variables being shown
here.
Errors
Since it is possible for custom Stringer/error interfaces to panic, spew
detects them and handles them internally by printing the panic information
inline with the output. Since spew is intended to provide deep pretty printing
capabilities on structures, it intentionally does not return any errors.
*/
package spew
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/dump.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew
import (
"bytes"
"encoding/hex"
"fmt"
"io"
"os"
"reflect"
"regexp"
"strconv"
"strings"
)
var (
// uint8Type is a reflect.Type representing a uint8. It is used to
// convert cgo types to uint8 slices for hexdumping.
uint8Type = reflect.TypeOf(uint8(0))
// cCharRE is a regular expression that matches a cgo char.
// It is used to detect character arrays to hexdump them.
cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`)
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
// char. It is used to detect unsigned character arrays to hexdump
// them.
cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`)
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
// It is used to detect uint8_t arrays to hexdump them.
cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`)
)
// dumpState contains information about the state of a dump operation.
type dumpState struct {
w io.Writer
depth int
pointers map[uintptr]int
ignoreNextType bool
ignoreNextIndent bool
cs *ConfigState
}
// indent performs indentation according to the depth level and cs.Indent
// option.
func (d *dumpState) indent() {
if d.ignoreNextIndent {
d.ignoreNextIndent = false
return
}
d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth))
}
// unpackValue returns values inside of non-nil interfaces when possible.
// This is useful for data types like structs, arrays, slices, and maps which
// can contain varying types packed inside an interface.
func (d *dumpState) unpackValue(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Interface && !v.IsNil() {
v = v.Elem()
}
return v
}
// dumpPtr handles formatting of pointers by indirecting them as necessary.
func (d *dumpState) dumpPtr(v reflect.Value) {
// Remove pointers at or below the current depth from map used to detect
// circular refs.
for k, depth := range d.pointers {
if depth >= d.depth {
delete(d.pointers, k)
}
}
// Keep list of all dereferenced pointers to show later.
pointerChain := make([]uintptr, 0)
// Figure out how many levels of indirection there are by dereferencing
// pointers and unpacking interfaces down the chain while detecting circular
// references.
nilFound := false
cycleFound := false
indirects := 0
ve := v
for ve.Kind() == reflect.Ptr {
if ve.IsNil() {
nilFound = true
break
}
indirects++
addr := ve.Pointer()
pointerChain = append(pointerChain, addr)
if pd, ok := d.pointers[addr]; ok && pd < d.depth {
cycleFound = true
indirects--
break
}
d.pointers[addr] = d.depth
ve = ve.Elem()
if ve.Kind() == reflect.Interface {
if ve.IsNil() {
nilFound = true
break
}
ve = ve.Elem()
}
}
// Display type information.
d.w.Write(openParenBytes)
d.w.Write(bytes.Repeat(asteriskBytes, indirects))
d.w.Write([]byte(ve.Type().String()))
d.w.Write(closeParenBytes)
// Display pointer information.
if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 {
d.w.Write(openParenBytes)
for i, addr := range pointerChain {
if i > 0 {
d.w.Write(pointerChainBytes)
}
printHexPtr(d.w, addr)
}
d.w.Write(closeParenBytes)
}
// Display dereferenced value.
d.w.Write(openParenBytes)
switch {
case nilFound:
d.w.Write(nilAngleBytes)
case cycleFound:
d.w.Write(circularBytes)
default:
d.ignoreNextType = true
d.dump(ve)
}
d.w.Write(closeParenBytes)
}
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
// reflection) arrays and slices are dumped in hexdump -C fashion.
func (d *dumpState) dumpSlice(v reflect.Value) {
// Determine whether this type should be hex dumped or not. Also,
// for types which should be hexdumped, try to use the underlying data
// first, then fall back to trying to convert them to a uint8 slice.
var buf []uint8
doConvert := false
doHexDump := false
numEntries := v.Len()
if numEntries > 0 {
vt := v.Index(0).Type()
vts := vt.String()
switch {
// C types that need to be converted.
case cCharRE.MatchString(vts):
fallthrough
case cUnsignedCharRE.MatchString(vts):
fallthrough
case cUint8tCharRE.MatchString(vts):
doConvert = true
// Try to use existing uint8 slices and fall back to converting
// and copying if that fails.
case vt.Kind() == reflect.Uint8:
// We need an addressable interface to convert the type
// to a byte slice. However, the reflect package won't
// give us an interface on certain things like
// unexported struct fields in order to enforce
// visibility rules. We use unsafe, when available, to
// bypass these restrictions since this package does not
// mutate the values.
vs := v
if !vs.CanInterface() || !vs.CanAddr() {
vs = unsafeReflectValue(vs)
}
if !UnsafeDisabled {
vs = vs.Slice(0, numEntries)
// Use the existing uint8 slice if it can be
// type asserted.
iface := vs.Interface()
if slice, ok := iface.([]uint8); ok {
buf = slice
doHexDump = true
break
}
}
// The underlying data needs to be converted if it can't
// be type asserted to a uint8 slice.
doConvert = true
}
// Copy and convert the underlying type if needed.
if doConvert && vt.ConvertibleTo(uint8Type) {
// Convert and copy each element into a uint8 byte
// slice.
buf = make([]uint8, numEntries)
for i := 0; i < numEntries; i++ {
vv := v.Index(i)
buf[i] = uint8(vv.Convert(uint8Type).Uint())
}
doHexDump = true
}
}
// Hexdump the entire slice as needed.
if doHexDump {
indent := strings.Repeat(d.cs.Indent, d.depth)
str := indent + hex.Dump(buf)
str = strings.Replace(str, "\n", "\n"+indent, -1)
str = strings.TrimRight(str, d.cs.Indent)
d.w.Write([]byte(str))
return
}
// Recursively call dump for each item.
for i := 0; i < numEntries; i++ {
d.dump(d.unpackValue(v.Index(i)))
if i < (numEntries - 1) {
d.w.Write(commaNewlineBytes)
} else {
d.w.Write(newlineBytes)
}
}
}
// dump is the main workhorse for dumping a value. It uses the passed reflect
// value to figure out what kind of object we are dealing with and formats it
// appropriately. It is a recursive function, however circular data structures
// are detected and handled properly.
func (d *dumpState) dump(v reflect.Value) {
// Handle invalid reflect values immediately.
kind := v.Kind()
if kind == reflect.Invalid {
d.w.Write(invalidAngleBytes)
return
}
// Handle pointers specially.
if kind == reflect.Ptr {
d.indent()
d.dumpPtr(v)
return
}
// Print type information unless already handled elsewhere.
if !d.ignoreNextType {
d.indent()
d.w.Write(openParenBytes)
d.w.Write([]byte(v.Type().String()))
d.w.Write(closeParenBytes)
d.w.Write(spaceBytes)
}
d.ignoreNextType = false
// Display length and capacity if the built-in len and cap functions
// work with the value's kind and the len/cap itself is non-zero.
valueLen, valueCap := 0, 0
switch v.Kind() {
case reflect.Array, reflect.Slice, reflect.Chan:
valueLen, valueCap = v.Len(), v.Cap()
case reflect.Map, reflect.String:
valueLen = v.Len()
}
if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 {
d.w.Write(openParenBytes)
if valueLen != 0 {
d.w.Write(lenEqualsBytes)
printInt(d.w, int64(valueLen), 10)
}
if !d.cs.DisableCapacities && valueCap != 0 {
if valueLen != 0 {
d.w.Write(spaceBytes)
}
d.w.Write(capEqualsBytes)
printInt(d.w, int64(valueCap), 10)
}
d.w.Write(closeParenBytes)
d.w.Write(spaceBytes)
}
// Call Stringer/error interfaces if they exist and the handle methods flag
// is enabled
if !d.cs.DisableMethods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(d.cs, d.w, v); handled {
return
}
}
}
switch kind {
case reflect.Invalid:
// Do nothing. We should never get here since invalid has already
// been handled above.
case reflect.Bool:
printBool(d.w, v.Bool())
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
printInt(d.w, v.Int(), 10)
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
printUint(d.w, v.Uint(), 10)
case reflect.Float32:
printFloat(d.w, v.Float(), 32)
case reflect.Float64:
printFloat(d.w, v.Float(), 64)
case reflect.Complex64:
printComplex(d.w, v.Complex(), 32)
case reflect.Complex128:
printComplex(d.w, v.Complex(), 64)
case reflect.Slice:
if v.IsNil() {
d.w.Write(nilAngleBytes)
break
}
fallthrough
case reflect.Array:
d.w.Write(openBraceNewlineBytes)
d.depth++
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.indent()
d.w.Write(maxNewlineBytes)
} else {
d.dumpSlice(v)
}
d.depth--
d.indent()
d.w.Write(closeBraceBytes)
case reflect.String:
d.w.Write([]byte(strconv.Quote(v.String())))
case reflect.Interface:
// The only time we should get here is for nil interfaces due to
// unpackValue calls.
if v.IsNil() {
d.w.Write(nilAngleBytes)
}
case reflect.Ptr:
// Do nothing. We should never get here since pointers have already
// been handled above.
case reflect.Map:
// nil maps should be indicated as different than empty maps
if v.IsNil() {
d.w.Write(nilAngleBytes)
break
}
d.w.Write(openBraceNewlineBytes)
d.depth++
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.indent()
d.w.Write(maxNewlineBytes)
} else {
numEntries := v.Len()
keys := v.MapKeys()
if d.cs.SortKeys {
sortValues(keys, d.cs)
}
for i, key := range keys {
d.dump(d.unpackValue(key))
d.w.Write(colonSpaceBytes)
d.ignoreNextIndent = true
d.dump(d.unpackValue(v.MapIndex(key)))
if i < (numEntries - 1) {
d.w.Write(commaNewlineBytes)
} else {
d.w.Write(newlineBytes)
}
}
}
d.depth--
d.indent()
d.w.Write(closeBraceBytes)
case reflect.Struct:
d.w.Write(openBraceNewlineBytes)
d.depth++
if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {
d.indent()
d.w.Write(maxNewlineBytes)
} else {
vt := v.Type()
numFields := v.NumField()
for i := 0; i < numFields; i++ {
d.indent()
vtf := vt.Field(i)
d.w.Write([]byte(vtf.Name))
d.w.Write(colonSpaceBytes)
d.ignoreNextIndent = true
d.dump(d.unpackValue(v.Field(i)))
if i < (numFields - 1) {
d.w.Write(commaNewlineBytes)
} else {
d.w.Write(newlineBytes)
}
}
}
d.depth--
d.indent()
d.w.Write(closeBraceBytes)
case reflect.Uintptr:
printHexPtr(d.w, uintptr(v.Uint()))
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
printHexPtr(d.w, v.Pointer())
// There were not any other types at the time this code was written, but
// fall back to letting the default fmt package handle it in case any new
// types are added.
default:
if v.CanInterface() {
fmt.Fprintf(d.w, "%v", v.Interface())
} else {
fmt.Fprintf(d.w, "%v", v.String())
}
}
}
// fdump is a helper function to consolidate the logic from the various public
// methods which take varying writers and config states.
func fdump(cs *ConfigState, w io.Writer, a ...interface{}) {
for _, arg := range a {
if arg == nil {
w.Write(interfaceBytes)
w.Write(spaceBytes)
w.Write(nilAngleBytes)
w.Write(newlineBytes)
continue
}
d := dumpState{w: w, cs: cs}
d.pointers = make(map[uintptr]int)
d.dump(reflect.ValueOf(arg))
d.w.Write(newlineBytes)
}
}
// Fdump formats and displays the passed arguments to io.Writer w. It formats
// exactly the same as Dump.
func Fdump(w io.Writer, a ...interface{}) {
fdump(&Config, w, a...)
}
// Sdump returns a string with the passed arguments formatted exactly the same
// as Dump.
func Sdump(a ...interface{}) string {
var buf bytes.Buffer
fdump(&Config, &buf, a...)
return buf.String()
}
/*
Dump displays the passed parameters to standard out with newlines, customizable
indentation, and additional debug information such as complete types and all
pointer addresses used to indirect to the final value. It provides the
following features over the built-in printing facilities provided by the fmt
package:
* Pointers are dereferenced and followed
* Circular data structures are detected and handled properly
* Custom Stringer/error interfaces are optionally invoked, including
on unexported types
* Custom types which only implement the Stringer/error interfaces via
a pointer receiver are optionally invoked when passing non-pointer
variables
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output
The configuration options are controlled by an exported package global,
spew.Config. See ConfigState for options documentation.
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
get the formatted result as a string.
*/
func Dump(a ...interface{}) {
fdump(&Config, os.Stdout, a...)
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/format.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew
import (
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
)
// supportedFlags is a list of all the character flags supported by fmt package.
const supportedFlags = "0-+# "
// formatState implements the fmt.Formatter interface and contains information
// about the state of a formatting operation. The NewFormatter function can
// be used to get a new Formatter which can be used directly as arguments
// in standard fmt package printing calls.
type formatState struct {
value interface{}
fs fmt.State
depth int
pointers map[uintptr]int
ignoreNextType bool
cs *ConfigState
}
// buildDefaultFormat recreates the original format string without precision
// and width information to pass in to fmt.Sprintf in the case of an
// unrecognized type. Unless new types are added to the language, this
// function won't ever be called.
func (f *formatState) buildDefaultFormat() (format string) {
buf := bytes.NewBuffer(percentBytes)
for _, flag := range supportedFlags {
if f.fs.Flag(int(flag)) {
buf.WriteRune(flag)
}
}
buf.WriteRune('v')
format = buf.String()
return format
}
// constructOrigFormat recreates the original format string including precision
// and width information to pass along to the standard fmt package. This allows
// automatic deferral of all format strings this package doesn't support.
func (f *formatState) constructOrigFormat(verb rune) (format string) {
buf := bytes.NewBuffer(percentBytes)
for _, flag := range supportedFlags {
if f.fs.Flag(int(flag)) {
buf.WriteRune(flag)
}
}
if width, ok := f.fs.Width(); ok {
buf.WriteString(strconv.Itoa(width))
}
if precision, ok := f.fs.Precision(); ok {
buf.Write(precisionBytes)
buf.WriteString(strconv.Itoa(precision))
}
buf.WriteRune(verb)
format = buf.String()
return format
}
// unpackValue returns values inside of non-nil interfaces when possible and
// ensures that types for values which have been unpacked from an interface
// are displayed when the show types flag is also set.
// This is useful for data types like structs, arrays, slices, and maps which
// can contain varying types packed inside an interface.
func (f *formatState) unpackValue(v reflect.Value) reflect.Value {
if v.Kind() == reflect.Interface {
f.ignoreNextType = false
if !v.IsNil() {
v = v.Elem()
}
}
return v
}
// formatPtr handles formatting of pointers by indirecting them as necessary.
func (f *formatState) formatPtr(v reflect.Value) {
// Display nil if top level pointer is nil.
showTypes := f.fs.Flag('#')
if v.IsNil() && (!showTypes || f.ignoreNextType) {
f.fs.Write(nilAngleBytes)
return
}
// Remove pointers at or below the current depth from map used to detect
// circular refs.
for k, depth := range f.pointers {
if depth >= f.depth {
delete(f.pointers, k)
}
}
// Keep list of all dereferenced pointers to possibly show later.
pointerChain := make([]uintptr, 0)
// Figure out how many levels of indirection there are by derferencing
// pointers and unpacking interfaces down the chain while detecting circular
// references.
nilFound := false
cycleFound := false
indirects := 0
ve := v
for ve.Kind() == reflect.Ptr {
if ve.IsNil() {
nilFound = true
break
}
indirects++
addr := ve.Pointer()
pointerChain = append(pointerChain, addr)
if pd, ok := f.pointers[addr]; ok && pd < f.depth {
cycleFound = true
indirects--
break
}
f.pointers[addr] = f.depth
ve = ve.Elem()
if ve.Kind() == reflect.Interface {
if ve.IsNil() {
nilFound = true
break
}
ve = ve.Elem()
}
}
// Display type or indirection level depending on flags.
if showTypes && !f.ignoreNextType {
f.fs.Write(openParenBytes)
f.fs.Write(bytes.Repeat(asteriskBytes, indirects))
f.fs.Write([]byte(ve.Type().String()))
f.fs.Write(closeParenBytes)
} else {
if nilFound || cycleFound {
indirects += strings.Count(ve.Type().String(), "*")
}
f.fs.Write(openAngleBytes)
f.fs.Write([]byte(strings.Repeat("*", indirects)))
f.fs.Write(closeAngleBytes)
}
// Display pointer information depending on flags.
if f.fs.Flag('+') && (len(pointerChain) > 0) {
f.fs.Write(openParenBytes)
for i, addr := range pointerChain {
if i > 0 {
f.fs.Write(pointerChainBytes)
}
printHexPtr(f.fs, addr)
}
f.fs.Write(closeParenBytes)
}
// Display dereferenced value.
switch {
case nilFound:
f.fs.Write(nilAngleBytes)
case cycleFound:
f.fs.Write(circularShortBytes)
default:
f.ignoreNextType = true
f.format(ve)
}
}
// format is the main workhorse for providing the Formatter interface. It
// uses the passed reflect value to figure out what kind of object we are
// dealing with and formats it appropriately. It is a recursive function,
// however circular data structures are detected and handled properly.
func (f *formatState) format(v reflect.Value) {
// Handle invalid reflect values immediately.
kind := v.Kind()
if kind == reflect.Invalid {
f.fs.Write(invalidAngleBytes)
return
}
// Handle pointers specially.
if kind == reflect.Ptr {
f.formatPtr(v)
return
}
// Print type information unless already handled elsewhere.
if !f.ignoreNextType && f.fs.Flag('#') {
f.fs.Write(openParenBytes)
f.fs.Write([]byte(v.Type().String()))
f.fs.Write(closeParenBytes)
}
f.ignoreNextType = false
// Call Stringer/error interfaces if they exist and the handle methods
// flag is enabled.
if !f.cs.DisableMethods {
if (kind != reflect.Invalid) && (kind != reflect.Interface) {
if handled := handleMethods(f.cs, f.fs, v); handled {
return
}
}
}
switch kind {
case reflect.Invalid:
// Do nothing. We should never get here since invalid has already
// been handled above.
case reflect.Bool:
printBool(f.fs, v.Bool())
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
printInt(f.fs, v.Int(), 10)
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
printUint(f.fs, v.Uint(), 10)
case reflect.Float32:
printFloat(f.fs, v.Float(), 32)
case reflect.Float64:
printFloat(f.fs, v.Float(), 64)
case reflect.Complex64:
printComplex(f.fs, v.Complex(), 32)
case reflect.Complex128:
printComplex(f.fs, v.Complex(), 64)
case reflect.Slice:
if v.IsNil() {
f.fs.Write(nilAngleBytes)
break
}
fallthrough
case reflect.Array:
f.fs.Write(openBracketBytes)
f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.fs.Write(maxShortBytes)
} else {
numEntries := v.Len()
for i := 0; i < numEntries; i++ {
if i > 0 {
f.fs.Write(spaceBytes)
}
f.ignoreNextType = true
f.format(f.unpackValue(v.Index(i)))
}
}
f.depth--
f.fs.Write(closeBracketBytes)
case reflect.String:
f.fs.Write([]byte(v.String()))
case reflect.Interface:
// The only time we should get here is for nil interfaces due to
// unpackValue calls.
if v.IsNil() {
f.fs.Write(nilAngleBytes)
}
case reflect.Ptr:
// Do nothing. We should never get here since pointers have already
// been handled above.
case reflect.Map:
// nil maps should be indicated as different than empty maps
if v.IsNil() {
f.fs.Write(nilAngleBytes)
break
}
f.fs.Write(openMapBytes)
f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.fs.Write(maxShortBytes)
} else {
keys := v.MapKeys()
if f.cs.SortKeys {
sortValues(keys, f.cs)
}
for i, key := range keys {
if i > 0 {
f.fs.Write(spaceBytes)
}
f.ignoreNextType = true
f.format(f.unpackValue(key))
f.fs.Write(colonBytes)
f.ignoreNextType = true
f.format(f.unpackValue(v.MapIndex(key)))
}
}
f.depth--
f.fs.Write(closeMapBytes)
case reflect.Struct:
numFields := v.NumField()
f.fs.Write(openBraceBytes)
f.depth++
if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {
f.fs.Write(maxShortBytes)
} else {
vt := v.Type()
for i := 0; i < numFields; i++ {
if i > 0 {
f.fs.Write(spaceBytes)
}
vtf := vt.Field(i)
if f.fs.Flag('+') || f.fs.Flag('#') {
f.fs.Write([]byte(vtf.Name))
f.fs.Write(colonBytes)
}
f.format(f.unpackValue(v.Field(i)))
}
}
f.depth--
f.fs.Write(closeBraceBytes)
case reflect.Uintptr:
printHexPtr(f.fs, uintptr(v.Uint()))
case reflect.UnsafePointer, reflect.Chan, reflect.Func:
printHexPtr(f.fs, v.Pointer())
// There were not any other types at the time this code was written, but
// fall back to letting the default fmt package handle it if any get added.
default:
format := f.buildDefaultFormat()
if v.CanInterface() {
fmt.Fprintf(f.fs, format, v.Interface())
} else {
fmt.Fprintf(f.fs, format, v.String())
}
}
}
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
// details.
func (f *formatState) Format(fs fmt.State, verb rune) {
f.fs = fs
// Use standard formatting for verbs that are not v.
if verb != 'v' {
format := f.constructOrigFormat(verb)
fmt.Fprintf(fs, format, f.value)
return
}
if f.value == nil {
if fs.Flag('#') {
fs.Write(interfaceBytes)
}
fs.Write(nilAngleBytes)
return
}
f.format(reflect.ValueOf(f.value))
}
// newFormatter is a helper function to consolidate the logic from the various
// public methods which take varying config states.
func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter {
fs := &formatState{value: v, cs: cs}
fs.pointers = make(map[uintptr]int)
return fs
}
/*
NewFormatter returns a custom formatter that satisfies the fmt.Formatter
interface. As a result, it integrates cleanly with standard fmt package
printing functions. The formatter is useful for inline printing of smaller data
types similar to the standard %v format specifier.
The custom formatter only responds to the %v (most compact), %+v (adds pointer
addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb
combinations. Any other verbs such as %x and %q will be sent to the the
standard fmt package for formatting. In addition, the custom formatter ignores
the width and precision arguments (however they will still work on the format
specifiers not handled by the custom formatter).
Typically this function shouldn't be called directly. It is much easier to make
use of the custom formatter by calling one of the convenience functions such as
Printf, Println, or Fprintf.
*/
func NewFormatter(v interface{}) fmt.Formatter {
return newFormatter(&Config, v)
}
================================================
FILE: vendor/github.com/davecgh/go-spew/spew/spew.go
================================================
/*
* Copyright (c) 2013-2016 Dave Collins
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package spew
import (
"fmt"
"io"
)
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the formatted string as a value that satisfies error. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b))
func Errorf(format string, a ...interface{}) (err error) {
return fmt.Errorf(format, convertArgs(a)...)
}
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b))
func Fprint(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprint(w, convertArgs(a)...)
}
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b))
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
return fmt.Fprintf(w, format, convertArgs(a)...)
}
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
// passed with a default Formatter interface returned by NewFormatter. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprintln(w, convertArgs(a)...)
}
// Print is a wrapper for fmt.Print that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b))
func Print(a ...interface{}) (n int, err error) {
return fmt.Print(convertArgs(a)...)
}
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b))
func Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Printf(format, convertArgs(a)...)
}
// Println is a wrapper for fmt.Println that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the number of bytes written and any write error encountered. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b))
func Println(a ...interface{}) (n int, err error) {
return fmt.Println(convertArgs(a)...)
}
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
func Sprint(a ...interface{}) string {
return fmt.Sprint(convertArgs(a)...)
}
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
func Sprintf(format string, a ...interface{}) string {
return fmt.Sprintf(format, convertArgs(a)...)
}
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
// were passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
func Sprintln(a ...interface{}) string {
return fmt.Sprintln(convertArgs(a)...)
}
// convertArgs accepts a slice of arguments and returns a slice of the same
// length with each argument converted to a default spew Formatter interface.
func convertArgs(args []interface{}) (formatters []interface{}) {
formatters = make([]interface{}, len(args))
for index, arg := range args {
formatters[index] = NewFormatter(arg)
}
return formatters
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/.gitignore
================================================
.DS_Store
bin
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/.travis.yml
================================================
language: go
script:
- go vet ./...
- go test -v ./...
go:
- 1.3
- 1.4
- 1.5
- 1.6
- 1.7
- tip
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/LICENSE
================================================
Copyright (c) 2012 Dave Grijalva
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/MIGRATION_GUIDE.md
================================================
## Migration Guide from v2 -> v3
Version 3 adds several new, frequently requested features. To do so, it introduces a few breaking changes. We've worked to keep these as minimal as possible. This guide explains the breaking changes and how you can quickly update your code.
### `Token.Claims` is now an interface type
The most requested feature from the 2.0 verison of this library was the ability to provide a custom type to the JSON parser for claims. This was implemented by introducing a new interface, `Claims`, to replace `map[string]interface{}`. We also included two concrete implementations of `Claims`: `MapClaims` and `StandardClaims`.
`MapClaims` is an alias for `map[string]interface{}` with built in validation behavior. It is the default claims type when using `Parse`. The usage is unchanged except you must type cast the claims property.
The old example for parsing a token looked like this..
```go
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
}
```
is now directly mapped to...
```go
if token, err := jwt.Parse(tokenString, keyLookupFunc); err == nil {
claims := token.Claims.(jwt.MapClaims)
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
}
```
`StandardClaims` is designed to be embedded in your custom type. You can supply a custom claims type with the new `ParseWithClaims` function. Here's an example of using a custom claims type.
```go
type MyCustomClaims struct {
User string
*StandardClaims
}
if token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, keyLookupFunc); err == nil {
claims := token.Claims.(*MyCustomClaims)
fmt.Printf("Token for user %v expires %v", claims.User, claims.StandardClaims.ExpiresAt)
}
```
### `ParseFromRequest` has been moved
To keep this library focused on the tokens without becoming overburdened with complex request processing logic, `ParseFromRequest` and its new companion `ParseFromRequestWithClaims` have been moved to a subpackage, `request`. The method signatues have also been augmented to receive a new argument: `Extractor`.
`Extractors` do the work of picking the token string out of a request. The interface is simple and composable.
This simple parsing example:
```go
if token, err := jwt.ParseFromRequest(tokenString, req, keyLookupFunc); err == nil {
fmt.Printf("Token for user %v expires %v", token.Claims["user"], token.Claims["exp"])
}
```
is directly mapped to:
```go
if token, err := request.ParseFromRequest(req, request.OAuth2Extractor, keyLookupFunc); err == nil {
claims := token.Claims.(jwt.MapClaims)
fmt.Printf("Token for user %v expires %v", claims["user"], claims["exp"])
}
```
There are several concrete `Extractor` types provided for your convenience:
* `HeaderExtractor` will search a list of headers until one contains content.
* `ArgumentExtractor` will search a list of keys in request query and form arguments until one contains content.
* `MultiExtractor` will try a list of `Extractors` in order until one returns content.
* `AuthorizationHeaderExtractor` will look in the `Authorization` header for a `Bearer` token.
* `OAuth2Extractor` searches the places an OAuth2 token would be specified (per the spec): `Authorization` header and `access_token` argument
* `PostExtractionFilter` wraps an `Extractor`, allowing you to process the content before it's parsed. A simple example is stripping the `Bearer ` text from a header
### RSA signing methods no longer accept `[]byte` keys
Due to a [critical vulnerability](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/), we've decided the convenience of accepting `[]byte` instead of `rsa.PublicKey` or `rsa.PrivateKey` isn't worth the risk of misuse.
To replace this behavior, we've added two helper methods: `ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error)` and `ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error)`. These are just simple helpers for unpacking PEM encoded PKCS1 and PKCS8 keys. If your keys are encoded any other way, all you need to do is convert them to the `crypto/rsa` package's types.
```go
func keyLookupFunc(*Token) (interface{}, error) {
// Don't forget to validate the alg is what you expect:
if _, ok := token.Method.(*jwt.SigningMethodRSA); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
// Look up key
key, err := lookupPublicKey(token.Header["kid"])
if err != nil {
return nil, err
}
// Unpack key from PEM encoded PKCS8
return jwt.ParseRSAPublicKeyFromPEM(key)
}
```
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/README.md
================================================
# jwt-go
[](https://travis-ci.org/dgrijalva/jwt-go)
[](https://godoc.org/github.com/dgrijalva/jwt-go)
A [go](http://www.golang.org) (or 'golang' for search engine friendliness) implementation of [JSON Web Tokens](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html)
**NEW VERSION COMING:** There have been a lot of improvements suggested since the version 3.0.0 released in 2016. I'm working now on cutting two different releases: 3.2.0 will contain any non-breaking changes or enhancements. 4.0.0 will follow shortly which will include breaking changes. See the 4.0.0 milestone to get an idea of what's coming. If you have other ideas, or would like to participate in 4.0.0, now's the time. If you depend on this library and don't want to be interrupted, I recommend you use your dependency mangement tool to pin to version 3.
**SECURITY NOTICE:** Some older versions of Go have a security issue in the cryotp/elliptic. Recommendation is to upgrade to at least 1.8.3. See issue #216 for more detail.
**SECURITY NOTICE:** It's important that you [validate the `alg` presented is what you expect](https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). This library attempts to make it easy to do the right thing by requiring key types match the expected alg, but you should take the extra step to verify it in your usage. See the examples provided.
## What the heck is a JWT?
JWT.io has [a great introduction](https://jwt.io/introduction) to JSON Web Tokens.
In short, it's a signed JSON object that does something useful (for example, authentication). It's commonly used for `Bearer` tokens in Oauth 2. A token is made of three parts, separated by `.`'s. The first two parts are JSON objects, that have been [base64url](http://tools.ietf.org/html/rfc4648) encoded. The last part is the signature, encoded the same way.
The first part is called the header. It contains the necessary information for verifying the last part, the signature. For example, which encryption method was used for signing and what key was used.
The part in the middle is the interesting bit. It's called the Claims and contains the actual stuff you care about. Refer to [the RFC](http://self-issued.info/docs/draft-jones-json-web-token.html) for information about reserved keys and the proper way to add your own.
## What's in the box?
This library supports the parsing and verification as well as the generation and signing of JWTs. Current supported signing algorithms are HMAC SHA, RSA, RSA-PSS, and ECDSA, though hooks are present for adding your own.
## Examples
See [the project documentation](https://godoc.org/github.com/dgrijalva/jwt-go) for examples of usage:
* [Simple example of parsing and validating a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac)
* [Simple example of building and signing a token](https://godoc.org/github.com/dgrijalva/jwt-go#example-New--Hmac)
* [Directory of Examples](https://godoc.org/github.com/dgrijalva/jwt-go#pkg-examples)
## Extensions
This library publishes all the necessary components for adding your own signing methods. Simply implement the `SigningMethod` interface and register a factory method using `RegisterSigningMethod`.
Here's an example of an extension that integrates with the Google App Engine signing tools: https://github.com/someone1/gcp-jwt-go
## Compliance
This library was last reviewed to comply with [RTF 7519](http://www.rfc-editor.org/info/rfc7519) dated May 2015 with a few notable differences:
* In order to protect against accidental use of [Unsecured JWTs](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#UnsecuredJWT), tokens using `alg=none` will only be accepted if the constant `jwt.UnsafeAllowNoneSignatureType` is provided as the key.
## Project Status & Versioning
This library is considered production ready. Feedback and feature requests are appreciated. The API should be considered stable. There should be very few backwards-incompatible changes outside of major version updates (and only with good reason).
This project uses [Semantic Versioning 2.0.0](http://semver.org). Accepted pull requests will land on `master`. Periodically, versions will be tagged from `master`. You can find all the releases on [the project releases page](https://github.com/dgrijalva/jwt-go/releases).
While we try to make it obvious when we make breaking changes, there isn't a great mechanism for pushing announcements out to users. You may want to use this alternative package include: `gopkg.in/dgrijalva/jwt-go.v3`. It will do the right thing WRT semantic versioning.
**BREAKING CHANGES:***
* Version 3.0.0 includes _a lot_ of changes from the 2.x line, including a few that break the API. We've tried to break as few things as possible, so there should just be a few type signature changes. A full list of breaking changes is available in `VERSION_HISTORY.md`. See `MIGRATION_GUIDE.md` for more information on updating your code.
## Usage Tips
### Signing vs Encryption
A token is simply a JSON object that is signed by its author. this tells you exactly two things about the data:
* The author of the token was in the possession of the signing secret
* The data has not been modified since it was signed
It's important to know that JWT does not provide encryption, which means anyone who has access to the token can read its contents. If you need to protect (encrypt) the data, there is a companion spec, `JWE`, that provides this functionality. JWE is currently outside the scope of this library.
### Choosing a Signing Method
There are several signing methods available, and you should probably take the time to learn about the various options before choosing one. The principal design decision is most likely going to be symmetric vs asymmetric.
Symmetric signing methods, such as HSA, use only a single secret. This is probably the simplest signing method to use since any `[]byte` can be used as a valid secret. They are also slightly computationally faster to use, though this rarely is enough to matter. Symmetric signing methods work the best when both producers and consumers of tokens are trusted, or even the same system. Since the same secret is used to both sign and validate tokens, you can't easily distribute the key for validation.
Asymmetric signing methods, such as RSA, use different keys for signing and verifying tokens. This makes it possible to produce tokens with a private key, and allow any consumer to access the public key for verification.
### Signing Methods and Key Types
Each signing method expects a different object type for its signing keys. See the package documentation for details. Here are the most common ones:
* The [HMAC signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodHMAC) (`HS256`,`HS384`,`HS512`) expect `[]byte` values for signing and validation
* The [RSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodRSA) (`RS256`,`RS384`,`RS512`) expect `*rsa.PrivateKey` for signing and `*rsa.PublicKey` for validation
* The [ECDSA signing method](https://godoc.org/github.com/dgrijalva/jwt-go#SigningMethodECDSA) (`ES256`,`ES384`,`ES512`) expect `*ecdsa.PrivateKey` for signing and `*ecdsa.PublicKey` for validation
### JWT and OAuth
It's worth mentioning that OAuth and JWT are not the same thing. A JWT token is simply a signed JSON object. It can be used anywhere such a thing is useful. There is some confusion, though, as JWT is the most common type of bearer token used in OAuth2 authentication.
Without going too far down the rabbit hole, here's a description of the interaction of these technologies:
* OAuth is a protocol for allowing an identity provider to be separate from the service a user is logging in to. For example, whenever you use Facebook to log into a different service (Yelp, Spotify, etc), you are using OAuth.
* OAuth defines several options for passing around authentication data. One popular method is called a "bearer token". A bearer token is simply a string that _should_ only be held by an authenticated user. Thus, simply presenting this token proves your identity. You can probably derive from here why a JWT might make a good bearer token.
* Because bearer tokens are used for authentication, it's important they're kept secret. This is why transactions that use bearer tokens typically happen over SSL.
## More
Documentation can be found [on godoc.org](http://godoc.org/github.com/dgrijalva/jwt-go).
The command line utility included in this project (cmd/jwt) provides a straightforward example of token creation and parsing as well as a useful tool for debugging your own integration. You'll also find several implementation examples in the documentation.
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/VERSION_HISTORY.md
================================================
## `jwt-go` Version History
#### 3.2.0
* Added method `ParseUnverified` to allow users to split up the tasks of parsing and validation
* HMAC signing method returns `ErrInvalidKeyType` instead of `ErrInvalidKey` where appropriate
* Added options to `request.ParseFromRequest`, which allows for an arbitrary list of modifiers to parsing behavior. Initial set include `WithClaims` and `WithParser`. Existing usage of this function will continue to work as before.
* Deprecated `ParseFromRequestWithClaims` to simplify API in the future.
#### 3.1.0
* Improvements to `jwt` command line tool
* Added `SkipClaimsValidation` option to `Parser`
* Documentation updates
#### 3.0.0
* **Compatibility Breaking Changes**: See MIGRATION_GUIDE.md for tips on updating your code
* Dropped support for `[]byte` keys when using RSA signing methods. This convenience feature could contribute to security vulnerabilities involving mismatched key types with signing methods.
* `ParseFromRequest` has been moved to `request` subpackage and usage has changed
* The `Claims` property on `Token` is now type `Claims` instead of `map[string]interface{}`. The default value is type `MapClaims`, which is an alias to `map[string]interface{}`. This makes it possible to use a custom type when decoding claims.
* Other Additions and Changes
* Added `Claims` interface type to allow users to decode the claims into a custom type
* Added `ParseWithClaims`, which takes a third argument of type `Claims`. Use this function instead of `Parse` if you have a custom type you'd like to decode into.
* Dramatically improved the functionality and flexibility of `ParseFromRequest`, which is now in the `request` subpackage
* Added `ParseFromRequestWithClaims` which is the `FromRequest` equivalent of `ParseWithClaims`
* Added new interface type `Extractor`, which is used for extracting JWT strings from http requests. Used with `ParseFromRequest` and `ParseFromRequestWithClaims`.
* Added several new, more specific, validation errors to error type bitmask
* Moved examples from README to executable example files
* Signing method registry is now thread safe
* Added new property to `ValidationError`, which contains the raw error returned by calls made by parse/verify (such as those returned by keyfunc or json parser)
#### 2.7.0
This will likely be the last backwards compatible release before 3.0.0, excluding essential bug fixes.
* Added new option `-show` to the `jwt` command that will just output the decoded token without verifying
* Error text for expired tokens includes how long it's been expired
* Fixed incorrect error returned from `ParseRSAPublicKeyFromPEM`
* Documentation updates
#### 2.6.0
* Exposed inner error within ValidationError
* Fixed validation errors when using UseJSONNumber flag
* Added several unit tests
#### 2.5.0
* Added support for signing method none. You shouldn't use this. The API tries to make this clear.
* Updated/fixed some documentation
* Added more helpful error message when trying to parse tokens that begin with `BEARER `
#### 2.4.0
* Added new type, Parser, to allow for configuration of various parsing parameters
* You can now specify a list of valid signing methods. Anything outside this set will be rejected.
* You can now opt to use the `json.Number` type instead of `float64` when parsing token JSON
* Added support for [Travis CI](https://travis-ci.org/dgrijalva/jwt-go)
* Fixed some bugs with ECDSA parsing
#### 2.3.0
* Added support for ECDSA signing methods
* Added support for RSA PSS signing methods (requires go v1.4)
#### 2.2.0
* Gracefully handle a `nil` `Keyfunc` being passed to `Parse`. Result will now be the parsed token and an error, instead of a panic.
#### 2.1.0
Backwards compatible API change that was missed in 2.0.0.
* The `SignedString` method on `Token` now takes `interface{}` instead of `[]byte`
#### 2.0.0
There were two major reasons for breaking backwards compatibility with this update. The first was a refactor required to expand the width of the RSA and HMAC-SHA signing implementations. There will likely be no required code changes to support this change.
The second update, while unfortunately requiring a small change in integration, is required to open up this library to other signing methods. Not all keys used for all signing methods have a single standard on-disk representation. Requiring `[]byte` as the type for all keys proved too limiting. Additionally, this implementation allows for pre-parsed tokens to be reused, which might matter in an application that parses a high volume of tokens with a small set of keys. Backwards compatibilty has been maintained for passing `[]byte` to the RSA signing methods, but they will also accept `*rsa.PublicKey` and `*rsa.PrivateKey`.
It is likely the only integration change required here will be to change `func(t *jwt.Token) ([]byte, error)` to `func(t *jwt.Token) (interface{}, error)` when calling `Parse`.
* **Compatibility Breaking Changes**
* `SigningMethodHS256` is now `*SigningMethodHMAC` instead of `type struct`
* `SigningMethodRS256` is now `*SigningMethodRSA` instead of `type struct`
* `KeyFunc` now returns `interface{}` instead of `[]byte`
* `SigningMethod.Sign` now takes `interface{}` instead of `[]byte` for the key
* `SigningMethod.Verify` now takes `interface{}` instead of `[]byte` for the key
* Renamed type `SigningMethodHS256` to `SigningMethodHMAC`. Specific sizes are now just instances of this type.
* Added public package global `SigningMethodHS256`
* Added public package global `SigningMethodHS384`
* Added public package global `SigningMethodHS512`
* Renamed type `SigningMethodRS256` to `SigningMethodRSA`. Specific sizes are now just instances of this type.
* Added public package global `SigningMethodRS256`
* Added public package global `SigningMethodRS384`
* Added public package global `SigningMethodRS512`
* Moved sample private key for HMAC tests from an inline value to a file on disk. Value is unchanged.
* Refactored the RSA implementation to be easier to read
* Exposed helper methods `ParseRSAPrivateKeyFromPEM` and `ParseRSAPublicKeyFromPEM`
#### 1.0.2
* Fixed bug in parsing public keys from certificates
* Added more tests around the parsing of keys for RS256
* Code refactoring in RS256 implementation. No functional changes
#### 1.0.1
* Fixed panic if RS256 signing method was passed an invalid key
#### 1.0.0
* First versioned release
* API stabilized
* Supports creating, signing, parsing, and validating JWT tokens
* Supports RS256 and HS256 signing methods
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/claims.go
================================================
package jwt
import (
"crypto/subtle"
"fmt"
"time"
)
// For a type to be a Claims object, it must just have a Valid method that determines
// if the token is invalid for any supported reason
type Claims interface {
Valid() error
}
// Structured version of Claims Section, as referenced at
// https://tools.ietf.org/html/rfc7519#section-4.1
// See examples for how to use this with your own claim types
type StandardClaims struct {
Audience string `json:"aud,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
Id string `json:"jti,omitempty"`
IssuedAt int64 `json:"iat,omitempty"`
Issuer string `json:"iss,omitempty"`
NotBefore int64 `json:"nbf,omitempty"`
Subject string `json:"sub,omitempty"`
}
// Validates time based claims "exp, iat, nbf".
// There is no accounting for clock skew.
// As well, if any of the above claims are not in the token, it will still
// be considered a valid claim.
func (c StandardClaims) Valid() error {
vErr := new(ValidationError)
now := TimeFunc().Unix()
// The claims below are optional, by default, so if they are set to the
// default value in Go, let's not fail the verification for them.
if c.VerifyExpiresAt(now, false) == false {
delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0))
vErr.Inner = fmt.Errorf("token is expired by %v", delta)
vErr.Errors |= ValidationErrorExpired
}
if c.VerifyIssuedAt(now, false) == false {
vErr.Inner = fmt.Errorf("Token used before issued")
vErr.Errors |= ValidationErrorIssuedAt
}
if c.VerifyNotBefore(now, false) == false {
vErr.Inner = fmt.Errorf("token is not valid yet")
vErr.Errors |= ValidationErrorNotValidYet
}
if vErr.valid() {
return nil
}
return vErr
}
// Compares the aud claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyAudience(cmp string, req bool) bool {
return verifyAud(c.Audience, cmp, req)
}
// Compares the exp claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyExpiresAt(cmp int64, req bool) bool {
return verifyExp(c.ExpiresAt, cmp, req)
}
// Compares the iat claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyIssuedAt(cmp int64, req bool) bool {
return verifyIat(c.IssuedAt, cmp, req)
}
// Compares the iss claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyIssuer(cmp string, req bool) bool {
return verifyIss(c.Issuer, cmp, req)
}
// Compares the nbf claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (c *StandardClaims) VerifyNotBefore(cmp int64, req bool) bool {
return verifyNbf(c.NotBefore, cmp, req)
}
// ----- helpers
func verifyAud(aud string, cmp string, required bool) bool {
if aud == "" {
return !required
}
if subtle.ConstantTimeCompare([]byte(aud), []byte(cmp)) != 0 {
return true
} else {
return false
}
}
func verifyExp(exp int64, now int64, required bool) bool {
if exp == 0 {
return !required
}
return now <= exp
}
func verifyIat(iat int64, now int64, required bool) bool {
if iat == 0 {
return !required
}
return now >= iat
}
func verifyIss(iss string, cmp string, required bool) bool {
if iss == "" {
return !required
}
if subtle.ConstantTimeCompare([]byte(iss), []byte(cmp)) != 0 {
return true
} else {
return false
}
}
func verifyNbf(nbf int64, now int64, required bool) bool {
if nbf == 0 {
return !required
}
return now >= nbf
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/doc.go
================================================
// Package jwt is a Go implementation of JSON Web Tokens: http://self-issued.info/docs/draft-jones-json-web-token.html
//
// See README.md for more info.
package jwt
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/ecdsa.go
================================================
package jwt
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"errors"
"math/big"
)
var (
// Sadly this is missing from crypto/ecdsa compared to crypto/rsa
ErrECDSAVerification = errors.New("crypto/ecdsa: verification error")
)
// Implements the ECDSA family of signing methods signing methods
// Expects *ecdsa.PrivateKey for signing and *ecdsa.PublicKey for verification
type SigningMethodECDSA struct {
Name string
Hash crypto.Hash
KeySize int
CurveBits int
}
// Specific instances for EC256 and company
var (
SigningMethodES256 *SigningMethodECDSA
SigningMethodES384 *SigningMethodECDSA
SigningMethodES512 *SigningMethodECDSA
)
func init() {
// ES256
SigningMethodES256 = &SigningMethodECDSA{"ES256", crypto.SHA256, 32, 256}
RegisterSigningMethod(SigningMethodES256.Alg(), func() SigningMethod {
return SigningMethodES256
})
// ES384
SigningMethodES384 = &SigningMethodECDSA{"ES384", crypto.SHA384, 48, 384}
RegisterSigningMethod(SigningMethodES384.Alg(), func() SigningMethod {
return SigningMethodES384
})
// ES512
SigningMethodES512 = &SigningMethodECDSA{"ES512", crypto.SHA512, 66, 521}
RegisterSigningMethod(SigningMethodES512.Alg(), func() SigningMethod {
return SigningMethodES512
})
}
func (m *SigningMethodECDSA) Alg() string {
return m.Name
}
// Implements the Verify method from SigningMethod
// For this verify method, key must be an ecdsa.PublicKey struct
func (m *SigningMethodECDSA) Verify(signingString, signature string, key interface{}) error {
var err error
// Decode the signature
var sig []byte
if sig, err = DecodeSegment(signature); err != nil {
return err
}
// Get the key
var ecdsaKey *ecdsa.PublicKey
switch k := key.(type) {
case *ecdsa.PublicKey:
ecdsaKey = k
default:
return ErrInvalidKeyType
}
if len(sig) != 2*m.KeySize {
return ErrECDSAVerification
}
r := big.NewInt(0).SetBytes(sig[:m.KeySize])
s := big.NewInt(0).SetBytes(sig[m.KeySize:])
// Create hasher
if !m.Hash.Available() {
return ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
// Verify the signature
if verifystatus := ecdsa.Verify(ecdsaKey, hasher.Sum(nil), r, s); verifystatus == true {
return nil
} else {
return ErrECDSAVerification
}
}
// Implements the Sign method from SigningMethod
// For this signing method, key must be an ecdsa.PrivateKey struct
func (m *SigningMethodECDSA) Sign(signingString string, key interface{}) (string, error) {
// Get the key
var ecdsaKey *ecdsa.PrivateKey
switch k := key.(type) {
case *ecdsa.PrivateKey:
ecdsaKey = k
default:
return "", ErrInvalidKeyType
}
// Create the hasher
if !m.Hash.Available() {
return "", ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
// Sign the string and return r, s
if r, s, err := ecdsa.Sign(rand.Reader, ecdsaKey, hasher.Sum(nil)); err == nil {
curveBits := ecdsaKey.Curve.Params().BitSize
if m.CurveBits != curveBits {
return "", ErrInvalidKey
}
keyBytes := curveBits / 8
if curveBits%8 > 0 {
keyBytes += 1
}
// We serialize the outpus (r and s) into big-endian byte arrays and pad
// them with zeros on the left to make sure the sizes work out. Both arrays
// must be keyBytes long, and the output must be 2*keyBytes long.
rBytes := r.Bytes()
rBytesPadded := make([]byte, keyBytes)
copy(rBytesPadded[keyBytes-len(rBytes):], rBytes)
sBytes := s.Bytes()
sBytesPadded := make([]byte, keyBytes)
copy(sBytesPadded[keyBytes-len(sBytes):], sBytes)
out := append(rBytesPadded, sBytesPadded...)
return EncodeSegment(out), nil
} else {
return "", err
}
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/ecdsa_utils.go
================================================
package jwt
import (
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"errors"
)
var (
ErrNotECPublicKey = errors.New("Key is not a valid ECDSA public key")
ErrNotECPrivateKey = errors.New("Key is not a valid ECDSA private key")
)
// Parse PEM encoded Elliptic Curve Private Key Structure
func ParseECPrivateKeyFromPEM(key []byte) (*ecdsa.PrivateKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, ErrKeyMustBePEMEncoded
}
// Parse the key
var parsedKey interface{}
if parsedKey, err = x509.ParseECPrivateKey(block.Bytes); err != nil {
return nil, err
}
var pkey *ecdsa.PrivateKey
var ok bool
if pkey, ok = parsedKey.(*ecdsa.PrivateKey); !ok {
return nil, ErrNotECPrivateKey
}
return pkey, nil
}
// Parse PEM encoded PKCS1 or PKCS8 public key
func ParseECPublicKeyFromPEM(key []byte) (*ecdsa.PublicKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, ErrKeyMustBePEMEncoded
}
// Parse the key
var parsedKey interface{}
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
if cert, err := x509.ParseCertificate(block.Bytes); err == nil {
parsedKey = cert.PublicKey
} else {
return nil, err
}
}
var pkey *ecdsa.PublicKey
var ok bool
if pkey, ok = parsedKey.(*ecdsa.PublicKey); !ok {
return nil, ErrNotECPublicKey
}
return pkey, nil
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/errors.go
================================================
package jwt
import (
"errors"
)
// Error constants
var (
ErrInvalidKey = errors.New("key is invalid")
ErrInvalidKeyType = errors.New("key is of invalid type")
ErrHashUnavailable = errors.New("the requested hash function is unavailable")
)
// The errors that might occur when parsing and validating a token
const (
ValidationErrorMalformed uint32 = 1 << iota // Token is malformed
ValidationErrorUnverifiable // Token could not be verified because of signing problems
ValidationErrorSignatureInvalid // Signature validation failed
// Standard Claim validation errors
ValidationErrorAudience // AUD validation failed
ValidationErrorExpired // EXP validation failed
ValidationErrorIssuedAt // IAT validation failed
ValidationErrorIssuer // ISS validation failed
ValidationErrorNotValidYet // NBF validation failed
ValidationErrorId // JTI validation failed
ValidationErrorClaimsInvalid // Generic claims validation error
)
// Helper for constructing a ValidationError with a string error message
func NewValidationError(errorText string, errorFlags uint32) *ValidationError {
return &ValidationError{
text: errorText,
Errors: errorFlags,
}
}
// The error from Parse if token is not valid
type ValidationError struct {
Inner error // stores the error returned by external dependencies, i.e.: KeyFunc
Errors uint32 // bitfield. see ValidationError... constants
text string // errors that do not have a valid error just have text
}
// Validation error is an error type
func (e ValidationError) Error() string {
if e.Inner != nil {
return e.Inner.Error()
} else if e.text != "" {
return e.text
} else {
return "token is invalid"
}
}
// No errors
func (e *ValidationError) valid() bool {
return e.Errors == 0
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/hmac.go
================================================
package jwt
import (
"crypto"
"crypto/hmac"
"errors"
)
// Implements the HMAC-SHA family of signing methods signing methods
// Expects key type of []byte for both signing and validation
type SigningMethodHMAC struct {
Name string
Hash crypto.Hash
}
// Specific instances for HS256 and company
var (
SigningMethodHS256 *SigningMethodHMAC
SigningMethodHS384 *SigningMethodHMAC
SigningMethodHS512 *SigningMethodHMAC
ErrSignatureInvalid = errors.New("signature is invalid")
)
func init() {
// HS256
SigningMethodHS256 = &SigningMethodHMAC{"HS256", crypto.SHA256}
RegisterSigningMethod(SigningMethodHS256.Alg(), func() SigningMethod {
return SigningMethodHS256
})
// HS384
SigningMethodHS384 = &SigningMethodHMAC{"HS384", crypto.SHA384}
RegisterSigningMethod(SigningMethodHS384.Alg(), func() SigningMethod {
return SigningMethodHS384
})
// HS512
SigningMethodHS512 = &SigningMethodHMAC{"HS512", crypto.SHA512}
RegisterSigningMethod(SigningMethodHS512.Alg(), func() SigningMethod {
return SigningMethodHS512
})
}
func (m *SigningMethodHMAC) Alg() string {
return m.Name
}
// Verify the signature of HSXXX tokens. Returns nil if the signature is valid.
func (m *SigningMethodHMAC) Verify(signingString, signature string, key interface{}) error {
// Verify the key is the right type
keyBytes, ok := key.([]byte)
if !ok {
return ErrInvalidKeyType
}
// Decode signature, for comparison
sig, err := DecodeSegment(signature)
if err != nil {
return err
}
// Can we use the specified hashing method?
if !m.Hash.Available() {
return ErrHashUnavailable
}
// This signing method is symmetric, so we validate the signature
// by reproducing the signature from the signing string and key, then
// comparing that against the provided signature.
hasher := hmac.New(m.Hash.New, keyBytes)
hasher.Write([]byte(signingString))
if !hmac.Equal(sig, hasher.Sum(nil)) {
return ErrSignatureInvalid
}
// No validation errors. Signature is good.
return nil
}
// Implements the Sign method from SigningMethod for this signing method.
// Key must be []byte
func (m *SigningMethodHMAC) Sign(signingString string, key interface{}) (string, error) {
if keyBytes, ok := key.([]byte); ok {
if !m.Hash.Available() {
return "", ErrHashUnavailable
}
hasher := hmac.New(m.Hash.New, keyBytes)
hasher.Write([]byte(signingString))
return EncodeSegment(hasher.Sum(nil)), nil
}
return "", ErrInvalidKeyType
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/map_claims.go
================================================
package jwt
import (
"encoding/json"
"errors"
// "fmt"
)
// Claims type that uses the map[string]interface{} for JSON decoding
// This is the default claims type if you don't supply one
type MapClaims map[string]interface{}
// Compares the aud claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyAudience(cmp string, req bool) bool {
aud, _ := m["aud"].(string)
return verifyAud(aud, cmp, req)
}
// Compares the exp claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyExpiresAt(cmp int64, req bool) bool {
switch exp := m["exp"].(type) {
case float64:
return verifyExp(int64(exp), cmp, req)
case json.Number:
v, _ := exp.Int64()
return verifyExp(v, cmp, req)
}
return req == false
}
// Compares the iat claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyIssuedAt(cmp int64, req bool) bool {
switch iat := m["iat"].(type) {
case float64:
return verifyIat(int64(iat), cmp, req)
case json.Number:
v, _ := iat.Int64()
return verifyIat(v, cmp, req)
}
return req == false
}
// Compares the iss claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyIssuer(cmp string, req bool) bool {
iss, _ := m["iss"].(string)
return verifyIss(iss, cmp, req)
}
// Compares the nbf claim against cmp.
// If required is false, this method will return true if the value matches or is unset
func (m MapClaims) VerifyNotBefore(cmp int64, req bool) bool {
switch nbf := m["nbf"].(type) {
case float64:
return verifyNbf(int64(nbf), cmp, req)
case json.Number:
v, _ := nbf.Int64()
return verifyNbf(v, cmp, req)
}
return req == false
}
// Validates time based claims "exp, iat, nbf".
// There is no accounting for clock skew.
// As well, if any of the above claims are not in the token, it will still
// be considered a valid claim.
func (m MapClaims) Valid() error {
vErr := new(ValidationError)
now := TimeFunc().Unix()
if m.VerifyExpiresAt(now, false) == false {
vErr.Inner = errors.New("Token is expired")
vErr.Errors |= ValidationErrorExpired
}
if m.VerifyIssuedAt(now, false) == false {
vErr.Inner = errors.New("Token used before issued")
vErr.Errors |= ValidationErrorIssuedAt
}
if m.VerifyNotBefore(now, false) == false {
vErr.Inner = errors.New("Token is not valid yet")
vErr.Errors |= ValidationErrorNotValidYet
}
if vErr.valid() {
return nil
}
return vErr
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/none.go
================================================
package jwt
// Implements the none signing method. This is required by the spec
// but you probably should never use it.
var SigningMethodNone *signingMethodNone
const UnsafeAllowNoneSignatureType unsafeNoneMagicConstant = "none signing method allowed"
var NoneSignatureTypeDisallowedError error
type signingMethodNone struct{}
type unsafeNoneMagicConstant string
func init() {
SigningMethodNone = &signingMethodNone{}
NoneSignatureTypeDisallowedError = NewValidationError("'none' signature type is not allowed", ValidationErrorSignatureInvalid)
RegisterSigningMethod(SigningMethodNone.Alg(), func() SigningMethod {
return SigningMethodNone
})
}
func (m *signingMethodNone) Alg() string {
return "none"
}
// Only allow 'none' alg type if UnsafeAllowNoneSignatureType is specified as the key
func (m *signingMethodNone) Verify(signingString, signature string, key interface{}) (err error) {
// Key must be UnsafeAllowNoneSignatureType to prevent accidentally
// accepting 'none' signing method
if _, ok := key.(unsafeNoneMagicConstant); !ok {
return NoneSignatureTypeDisallowedError
}
// If signing method is none, signature must be an empty string
if signature != "" {
return NewValidationError(
"'none' signing method with non-empty signature",
ValidationErrorSignatureInvalid,
)
}
// Accept 'none' signing method.
return nil
}
// Only allow 'none' signing if UnsafeAllowNoneSignatureType is specified as the key
func (m *signingMethodNone) Sign(signingString string, key interface{}) (string, error) {
if _, ok := key.(unsafeNoneMagicConstant); ok {
return "", nil
}
return "", NoneSignatureTypeDisallowedError
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/parser.go
================================================
package jwt
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
type Parser struct {
ValidMethods []string // If populated, only these methods will be considered valid
UseJSONNumber bool // Use JSON Number format in JSON decoder
SkipClaimsValidation bool // Skip claims validation during token parsing
}
// Parse, validate, and return a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func (p *Parser) Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return p.ParseWithClaims(tokenString, MapClaims{}, keyFunc)
}
func (p *Parser) ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
token, parts, err := p.ParseUnverified(tokenString, claims)
if err != nil {
return token, err
}
// Verify signing method is in the required set
if p.ValidMethods != nil {
var signingMethodValid = false
var alg = token.Method.Alg()
for _, m := range p.ValidMethods {
if m == alg {
signingMethodValid = true
break
}
}
if !signingMethodValid {
// signing method is not in the listed set
return token, NewValidationError(fmt.Sprintf("signing method %v is invalid", alg), ValidationErrorSignatureInvalid)
}
}
// Lookup key
var key interface{}
if keyFunc == nil {
// keyFunc was not provided. short circuiting validation
return token, NewValidationError("no Keyfunc was provided.", ValidationErrorUnverifiable)
}
if key, err = keyFunc(token); err != nil {
// keyFunc returned an error
if ve, ok := err.(*ValidationError); ok {
return token, ve
}
return token, &ValidationError{Inner: err, Errors: ValidationErrorUnverifiable}
}
vErr := &ValidationError{}
// Validate Claims
if !p.SkipClaimsValidation {
if err := token.Claims.Valid(); err != nil {
// If the Claims Valid returned an error, check if it is a validation error,
// If it was another error type, create a ValidationError with a generic ClaimsInvalid flag set
if e, ok := err.(*ValidationError); !ok {
vErr = &ValidationError{Inner: err, Errors: ValidationErrorClaimsInvalid}
} else {
vErr = e
}
}
}
// Perform validation
token.Signature = parts[2]
if err = token.Method.Verify(strings.Join(parts[0:2], "."), token.Signature, key); err != nil {
vErr.Inner = err
vErr.Errors |= ValidationErrorSignatureInvalid
}
if vErr.valid() {
token.Valid = true
return token, nil
}
return token, vErr
}
// WARNING: Don't use this method unless you know what you're doing
//
// This method parses the token but doesn't validate the signature. It's only
// ever useful in cases where you know the signature is valid (because it has
// been checked previously in the stack) and you want to extract values from
// it.
func (p *Parser) ParseUnverified(tokenString string, claims Claims) (token *Token, parts []string, err error) {
parts = strings.Split(tokenString, ".")
if len(parts) != 3 {
return nil, parts, NewValidationError("token contains an invalid number of segments", ValidationErrorMalformed)
}
token = &Token{Raw: tokenString}
// parse Header
var headerBytes []byte
if headerBytes, err = DecodeSegment(parts[0]); err != nil {
if strings.HasPrefix(strings.ToLower(tokenString), "bearer ") {
return token, parts, NewValidationError("tokenstring should not contain 'bearer '", ValidationErrorMalformed)
}
return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
if err = json.Unmarshal(headerBytes, &token.Header); err != nil {
return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
// parse Claims
var claimBytes []byte
token.Claims = claims
if claimBytes, err = DecodeSegment(parts[1]); err != nil {
return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
dec := json.NewDecoder(bytes.NewBuffer(claimBytes))
if p.UseJSONNumber {
dec.UseNumber()
}
// JSON Decode. Special case for map type to avoid weird pointer behavior
if c, ok := token.Claims.(MapClaims); ok {
err = dec.Decode(&c)
} else {
err = dec.Decode(&claims)
}
// Handle decode error
if err != nil {
return token, parts, &ValidationError{Inner: err, Errors: ValidationErrorMalformed}
}
// Lookup signature method
if method, ok := token.Header["alg"].(string); ok {
if token.Method = GetSigningMethod(method); token.Method == nil {
return token, parts, NewValidationError("signing method (alg) is unavailable.", ValidationErrorUnverifiable)
}
} else {
return token, parts, NewValidationError("signing method (alg) is unspecified.", ValidationErrorUnverifiable)
}
return token, parts, nil
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/rsa.go
================================================
package jwt
import (
"crypto"
"crypto/rand"
"crypto/rsa"
)
// Implements the RSA family of signing methods signing methods
// Expects *rsa.PrivateKey for signing and *rsa.PublicKey for validation
type SigningMethodRSA struct {
Name string
Hash crypto.Hash
}
// Specific instances for RS256 and company
var (
SigningMethodRS256 *SigningMethodRSA
SigningMethodRS384 *SigningMethodRSA
SigningMethodRS512 *SigningMethodRSA
)
func init() {
// RS256
SigningMethodRS256 = &SigningMethodRSA{"RS256", crypto.SHA256}
RegisterSigningMethod(SigningMethodRS256.Alg(), func() SigningMethod {
return SigningMethodRS256
})
// RS384
SigningMethodRS384 = &SigningMethodRSA{"RS384", crypto.SHA384}
RegisterSigningMethod(SigningMethodRS384.Alg(), func() SigningMethod {
return SigningMethodRS384
})
// RS512
SigningMethodRS512 = &SigningMethodRSA{"RS512", crypto.SHA512}
RegisterSigningMethod(SigningMethodRS512.Alg(), func() SigningMethod {
return SigningMethodRS512
})
}
func (m *SigningMethodRSA) Alg() string {
return m.Name
}
// Implements the Verify method from SigningMethod
// For this signing method, must be an *rsa.PublicKey structure.
func (m *SigningMethodRSA) Verify(signingString, signature string, key interface{}) error {
var err error
// Decode the signature
var sig []byte
if sig, err = DecodeSegment(signature); err != nil {
return err
}
var rsaKey *rsa.PublicKey
var ok bool
if rsaKey, ok = key.(*rsa.PublicKey); !ok {
return ErrInvalidKeyType
}
// Create hasher
if !m.Hash.Available() {
return ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
// Verify the signature
return rsa.VerifyPKCS1v15(rsaKey, m.Hash, hasher.Sum(nil), sig)
}
// Implements the Sign method from SigningMethod
// For this signing method, must be an *rsa.PrivateKey structure.
func (m *SigningMethodRSA) Sign(signingString string, key interface{}) (string, error) {
var rsaKey *rsa.PrivateKey
var ok bool
// Validate type of key
if rsaKey, ok = key.(*rsa.PrivateKey); !ok {
return "", ErrInvalidKey
}
// Create the hasher
if !m.Hash.Available() {
return "", ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
// Sign the string and return the encoded bytes
if sigBytes, err := rsa.SignPKCS1v15(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil)); err == nil {
return EncodeSegment(sigBytes), nil
} else {
return "", err
}
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/rsa_pss.go
================================================
// +build go1.4
package jwt
import (
"crypto"
"crypto/rand"
"crypto/rsa"
)
// Implements the RSAPSS family of signing methods signing methods
type SigningMethodRSAPSS struct {
*SigningMethodRSA
Options *rsa.PSSOptions
}
// Specific instances for RS/PS and company
var (
SigningMethodPS256 *SigningMethodRSAPSS
SigningMethodPS384 *SigningMethodRSAPSS
SigningMethodPS512 *SigningMethodRSAPSS
)
func init() {
// PS256
SigningMethodPS256 = &SigningMethodRSAPSS{
&SigningMethodRSA{
Name: "PS256",
Hash: crypto.SHA256,
},
&rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: crypto.SHA256,
},
}
RegisterSigningMethod(SigningMethodPS256.Alg(), func() SigningMethod {
return SigningMethodPS256
})
// PS384
SigningMethodPS384 = &SigningMethodRSAPSS{
&SigningMethodRSA{
Name: "PS384",
Hash: crypto.SHA384,
},
&rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: crypto.SHA384,
},
}
RegisterSigningMethod(SigningMethodPS384.Alg(), func() SigningMethod {
return SigningMethodPS384
})
// PS512
SigningMethodPS512 = &SigningMethodRSAPSS{
&SigningMethodRSA{
Name: "PS512",
Hash: crypto.SHA512,
},
&rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthAuto,
Hash: crypto.SHA512,
},
}
RegisterSigningMethod(SigningMethodPS512.Alg(), func() SigningMethod {
return SigningMethodPS512
})
}
// Implements the Verify method from SigningMethod
// For this verify method, key must be an rsa.PublicKey struct
func (m *SigningMethodRSAPSS) Verify(signingString, signature string, key interface{}) error {
var err error
// Decode the signature
var sig []byte
if sig, err = DecodeSegment(signature); err != nil {
return err
}
var rsaKey *rsa.PublicKey
switch k := key.(type) {
case *rsa.PublicKey:
rsaKey = k
default:
return ErrInvalidKey
}
// Create hasher
if !m.Hash.Available() {
return ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
return rsa.VerifyPSS(rsaKey, m.Hash, hasher.Sum(nil), sig, m.Options)
}
// Implements the Sign method from SigningMethod
// For this signing method, key must be an rsa.PrivateKey struct
func (m *SigningMethodRSAPSS) Sign(signingString string, key interface{}) (string, error) {
var rsaKey *rsa.PrivateKey
switch k := key.(type) {
case *rsa.PrivateKey:
rsaKey = k
default:
return "", ErrInvalidKeyType
}
// Create the hasher
if !m.Hash.Available() {
return "", ErrHashUnavailable
}
hasher := m.Hash.New()
hasher.Write([]byte(signingString))
// Sign the string and return the encoded bytes
if sigBytes, err := rsa.SignPSS(rand.Reader, rsaKey, m.Hash, hasher.Sum(nil), m.Options); err == nil {
return EncodeSegment(sigBytes), nil
} else {
return "", err
}
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/rsa_utils.go
================================================
package jwt
import (
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
)
var (
ErrKeyMustBePEMEncoded = errors.New("Invalid Key: Key must be PEM encoded PKCS1 or PKCS8 private key")
ErrNotRSAPrivateKey = errors.New("Key is not a valid RSA private key")
ErrNotRSAPublicKey = errors.New("Key is not a valid RSA public key")
)
// Parse PEM encoded PKCS1 or PKCS8 private key
func ParseRSAPrivateKeyFromPEM(key []byte) (*rsa.PrivateKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, ErrKeyMustBePEMEncoded
}
var parsedKey interface{}
if parsedKey, err = x509.ParsePKCS1PrivateKey(block.Bytes); err != nil {
if parsedKey, err = x509.ParsePKCS8PrivateKey(block.Bytes); err != nil {
return nil, err
}
}
var pkey *rsa.PrivateKey
var ok bool
if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
return nil, ErrNotRSAPrivateKey
}
return pkey, nil
}
// Parse PEM encoded PKCS1 or PKCS8 private key protected with password
func ParseRSAPrivateKeyFromPEMWithPassword(key []byte, password string) (*rsa.PrivateKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, ErrKeyMustBePEMEncoded
}
var parsedKey interface{}
var blockDecrypted []byte
if blockDecrypted, err = x509.DecryptPEMBlock(block, []byte(password)); err != nil {
return nil, err
}
if parsedKey, err = x509.ParsePKCS1PrivateKey(blockDecrypted); err != nil {
if parsedKey, err = x509.ParsePKCS8PrivateKey(blockDecrypted); err != nil {
return nil, err
}
}
var pkey *rsa.PrivateKey
var ok bool
if pkey, ok = parsedKey.(*rsa.PrivateKey); !ok {
return nil, ErrNotRSAPrivateKey
}
return pkey, nil
}
// Parse PEM encoded PKCS1 or PKCS8 public key
func ParseRSAPublicKeyFromPEM(key []byte) (*rsa.PublicKey, error) {
var err error
// Parse PEM block
var block *pem.Block
if block, _ = pem.Decode(key); block == nil {
return nil, ErrKeyMustBePEMEncoded
}
// Parse the key
var parsedKey interface{}
if parsedKey, err = x509.ParsePKIXPublicKey(block.Bytes); err != nil {
if cert, err := x509.ParseCertificate(block.Bytes); err == nil {
parsedKey = cert.PublicKey
} else {
return nil, err
}
}
var pkey *rsa.PublicKey
var ok bool
if pkey, ok = parsedKey.(*rsa.PublicKey); !ok {
return nil, ErrNotRSAPublicKey
}
return pkey, nil
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/signing_method.go
================================================
package jwt
import (
"sync"
)
var signingMethods = map[string]func() SigningMethod{}
var signingMethodLock = new(sync.RWMutex)
// Implement SigningMethod to add new methods for signing or verifying tokens.
type SigningMethod interface {
Verify(signingString, signature string, key interface{}) error // Returns nil if signature is valid
Sign(signingString string, key interface{}) (string, error) // Returns encoded signature or error
Alg() string // returns the alg identifier for this method (example: 'HS256')
}
// Register the "alg" name and a factory function for signing method.
// This is typically done during init() in the method's implementation
func RegisterSigningMethod(alg string, f func() SigningMethod) {
signingMethodLock.Lock()
defer signingMethodLock.Unlock()
signingMethods[alg] = f
}
// Get a signing method from an "alg" string
func GetSigningMethod(alg string) (method SigningMethod) {
signingMethodLock.RLock()
defer signingMethodLock.RUnlock()
if methodF, ok := signingMethods[alg]; ok {
method = methodF()
}
return
}
================================================
FILE: vendor/github.com/dgrijalva/jwt-go/token.go
================================================
package jwt
import (
"encoding/base64"
"encoding/json"
"strings"
"time"
)
// TimeFunc provides the current time when parsing token to validate "exp" claim (expiration time).
// You can override it to use another time value. This is useful for testing or if your
// server uses a different time zone than your tokens.
var TimeFunc = time.Now
// Parse methods use this callback function to supply
// the key for verification. The function receives the parsed,
// but unverified Token. This allows you to use properties in the
// Header of the token (such as `kid`) to identify which key to use.
type Keyfunc func(*Token) (interface{}, error)
// A JWT Token. Different fields will be used depending on whether you're
// creating or parsing/verifying a token.
type Token struct {
Raw string // The raw token. Populated when you Parse a token
Method SigningMethod // The signing method used or to be used
Header map[string]interface{} // The first segment of the token
Claims Claims // The second segment of the token
Signature string // The third segment of the token. Populated when you Parse a token
Valid bool // Is the token valid? Populated when you Parse/Verify a token
}
// Create a new Token. Takes a signing method
func New(method SigningMethod) *Token {
return NewWithClaims(method, MapClaims{})
}
func NewWithClaims(method SigningMethod, claims Claims) *Token {
return &Token{
Header: map[string]interface{}{
"typ": "JWT",
"alg": method.Alg(),
},
Claims: claims,
Method: method,
}
}
// Get the complete, signed token
func (t *Token) SignedString(key interface{}) (string, error) {
var sig, sstr string
var err error
if sstr, err = t.SigningString(); err != nil {
return "", err
}
if sig, err = t.Method.Sign(sstr, key); err != nil {
return "", err
}
return strings.Join([]string{sstr, sig}, "."), nil
}
// Generate the signing string. This is the
// most expensive part of the whole deal. Unless you
// need this for something special, just go straight for
// the SignedString.
func (t *Token) SigningString() (string, error) {
var err error
parts := make([]string, 2)
for i, _ := range parts {
var jsonValue []byte
if i == 0 {
if jsonValue, err = json.Marshal(t.Header); err != nil {
return "", err
}
} else {
if jsonValue, err = json.Marshal(t.Claims); err != nil {
return "", err
}
}
parts[i] = EncodeSegment(jsonValue)
}
return strings.Join(parts, "."), nil
}
// Parse, validate, and return a token.
// keyFunc will receive the parsed token and should return the key for validating.
// If everything is kosher, err will be nil
func Parse(tokenString string, keyFunc Keyfunc) (*Token, error) {
return new(Parser).Parse(tokenString, keyFunc)
}
func ParseWithClaims(tokenString string, claims Claims, keyFunc Keyfunc) (*Token, error) {
return new(Parser).ParseWithClaims(tokenString, claims, keyFunc)
}
// Encode JWT specific base64url encoding with padding stripped
func EncodeSegment(seg []byte) string {
return strings.TrimRight(base64.URLEncoding.EncodeToString(seg), "=")
}
// Decode JWT specific base64url encoding with padding stripped
func DecodeSegment(seg string) ([]byte, error) {
if l := len(seg) % 4; l > 0 {
seg += strings.Repeat("=", 4-l)
}
return base64.URLEncoding.DecodeString(seg)
}
================================================
FILE: vendor/github.com/dimchansky/utfbom/.gitignore
================================================
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
*.o
*.a
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.prof
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
# Gogland
.idea/
================================================
FILE: vendor/github.com/dimchansky/utfbom/.travis.yml
================================================
language: go
sudo: false
go:
- 1.10.x
- 1.11.x
- 1.12.x
- 1.13.x
- 1.14.x
- 1.15.x
cache:
directories:
- $HOME/.cache/go-build
- $HOME/gopath/pkg/mod
env:
global:
- GO111MODULE=on
before_install:
- go get github.com/mattn/goveralls
- go get golang.org/x/tools/cmd/cover
- go get golang.org/x/tools/cmd/goimports
- go get golang.org/x/lint/golint
script:
- gofiles=$(find ./ -name '*.go') && [ -z "$gofiles" ] || unformatted=$(goimports -l $gofiles) && [ -z "$unformatted" ] || (echo >&2 "Go files must be formatted with gofmt. Following files has problem:\n $unformatted" && false)
- golint ./... # This won't break the build, just show warnings
- $HOME/gopath/bin/goveralls -service=travis-ci
================================================
FILE: vendor/github.com/dimchansky/utfbom/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) 2018-2020, Dmitrij Koniajev (dimchansky@gmail.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: vendor/github.com/dimchansky/utfbom/README.md
================================================
# utfbom [](https://godoc.org/github.com/dimchansky/utfbom) [](https://opensource.org/licenses/Apache-2.0) [](https://travis-ci.org/dimchansky/utfbom) [](https://goreportcard.com/report/github.com/dimchansky/utfbom) [](https://coveralls.io/github/dimchansky/utfbom?branch=master)
The package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary. It can also return the encoding detected by the BOM.
## Installation
go get -u github.com/dimchansky/utfbom
## Example
```go
package main
import (
"bytes"
"fmt"
"io/ioutil"
"github.com/dimchansky/utfbom"
)
func main() {
trySkip([]byte("\xEF\xBB\xBFhello"))
trySkip([]byte("hello"))
}
func trySkip(byteData []byte) {
fmt.Println("Input:", byteData)
// just skip BOM
output, err := ioutil.ReadAll(utfbom.SkipOnly(bytes.NewReader(byteData)))
if err != nil {
fmt.Println(err)
return
}
fmt.Println("ReadAll with BOM skipping", output)
// skip BOM and detect encoding
sr, enc := utfbom.Skip(bytes.NewReader(byteData))
fmt.Printf("Detected encoding: %s\n", enc)
output, err = ioutil.ReadAll(sr)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("ReadAll with BOM detection and skipping", output)
fmt.Println()
}
```
Output:
```
$ go run main.go
Input: [239 187 191 104 101 108 108 111]
ReadAll with BOM skipping [104 101 108 108 111]
Detected encoding: UTF8
ReadAll with BOM detection and skipping [104 101 108 108 111]
Input: [104 101 108 108 111]
ReadAll with BOM skipping [104 101 108 108 111]
Detected encoding: Unknown
ReadAll with BOM detection and skipping [104 101 108 108 111]
```
================================================
FILE: vendor/github.com/dimchansky/utfbom/utfbom.go
================================================
// Package utfbom implements the detection of the BOM (Unicode Byte Order Mark) and removing as necessary.
// It wraps an io.Reader object, creating another object (Reader) that also implements the io.Reader
// interface but provides automatic BOM checking and removing as necessary.
package utfbom
import (
"errors"
"io"
)
// Encoding is type alias for detected UTF encoding.
type Encoding int
// Constants to identify detected UTF encodings.
const (
// Unknown encoding, returned when no BOM was detected
Unknown Encoding = iota
// UTF8, BOM bytes: EF BB BF
UTF8
// UTF-16, big-endian, BOM bytes: FE FF
UTF16BigEndian
// UTF-16, little-endian, BOM bytes: FF FE
UTF16LittleEndian
// UTF-32, big-endian, BOM bytes: 00 00 FE FF
UTF32BigEndian
// UTF-32, little-endian, BOM bytes: FF FE 00 00
UTF32LittleEndian
)
// String returns a user-friendly string representation of the encoding. Satisfies fmt.Stringer interface.
func (e Encoding) String() string {
switch e {
case UTF8:
return "UTF8"
case UTF16BigEndian:
return "UTF16BigEndian"
case UTF16LittleEndian:
return "UTF16LittleEndian"
case UTF32BigEndian:
return "UTF32BigEndian"
case UTF32LittleEndian:
return "UTF32LittleEndian"
default:
return "Unknown"
}
}
const maxConsecutiveEmptyReads = 100
// Skip creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary.
// It also returns the encoding detected by the BOM.
// If the detected encoding is not needed, you can call the SkipOnly function.
func Skip(rd io.Reader) (*Reader, Encoding) {
// Is it already a Reader?
b, ok := rd.(*Reader)
if ok {
return b, Unknown
}
enc, left, err := detectUtf(rd)
return &Reader{
rd: rd,
buf: left,
err: err,
}, enc
}
// SkipOnly creates Reader which automatically detects BOM (Unicode Byte Order Mark) and removes it as necessary.
func SkipOnly(rd io.Reader) *Reader {
r, _ := Skip(rd)
return r
}
// Reader implements automatic BOM (Unicode Byte Order Mark) checking and
// removing as necessary for an io.Reader object.
type Reader struct {
rd io.Reader // reader provided by the client
buf []byte // buffered data
err error // last error
}
// Read is an implementation of io.Reader interface.
// The bytes are taken from the underlying Reader, but it checks for BOMs, removing them as necessary.
func (r *Reader) Read(p []byte) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
if r.buf == nil {
if r.err != nil {
return 0, r.readErr()
}
return r.rd.Read(p)
}
// copy as much as we can
n = copy(p, r.buf)
r.buf = nilIfEmpty(r.buf[n:])
return n, nil
}
func (r *Reader) readErr() error {
err := r.err
r.err = nil
return err
}
var errNegativeRead = errors.New("utfbom: reader returned negative count from Read")
func detectUtf(rd io.Reader) (enc Encoding, buf []byte, err error) {
buf, err = readBOM(rd)
if len(buf) >= 4 {
if isUTF32BigEndianBOM4(buf) {
return UTF32BigEndian, nilIfEmpty(buf[4:]), err
}
if isUTF32LittleEndianBOM4(buf) {
return UTF32LittleEndian, nilIfEmpty(buf[4:]), err
}
}
if len(buf) > 2 && isUTF8BOM3(buf) {
return UTF8, nilIfEmpty(buf[3:]), err
}
if (err != nil && err != io.EOF) || (len(buf) < 2) {
return Unknown, nilIfEmpty(buf), err
}
if isUTF16BigEndianBOM2(buf) {
return UTF16BigEndian, nilIfEmpty(buf[2:]), err
}
if isUTF16LittleEndianBOM2(buf) {
return UTF16LittleEndian, nilIfEmpty(buf[2:]), err
}
return Unknown, nilIfEmpty(buf), err
}
func readBOM(rd io.Reader) (buf []byte, err error) {
const maxBOMSize = 4
var bom [maxBOMSize]byte // used to read BOM
// read as many bytes as possible
for nEmpty, n := 0, 0; err == nil && len(buf) < maxBOMSize; buf = bom[:len(buf)+n] {
if n, err = rd.Read(bom[len(buf):]); n < 0 {
panic(errNegativeRead)
}
if n > 0 {
nEmpty = 0
} else {
nEmpty++
if nEmpty >= maxConsecutiveEmptyReads {
err = io.ErrNoProgress
}
}
}
return
}
func isUTF32BigEndianBOM4(buf []byte) bool {
return buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0xFE && buf[3] == 0xFF
}
func isUTF32LittleEndianBOM4(buf []byte) bool {
return buf[0] == 0xFF && buf[1] == 0xFE && buf[2] == 0x00 && buf[3] == 0x00
}
func isUTF8BOM3(buf []byte) bool {
return buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF
}
func isUTF16BigEndianBOM2(buf []byte) bool {
return buf[0] == 0xFE && buf[1] == 0xFF
}
func isUTF16LittleEndianBOM2(buf []byte) bool {
return buf[0] == 0xFF && buf[1] == 0xFE
}
func nilIfEmpty(buf []byte) (res []byte) {
if len(buf) > 0 {
res = buf
}
return
}
================================================
FILE: vendor/github.com/dsnet/compress/.travis.yml
================================================
sudo: false
language: go
before_install:
- curl -L https://github.com/google/brotli/archive/v1.0.2.tar.gz | tar -zxv
- (cd brotli-1.0.2 && mkdir out && cd out && ../configure-cmake && make && sudo make install)
- rm -rf brotli-1.0.2
- curl -L https://github.com/facebook/zstd/archive/v1.3.2.tar.gz | tar -zxv
- (cd zstd-1.3.2 && sudo make install)
- rm -rf zstd-1.3.2
- sudo ldconfig
- mkdir /tmp/go1.12
- curl -L -s https://dl.google.com/go/go1.12.linux-amd64.tar.gz | tar -zxf - -C /tmp/go1.12 --strip-components 1
- unset GOROOT
- (GO111MODULE=on /tmp/go1.12/bin/go mod vendor)
- (cd /tmp && GO111MODULE=on /tmp/go1.12/bin/go get golang.org/x/lint/golint@8f45f776aaf18cebc8d65861cc70c33c60471952)
- (cd /tmp && GO111MODULE=on /tmp/go1.12/bin/go get honnef.co/go/tools/cmd/staticcheck@2019.1)
matrix:
include:
- go: 1.9.x
script:
- go test -v -race ./...
- go: 1.10.x
script:
- go test -v -race ./...
- go: 1.11.x
script:
- go test -v -race ./...
- go: 1.12.x
script:
- ./ztest.sh
- go: master
script:
- go test -v -race ./...
allow_failures:
- go: master
fast_finish: true
================================================
FILE: vendor/github.com/dsnet/compress/LICENSE.md
================================================
Copyright © 2015, Joe Tsai and The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the copyright holder nor the names of its contributors may be used to
endorse or promote products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/dsnet/compress/README.md
================================================
# Collection of compression libraries for Go #
[](https://godoc.org/github.com/dsnet/compress)
[](https://travis-ci.org/dsnet/compress)
[](https://goreportcard.com/report/github.com/dsnet/compress)
## Introduction ##
**NOTE: This library is in active development. As such, there are no guarantees about the stability of the API. The author reserves the right to arbitrarily break the API for any reason.**
This repository hosts a collection of compression related libraries. The goal of this project is to provide pure Go implementations for popular compression algorithms beyond what the Go standard library provides. The goals for these packages are as follows:
* Maintainable: That the code remains well documented, well tested, readable, easy to maintain, and easy to verify that it conforms to the specification for the format being implemented.
* Performant: To be able to compress and decompress within at least 80% of the rates that the C implementations are able to achieve.
* Flexible: That the code provides low-level and fine granularity control over the compression streams similar to what the C APIs would provide.
Of these three, the first objective is often at odds with the other two objectives and provides interesting challenges. Higher performance can often be achieved by muddling abstraction layers or using non-intuitive low-level primitives. Also, more features and functionality, while useful in some situations, often complicates the API. Thus, this package will attempt to satisfy all the goals, but will defer to favoring maintainability when the performance or flexibility benefits are not significant enough.
## Library Status ##
For the packages available, only some features are currently implemented:
| Package | Reader | Writer |
| ------- | :----: | :----: |
| brotli | :white_check_mark: | |
| bzip2 | :white_check_mark: | :white_check_mark: |
| flate | :white_check_mark: | |
| xflate | :white_check_mark: | :white_check_mark: |
This library is in active development. As such, there are no guarantees about the stability of the API. The author reserves the right to arbitrarily break the API for any reason. When the library becomes more mature, it is planned to eventually conform to some strict versioning scheme like [Semantic Versioning](http://semver.org/).
However, in the meanwhile, this library does provide some basic API guarantees. For the types defined below, the method signatures are guaranteed to not change. Note that the author still reserves the right to change the fields within each ```Reader``` and ```Writer``` structs.
```go
type ReaderConfig struct { ... }
type Reader struct { ... }
func NewReader(io.Reader, *ReaderConfig) (*Reader, error) { ... }
func (*Reader) Read([]byte) (int, error) { ... }
func (*Reader) Close() error { ... }
type WriterConfig struct { ... }
type Writer struct { ... }
func NewWriter(io.Writer, *WriterConfig) (*Writer, error) { ... }
func (*Writer) Write([]byte) (int, error) { ... }
func (*Writer) Close() error { ... }
```
To see what work still remains, see the [Task List](https://github.com/dsnet/compress/wiki/Task-List).
## Performance ##
See [Performance Metrics](https://github.com/dsnet/compress/wiki/Performance-Metrics).
## Frequently Asked Questions ##
See [Frequently Asked Questions](https://github.com/dsnet/compress/wiki/Frequently-Asked-Questions).
## Installation ##
Run the command:
```go get -u github.com/dsnet/compress```
This library requires `Go1.9` or higher in order to build.
## Packages ##
| Package | Description |
| :------ | :---------- |
| [brotli](http://godoc.org/github.com/dsnet/compress/brotli) | Package brotli implements the Brotli format, described in RFC 7932. |
| [bzip2](http://godoc.org/github.com/dsnet/compress/bzip2) | Package bzip2 implements the BZip2 compressed data format. |
| [flate](http://godoc.org/github.com/dsnet/compress/flate) | Package flate implements the DEFLATE format, described in RFC 1951. |
| [xflate](http://godoc.org/github.com/dsnet/compress/xflate) | Package xflate implements the XFLATE format, an random-access extension to DEFLATE. |
================================================
FILE: vendor/github.com/dsnet/compress/api.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Package compress is a collection of compression libraries.
package compress
import (
"bufio"
"io"
"github.com/dsnet/compress/internal/errors"
)
// The Error interface identifies all compression related errors.
type Error interface {
error
CompressError()
// IsDeprecated reports the use of a deprecated and unsupported feature.
IsDeprecated() bool
// IsCorrupted reports whether the input stream was corrupted.
IsCorrupted() bool
}
var _ Error = errors.Error{}
// ByteReader is an interface accepted by all decompression Readers.
// It guarantees that the decompressor never reads more data than is necessary
// from the underlying io.Reader.
type ByteReader interface {
io.Reader
io.ByteReader
}
var _ ByteReader = (*bufio.Reader)(nil)
// BufferedReader is an interface accepted by all decompression Readers.
// It guarantees that the decompressor never reads more data than is necessary
// from the underlying io.Reader. Since BufferedReader allows a decompressor
// to peek at bytes further along in the stream without advancing the read
// pointer, decompression can experience a significant performance gain when
// provided a reader that satisfies this interface. Thus, a decompressor will
// prefer this interface over ByteReader for performance reasons.
//
// The bufio.Reader satisfies this interface.
type BufferedReader interface {
io.Reader
// Buffered returns the number of bytes currently buffered.
//
// This value becomes invalid following the next Read/Discard operation.
Buffered() int
// Peek returns the next n bytes without advancing the reader.
//
// If Peek returns fewer than n bytes, it also returns an error explaining
// why the peek is short. Peek must support peeking of at least 8 bytes.
// If 0 <= n <= Buffered(), Peek is guaranteed to succeed without reading
// from the underlying io.Reader.
//
// This result becomes invalid following the next Read/Discard operation.
Peek(n int) ([]byte, error)
// Discard skips the next n bytes, returning the number of bytes discarded.
//
// If Discard skips fewer than n bytes, it also returns an error.
// If 0 <= n <= Buffered(), Discard is guaranteed to succeed without reading
// from the underlying io.Reader.
Discard(n int) (int, error)
}
var _ BufferedReader = (*bufio.Reader)(nil)
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/bwt.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import "github.com/dsnet/compress/bzip2/internal/sais"
// The Burrows-Wheeler Transform implementation used here is based on the
// Suffix Array by Induced Sorting (SA-IS) methodology by Nong, Zhang, and Chan.
// This implementation uses the sais algorithm originally written by Yuta Mori.
//
// The SA-IS algorithm runs in O(n) and outputs a Suffix Array. There is a
// mathematical relationship between Suffix Arrays and the Burrows-Wheeler
// Transform, such that a SA can be converted to a BWT in O(n) time.
//
// References:
// http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-RR-124.pdf
// https://github.com/cscott/compressjs/blob/master/lib/BWT.js
// https://www.quora.com/How-can-I-optimize-burrows-wheeler-transform-and-inverse-transform-to-work-in-O-n-time-O-n-space
type burrowsWheelerTransform struct {
buf []byte
sa []int
perm []uint32
}
func (bwt *burrowsWheelerTransform) Encode(buf []byte) (ptr int) {
if len(buf) == 0 {
return -1
}
// TODO(dsnet): Find a way to avoid the duplicate input string method.
// We only need to do this because suffix arrays (by definition) only
// operate non-wrapped suffixes of a string. On the other hand,
// the BWT specifically used in bzip2 operate on a strings that wrap-around
// when being sorted.
// Step 1: Concatenate the input string to itself so that we can use the
// suffix array algorithm for bzip2's variant of BWT.
n := len(buf)
bwt.buf = append(append(bwt.buf[:0], buf...), buf...)
if cap(bwt.sa) < 2*n {
bwt.sa = make([]int, 2*n)
}
t := bwt.buf[:2*n]
sa := bwt.sa[:2*n]
// Step 2: Compute the suffix array (SA). The input string, t, will not be
// modified, while the results will be written to the output, sa.
sais.ComputeSA(t, sa)
// Step 3: Convert the SA to a BWT. Since ComputeSA does not mutate the
// input, we have two copies of the input; in buf and buf2. Thus, we write
// the transformation to buf, while using buf2.
var j int
buf2 := t[n:]
for _, i := range sa {
if i < n {
if i == 0 {
ptr = j
i = n
}
buf[j] = buf2[i-1]
j++
}
}
return ptr
}
func (bwt *burrowsWheelerTransform) Decode(buf []byte, ptr int) {
if len(buf) == 0 {
return
}
// Step 1: Compute cumm, where cumm[ch] reports the total number of
// characters that precede the character ch in the alphabet.
var cumm [256]int
for _, v := range buf {
cumm[v]++
}
var sum int
for i, v := range cumm {
cumm[i] = sum
sum += v
}
// Step 2: Compute perm, where perm[ptr] contains a pointer to the next
// byte in buf and the next pointer in perm itself.
if cap(bwt.perm) < len(buf) {
bwt.perm = make([]uint32, len(buf))
}
perm := bwt.perm[:len(buf)]
for i, b := range buf {
perm[cumm[b]] = uint32(i)
cumm[b]++
}
// Step 3: Follow each pointer in perm to the next byte, starting with the
// origin pointer.
if cap(bwt.buf) < len(buf) {
bwt.buf = make([]byte, len(buf))
}
buf2 := bwt.buf[:len(buf)]
i := perm[ptr]
for j := range buf2 {
buf2[j] = buf[i]
i = perm[i]
}
copy(buf, buf2)
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/common.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Package bzip2 implements the BZip2 compressed data format.
//
// Canonical C implementation:
// http://bzip.org
//
// Unofficial format specification:
// https://github.com/dsnet/compress/blob/master/doc/bzip2-format.pdf
package bzip2
import (
"fmt"
"hash/crc32"
"github.com/dsnet/compress/internal"
"github.com/dsnet/compress/internal/errors"
)
// There does not exist a formal specification of the BZip2 format. As such,
// much of this work is derived by either reverse engineering the original C
// source code or using secondary sources.
//
// Significant amounts of fuzz testing is done to ensure that outputs from
// this package is properly decoded by the C library. Furthermore, we test that
// both this package and the C library agree about what inputs are invalid.
//
// Compression stack:
// Run-length encoding 1 (RLE1)
// Burrows-Wheeler transform (BWT)
// Move-to-front transform (MTF)
// Run-length encoding 2 (RLE2)
// Prefix encoding (PE)
//
// References:
// http://bzip.org/
// https://en.wikipedia.org/wiki/Bzip2
// https://code.google.com/p/jbzip2/
const (
BestSpeed = 1
BestCompression = 9
DefaultCompression = 6
)
const (
hdrMagic = 0x425a // Hex of "BZ"
blkMagic = 0x314159265359 // BCD of PI
endMagic = 0x177245385090 // BCD of sqrt(PI)
blockSize = 100000
)
func errorf(c int, f string, a ...interface{}) error {
return errors.Error{Code: c, Pkg: "bzip2", Msg: fmt.Sprintf(f, a...)}
}
func panicf(c int, f string, a ...interface{}) {
errors.Panic(errorf(c, f, a...))
}
// errWrap converts a lower-level errors.Error to be one from this package.
// The replaceCode passed in will be used to replace the code for any errors
// with the errors.Invalid code.
//
// For the Reader, set this to errors.Corrupted.
// For the Writer, set this to errors.Internal.
func errWrap(err error, replaceCode int) error {
if cerr, ok := err.(errors.Error); ok {
if errors.IsInvalid(cerr) {
cerr.Code = replaceCode
}
err = errorf(cerr.Code, "%s", cerr.Msg)
}
return err
}
var errClosed = errorf(errors.Closed, "")
// crc computes the CRC-32 used by BZip2.
//
// The CRC-32 computation in bzip2 treats bytes as having bits in big-endian
// order. That is, the MSB is read before the LSB. Thus, we can use the
// standard library version of CRC-32 IEEE with some minor adjustments.
//
// The byte array is used as an intermediate buffer to swap the bits of every
// byte of the input.
type crc struct {
val uint32
buf [256]byte
}
// update computes the CRC-32 of appending buf to c.
func (c *crc) update(buf []byte) {
cval := internal.ReverseUint32(c.val)
for len(buf) > 0 {
n := len(buf)
if n > len(c.buf) {
n = len(c.buf)
}
for i, b := range buf[:n] {
c.buf[i] = internal.ReverseLUT[b]
}
cval = crc32.Update(cval, crc32.IEEETable, c.buf[:n])
buf = buf[n:]
}
c.val = internal.ReverseUint32(cval)
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/fuzz_off.go
================================================
// Copyright 2016, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build !gofuzz
// This file exists to suppress fuzzing details from release builds.
package bzip2
type fuzzReader struct{}
func (*fuzzReader) updateChecksum(int64, uint32) {}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/fuzz_on.go
================================================
// Copyright 2016, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build gofuzz
// This file exists to export internal implementation details for fuzz testing.
package bzip2
func ForwardBWT(buf []byte) (ptr int) {
var bwt burrowsWheelerTransform
return bwt.Encode(buf)
}
func ReverseBWT(buf []byte, ptr int) {
var bwt burrowsWheelerTransform
bwt.Decode(buf, ptr)
}
type fuzzReader struct {
Checksums Checksums
}
// updateChecksum updates Checksums.
//
// If a valid pos is provided, it appends the (pos, val) pair to the slice.
// Otherwise, it will update the last record with the new value.
func (fr *fuzzReader) updateChecksum(pos int64, val uint32) {
if pos >= 0 {
fr.Checksums = append(fr.Checksums, Checksum{pos, val})
} else {
fr.Checksums[len(fr.Checksums)-1].Value = val
}
}
type Checksum struct {
Offset int64 // Bit offset of the checksum
Value uint32 // Checksum value
}
type Checksums []Checksum
// Apply overwrites all checksum fields in d with the ones in cs.
func (cs Checksums) Apply(d []byte) []byte {
d = append([]byte(nil), d...)
for _, c := range cs {
setU32(d, c.Offset, c.Value)
}
return d
}
func setU32(d []byte, pos int64, val uint32) {
for i := uint(0); i < 32; i++ {
bpos := uint64(pos) + uint64(i)
d[bpos/8] &= ^byte(1 << (7 - bpos%8))
d[bpos/8] |= byte(val>>(31-i)) << (7 - bpos%8)
}
}
// Verify checks that all checksum fields in d matches those in cs.
func (cs Checksums) Verify(d []byte) bool {
for _, c := range cs {
if getU32(d, c.Offset) != c.Value {
return false
}
}
return true
}
func getU32(d []byte, pos int64) (val uint32) {
for i := uint(0); i < 32; i++ {
bpos := uint64(pos) + uint64(i)
val |= (uint32(d[bpos/8] >> (7 - bpos%8))) << (31 - i)
}
return val
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/internal/sais/common.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Package sais implements a linear time suffix array algorithm.
package sais
//go:generate go run sais_gen.go byte sais_byte.go
//go:generate go run sais_gen.go int sais_int.go
// This package ports the C sais implementation by Yuta Mori. The ports are
// located in sais_byte.go and sais_int.go, which are identical to each other
// except for the types. Since Go does not support generics, we use generators to
// create the two files.
//
// References:
// https://sites.google.com/site/yuta256/sais
// https://www.researchgate.net/publication/221313676_Linear_Time_Suffix_Array_Construction_Using_D-Critical_Substrings
// https://www.researchgate.net/publication/224176324_Two_Efficient_Algorithms_for_Linear_Time_Suffix_Array_Construction
// ComputeSA computes the suffix array of t and places the result in sa.
// Both t and sa must be the same length.
func ComputeSA(t []byte, sa []int) {
if len(sa) != len(t) {
panic("mismatching sizes")
}
computeSA_byte(t, sa, 0, len(t), 256)
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/internal/sais/sais_byte.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Code generated by sais_gen.go. DO NOT EDIT.
// ====================================================
// Copyright (c) 2008-2010 Yuta Mori All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// ====================================================
package sais
func getCounts_byte(T []byte, C []int, n, k int) {
var i int
for i = 0; i < k; i++ {
C[i] = 0
}
for i = 0; i < n; i++ {
C[T[i]]++
}
}
func getBuckets_byte(C, B []int, k int, end bool) {
var i, sum int
if end {
for i = 0; i < k; i++ {
sum += C[i]
B[i] = sum
}
} else {
for i = 0; i < k; i++ {
sum += C[i]
B[i] = sum - C[i]
}
}
}
func sortLMS1_byte(T []byte, SA, C, B []int, n, k int) {
var b, i, j int
var c0, c1 int
// Compute SAl.
if &C[0] == &B[0] {
getCounts_byte(T, C, n, k)
}
getBuckets_byte(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
j--
if int(T[j]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i = 0; i < n; i++ {
if j = SA[i]; j > 0 {
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
if int(T[j]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
SA[i] = 0
} else if j < 0 {
SA[i] = ^j
}
}
// Compute SAs.
if &C[0] == &B[0] {
getCounts_byte(T, C, n, k)
}
getBuckets_byte(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i = n - 1; i >= 0; i-- {
if j = SA[i]; j > 0 {
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
b--
if int(T[j]) > c1 {
SA[b] = ^(j + 1)
} else {
SA[b] = j
}
SA[i] = 0
}
}
}
func postProcLMS1_byte(T []byte, SA []int, n, m int) int {
var i, j, p, q, plen, qlen, name int
var c0, c1 int
var diff bool
// Compact all the sorted substrings into the first m items of SA.
// 2*m must be not larger than n (provable).
for i = 0; SA[i] < 0; i++ {
SA[i] = ^SA[i]
}
if i < m {
for j, i = i, i+1; ; i++ {
if p = SA[i]; p < 0 {
SA[j] = ^p
j++
SA[i] = 0
if j == m {
break
}
}
}
}
// Store the length of all substrings.
i = n - 1
j = n - 1
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
SA[m+((i+1)>>1)] = j - i
j = i + 1
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
// Find the lexicographic names of all substrings.
name = 0
qlen = 0
for i, q = 0, n; i < m; i++ {
p = SA[i]
plen = SA[m+(p>>1)]
diff = true
if (plen == qlen) && ((q + plen) < n) {
for j = 0; (j < plen) && (T[p+j] == T[q+j]); j++ {
}
if j == plen {
diff = false
}
}
if diff {
name++
q = p
qlen = plen
}
SA[m+(p>>1)] = name
}
return name
}
func sortLMS2_byte(T []byte, SA, C, B, D []int, n, k int) {
var b, i, j, t, d int
var c0, c1 int
// Compute SAl.
getBuckets_byte(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
j--
if int(T[j]) < c1 {
t = 1
} else {
t = 0
}
j += n
if t&1 > 0 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i, d = 0, 0; i < n; i++ {
if j = SA[i]; j > 0 {
if n <= j {
d += 1
j -= n
}
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
t = int(c0) << 1
if int(T[j]) < c1 {
t |= 1
}
if D[t] != d {
j += n
D[t] = d
}
if t&1 > 0 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
SA[i] = 0
} else if j < 0 {
SA[i] = ^j
}
}
for i = n - 1; 0 <= i; i-- {
if SA[i] > 0 {
if SA[i] < n {
SA[i] += n
for j = i - 1; SA[j] < n; j-- {
}
SA[j] -= n
i = j
}
}
}
// Compute SAs.
getBuckets_byte(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i, d = n-1, d+1; i >= 0; i-- {
if j = SA[i]; j > 0 {
if n <= j {
d += 1
j -= n
}
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
t = int(c0) << 1
if int(T[j]) > c1 {
t |= 1
}
if D[t] != d {
j += n
D[t] = d
}
b--
if t&1 > 0 {
SA[b] = ^(j + 1)
} else {
SA[b] = j
}
SA[i] = 0
}
}
}
func postProcLMS2_byte(SA []int, n, m int) int {
var i, j, d, name int
// Compact all the sorted LMS substrings into the first m items of SA.
name = 0
for i = 0; SA[i] < 0; i++ {
j = ^SA[i]
if n <= j {
name += 1
}
SA[i] = j
}
if i < m {
for d, i = i, i+1; ; i++ {
if j = SA[i]; j < 0 {
j = ^j
if n <= j {
name += 1
}
SA[d] = j
d++
SA[i] = 0
if d == m {
break
}
}
}
}
if name < m {
// Store the lexicographic names.
for i, d = m-1, name+1; 0 <= i; i-- {
if j = SA[i]; n <= j {
j -= n
d--
}
SA[m+(j>>1)] = d
}
} else {
// Unset flags.
for i = 0; i < m; i++ {
if j = SA[i]; n <= j {
j -= n
SA[i] = j
}
}
}
return name
}
func induceSA_byte(T []byte, SA, C, B []int, n, k int) {
var b, i, j int
var c0, c1 int
// Compute SAl.
if &C[0] == &B[0] {
getCounts_byte(T, C, n, k)
}
getBuckets_byte(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
if j > 0 && int(T[j-1]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i = 0; i < n; i++ {
j = SA[i]
SA[i] = ^j
if j > 0 {
j--
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
if j > 0 && int(T[j-1]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
}
}
// Compute SAs.
if &C[0] == &B[0] {
getCounts_byte(T, C, n, k)
}
getBuckets_byte(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i = n - 1; i >= 0; i-- {
if j = SA[i]; j > 0 {
j--
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
b--
if (j == 0) || (int(T[j-1]) > c1) {
SA[b] = ^j
} else {
SA[b] = j
}
} else {
SA[i] = ^j
}
}
}
func computeSA_byte(T []byte, SA []int, fs, n, k int) {
const (
minBucketSize = 512
sortLMS2Limit = 0x3fffffff
)
var C, B, D, RA []int
var bo int // Offset of B relative to SA
var b, i, j, m, p, q, name, newfs int
var c0, c1 int
var flags uint
if k <= minBucketSize {
C = make([]int, k)
if k <= fs {
bo = n + fs - k
B = SA[bo:]
flags = 1
} else {
B = make([]int, k)
flags = 3
}
} else if k <= fs {
C = SA[n+fs-k:]
if k <= fs-k {
bo = n + fs - 2*k
B = SA[bo:]
flags = 0
} else if k <= 4*minBucketSize {
B = make([]int, k)
flags = 2
} else {
B = C
flags = 8
}
} else {
C = make([]int, k)
B = C
flags = 4 | 8
}
if n <= sortLMS2Limit && 2 <= (n/k) {
if flags&1 > 0 {
if 2*k <= fs-k {
flags |= 32
} else {
flags |= 16
}
} else if flags == 0 && 2*k <= (fs-2*k) {
flags |= 32
}
}
// Stage 1: Reduce the problem by at least 1/2.
// Sort all the LMS-substrings.
getCounts_byte(T, C, n, k)
getBuckets_byte(C, B, k, true) // Find ends of buckets
for i = 0; i < n; i++ {
SA[i] = 0
}
b = -1
i = n - 1
j = n
m = 0
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
if b >= 0 {
SA[b] = j
}
B[c1]--
b = B[c1]
j = i
m++
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
if m > 1 {
if flags&(16|32) > 0 {
if flags&16 > 0 {
D = make([]int, 2*k)
} else {
D = SA[bo-2*k:]
}
B[T[j+1]]++
for i, j = 0, 0; i < k; i++ {
j += C[i]
if B[i] != j {
SA[B[i]] += n
}
D[i] = 0
D[i+k] = 0
}
sortLMS2_byte(T, SA, C, B, D, n, k)
name = postProcLMS2_byte(SA, n, m)
} else {
sortLMS1_byte(T, SA, C, B, n, k)
name = postProcLMS1_byte(T, SA, n, m)
}
} else if m == 1 {
SA[b] = j + 1
name = 1
} else {
name = 0
}
// Stage 2: Solve the reduced problem.
// Recurse if names are not yet unique.
if name < m {
newfs = n + fs - 2*m
if flags&(1|4|8) == 0 {
if k+name <= newfs {
newfs -= k
} else {
flags |= 8
}
}
RA = SA[m+newfs:]
for i, j = m+(n>>1)-1, m-1; m <= i; i-- {
if SA[i] != 0 {
RA[j] = SA[i] - 1
j--
}
}
computeSA_int(RA, SA, newfs, m, name)
i = n - 1
j = m - 1
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
RA[j] = i + 1
j--
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
for i = 0; i < m; i++ {
SA[i] = RA[SA[i]]
}
if flags&4 > 0 {
B = make([]int, k)
C = B
}
if flags&2 > 0 {
B = make([]int, k)
}
}
// Stage 3: Induce the result for the original problem.
if flags&8 > 0 {
getCounts_byte(T, C, n, k)
}
// Put all left-most S characters into their buckets.
if m > 1 {
getBuckets_byte(C, B, k, true) // Find ends of buckets
i = m - 1
j = n
p = SA[m-1]
c1 = int(T[p])
for {
c0 = c1
q = B[c0]
for q < j {
j--
SA[j] = 0
}
for {
j--
SA[j] = p
if i--; i < 0 {
break
}
p = SA[i]
if c1 = int(T[p]); c1 != c0 {
break
}
}
if i < 0 {
break
}
}
for j > 0 {
j--
SA[j] = 0
}
}
induceSA_byte(T, SA, C, B, n, k)
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/internal/sais/sais_int.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Code generated by sais_gen.go. DO NOT EDIT.
// ====================================================
// Copyright (c) 2008-2010 Yuta Mori All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// ====================================================
package sais
func getCounts_int(T []int, C []int, n, k int) {
var i int
for i = 0; i < k; i++ {
C[i] = 0
}
for i = 0; i < n; i++ {
C[T[i]]++
}
}
func getBuckets_int(C, B []int, k int, end bool) {
var i, sum int
if end {
for i = 0; i < k; i++ {
sum += C[i]
B[i] = sum
}
} else {
for i = 0; i < k; i++ {
sum += C[i]
B[i] = sum - C[i]
}
}
}
func sortLMS1_int(T []int, SA, C, B []int, n, k int) {
var b, i, j int
var c0, c1 int
// Compute SAl.
if &C[0] == &B[0] {
getCounts_int(T, C, n, k)
}
getBuckets_int(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
j--
if int(T[j]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i = 0; i < n; i++ {
if j = SA[i]; j > 0 {
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
if int(T[j]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
SA[i] = 0
} else if j < 0 {
SA[i] = ^j
}
}
// Compute SAs.
if &C[0] == &B[0] {
getCounts_int(T, C, n, k)
}
getBuckets_int(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i = n - 1; i >= 0; i-- {
if j = SA[i]; j > 0 {
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
b--
if int(T[j]) > c1 {
SA[b] = ^(j + 1)
} else {
SA[b] = j
}
SA[i] = 0
}
}
}
func postProcLMS1_int(T []int, SA []int, n, m int) int {
var i, j, p, q, plen, qlen, name int
var c0, c1 int
var diff bool
// Compact all the sorted substrings into the first m items of SA.
// 2*m must be not larger than n (provable).
for i = 0; SA[i] < 0; i++ {
SA[i] = ^SA[i]
}
if i < m {
for j, i = i, i+1; ; i++ {
if p = SA[i]; p < 0 {
SA[j] = ^p
j++
SA[i] = 0
if j == m {
break
}
}
}
}
// Store the length of all substrings.
i = n - 1
j = n - 1
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
SA[m+((i+1)>>1)] = j - i
j = i + 1
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
// Find the lexicographic names of all substrings.
name = 0
qlen = 0
for i, q = 0, n; i < m; i++ {
p = SA[i]
plen = SA[m+(p>>1)]
diff = true
if (plen == qlen) && ((q + plen) < n) {
for j = 0; (j < plen) && (T[p+j] == T[q+j]); j++ {
}
if j == plen {
diff = false
}
}
if diff {
name++
q = p
qlen = plen
}
SA[m+(p>>1)] = name
}
return name
}
func sortLMS2_int(T []int, SA, C, B, D []int, n, k int) {
var b, i, j, t, d int
var c0, c1 int
// Compute SAl.
getBuckets_int(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
j--
if int(T[j]) < c1 {
t = 1
} else {
t = 0
}
j += n
if t&1 > 0 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i, d = 0, 0; i < n; i++ {
if j = SA[i]; j > 0 {
if n <= j {
d += 1
j -= n
}
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
t = int(c0) << 1
if int(T[j]) < c1 {
t |= 1
}
if D[t] != d {
j += n
D[t] = d
}
if t&1 > 0 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
SA[i] = 0
} else if j < 0 {
SA[i] = ^j
}
}
for i = n - 1; 0 <= i; i-- {
if SA[i] > 0 {
if SA[i] < n {
SA[i] += n
for j = i - 1; SA[j] < n; j-- {
}
SA[j] -= n
i = j
}
}
}
// Compute SAs.
getBuckets_int(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i, d = n-1, d+1; i >= 0; i-- {
if j = SA[i]; j > 0 {
if n <= j {
d += 1
j -= n
}
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
j--
t = int(c0) << 1
if int(T[j]) > c1 {
t |= 1
}
if D[t] != d {
j += n
D[t] = d
}
b--
if t&1 > 0 {
SA[b] = ^(j + 1)
} else {
SA[b] = j
}
SA[i] = 0
}
}
}
func postProcLMS2_int(SA []int, n, m int) int {
var i, j, d, name int
// Compact all the sorted LMS substrings into the first m items of SA.
name = 0
for i = 0; SA[i] < 0; i++ {
j = ^SA[i]
if n <= j {
name += 1
}
SA[i] = j
}
if i < m {
for d, i = i, i+1; ; i++ {
if j = SA[i]; j < 0 {
j = ^j
if n <= j {
name += 1
}
SA[d] = j
d++
SA[i] = 0
if d == m {
break
}
}
}
}
if name < m {
// Store the lexicographic names.
for i, d = m-1, name+1; 0 <= i; i-- {
if j = SA[i]; n <= j {
j -= n
d--
}
SA[m+(j>>1)] = d
}
} else {
// Unset flags.
for i = 0; i < m; i++ {
if j = SA[i]; n <= j {
j -= n
SA[i] = j
}
}
}
return name
}
func induceSA_int(T []int, SA, C, B []int, n, k int) {
var b, i, j int
var c0, c1 int
// Compute SAl.
if &C[0] == &B[0] {
getCounts_int(T, C, n, k)
}
getBuckets_int(C, B, k, false) // Find starts of buckets
j = n - 1
c1 = int(T[j])
b = B[c1]
if j > 0 && int(T[j-1]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
for i = 0; i < n; i++ {
j = SA[i]
SA[i] = ^j
if j > 0 {
j--
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
if j > 0 && int(T[j-1]) < c1 {
SA[b] = ^j
} else {
SA[b] = j
}
b++
}
}
// Compute SAs.
if &C[0] == &B[0] {
getCounts_int(T, C, n, k)
}
getBuckets_int(C, B, k, true) // Find ends of buckets
c1 = 0
b = B[c1]
for i = n - 1; i >= 0; i-- {
if j = SA[i]; j > 0 {
j--
if c0 = int(T[j]); c0 != c1 {
B[c1] = b
c1 = c0
b = B[c1]
}
b--
if (j == 0) || (int(T[j-1]) > c1) {
SA[b] = ^j
} else {
SA[b] = j
}
} else {
SA[i] = ^j
}
}
}
func computeSA_int(T []int, SA []int, fs, n, k int) {
const (
minBucketSize = 512
sortLMS2Limit = 0x3fffffff
)
var C, B, D, RA []int
var bo int // Offset of B relative to SA
var b, i, j, m, p, q, name, newfs int
var c0, c1 int
var flags uint
if k <= minBucketSize {
C = make([]int, k)
if k <= fs {
bo = n + fs - k
B = SA[bo:]
flags = 1
} else {
B = make([]int, k)
flags = 3
}
} else if k <= fs {
C = SA[n+fs-k:]
if k <= fs-k {
bo = n + fs - 2*k
B = SA[bo:]
flags = 0
} else if k <= 4*minBucketSize {
B = make([]int, k)
flags = 2
} else {
B = C
flags = 8
}
} else {
C = make([]int, k)
B = C
flags = 4 | 8
}
if n <= sortLMS2Limit && 2 <= (n/k) {
if flags&1 > 0 {
if 2*k <= fs-k {
flags |= 32
} else {
flags |= 16
}
} else if flags == 0 && 2*k <= (fs-2*k) {
flags |= 32
}
}
// Stage 1: Reduce the problem by at least 1/2.
// Sort all the LMS-substrings.
getCounts_int(T, C, n, k)
getBuckets_int(C, B, k, true) // Find ends of buckets
for i = 0; i < n; i++ {
SA[i] = 0
}
b = -1
i = n - 1
j = n
m = 0
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
if b >= 0 {
SA[b] = j
}
B[c1]--
b = B[c1]
j = i
m++
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
if m > 1 {
if flags&(16|32) > 0 {
if flags&16 > 0 {
D = make([]int, 2*k)
} else {
D = SA[bo-2*k:]
}
B[T[j+1]]++
for i, j = 0, 0; i < k; i++ {
j += C[i]
if B[i] != j {
SA[B[i]] += n
}
D[i] = 0
D[i+k] = 0
}
sortLMS2_int(T, SA, C, B, D, n, k)
name = postProcLMS2_int(SA, n, m)
} else {
sortLMS1_int(T, SA, C, B, n, k)
name = postProcLMS1_int(T, SA, n, m)
}
} else if m == 1 {
SA[b] = j + 1
name = 1
} else {
name = 0
}
// Stage 2: Solve the reduced problem.
// Recurse if names are not yet unique.
if name < m {
newfs = n + fs - 2*m
if flags&(1|4|8) == 0 {
if k+name <= newfs {
newfs -= k
} else {
flags |= 8
}
}
RA = SA[m+newfs:]
for i, j = m+(n>>1)-1, m-1; m <= i; i-- {
if SA[i] != 0 {
RA[j] = SA[i] - 1
j--
}
}
computeSA_int(RA, SA, newfs, m, name)
i = n - 1
j = m - 1
c0 = int(T[n-1])
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
for i >= 0 {
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 > c1 {
break
}
}
if i >= 0 {
RA[j] = i + 1
j--
for {
c1 = c0
if i--; i < 0 {
break
}
if c0 = int(T[i]); c0 < c1 {
break
}
}
}
}
for i = 0; i < m; i++ {
SA[i] = RA[SA[i]]
}
if flags&4 > 0 {
B = make([]int, k)
C = B
}
if flags&2 > 0 {
B = make([]int, k)
}
}
// Stage 3: Induce the result for the original problem.
if flags&8 > 0 {
getCounts_int(T, C, n, k)
}
// Put all left-most S characters into their buckets.
if m > 1 {
getBuckets_int(C, B, k, true) // Find ends of buckets
i = m - 1
j = n
p = SA[m-1]
c1 = int(T[p])
for {
c0 = c1
q = B[c0]
for q < j {
j--
SA[j] = 0
}
for {
j--
SA[j] = p
if i--; i < 0 {
break
}
p = SA[i]
if c1 = int(T[p]); c1 != c0 {
break
}
}
if i < 0 {
break
}
}
for j > 0 {
j--
SA[j] = 0
}
}
induceSA_int(T, SA, C, B, n, k)
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/mtf_rle2.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import "github.com/dsnet/compress/internal/errors"
// moveToFront implements both the MTF and RLE stages of bzip2 at the same time.
// Any runs of zeros in the encoded output will be replaced by a sequence of
// RUNA and RUNB symbols are encode the length of the run.
//
// The RLE encoding used can actually be encoded to and decoded from using
// normal two's complement arithmetic. The methodology for doing so is below.
//
// Assuming the following:
// num: The value being encoded by RLE encoding.
// run: A sequence of RUNA and RUNB symbols represented as a binary integer,
// where RUNA is the 0 bit, RUNB is the 1 bit, and least-significant RUN
// symbols are at the least-significant bit positions.
// cnt: The number of RUNA and RUNB symbols.
//
// Then the RLE encoding used by bzip2 has this mathematical property:
// num+1 == (1< len(mtf.dictBuf) {
panicf(errors.Internal, "alphabet too large")
}
copy(mtf.dictBuf[:], dict)
mtf.dictLen = len(dict)
mtf.blkSize = blkSize
}
func (mtf *moveToFront) Encode(vals []byte) (syms []uint16) {
dict := mtf.dictBuf[:mtf.dictLen]
syms = mtf.syms[:0]
if len(vals) > mtf.blkSize {
panicf(errors.Internal, "exceeded block size")
}
var lastNum uint32
for _, val := range vals {
// Normal move-to-front transform.
var idx uint8 // Reverse lookup idx in dict
for di, dv := range dict {
if dv == val {
idx = uint8(di)
break
}
}
copy(dict[1:], dict[:idx])
dict[0] = val
// Run-length encoding augmentation.
if idx == 0 {
lastNum++
continue
}
if lastNum > 0 {
for rc := lastNum + 1; rc != 1; rc >>= 1 {
syms = append(syms, uint16(rc&1))
}
lastNum = 0
}
syms = append(syms, uint16(idx)+1)
}
if lastNum > 0 {
for rc := lastNum + 1; rc != 1; rc >>= 1 {
syms = append(syms, uint16(rc&1))
}
}
mtf.syms = syms
return syms
}
func (mtf *moveToFront) Decode(syms []uint16) (vals []byte) {
dict := mtf.dictBuf[:mtf.dictLen]
vals = mtf.vals[:0]
var lastCnt uint
var lastRun uint32
for _, sym := range syms {
// Run-length encoding augmentation.
if sym < 2 {
lastRun |= uint32(sym) << lastCnt
lastCnt++
continue
}
if lastCnt > 0 {
cnt := int((1< mtf.blkSize || lastCnt > 24 {
panicf(errors.Corrupted, "run-length decoding exceeded block size")
}
for i := cnt; i > 0; i-- {
vals = append(vals, dict[0])
}
lastCnt, lastRun = 0, 0
}
// Normal move-to-front transform.
val := dict[sym-1] // Forward lookup val in dict
copy(dict[1:], dict[:sym-1])
dict[0] = val
if len(vals) >= mtf.blkSize {
panicf(errors.Corrupted, "run-length decoding exceeded block size")
}
vals = append(vals, val)
}
if lastCnt > 0 {
cnt := int((1< mtf.blkSize || lastCnt > 24 {
panicf(errors.Corrupted, "run-length decoding exceeded block size")
}
for i := cnt; i > 0; i-- {
vals = append(vals, dict[0])
}
}
mtf.vals = vals
return vals
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/prefix.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import (
"io"
"github.com/dsnet/compress/internal"
"github.com/dsnet/compress/internal/errors"
"github.com/dsnet/compress/internal/prefix"
)
const (
minNumTrees = 2
maxNumTrees = 6
maxPrefixBits = 20 // Maximum bit-width of a prefix code
maxNumSyms = 256 + 2 // Maximum number of symbols in the alphabet
numBlockSyms = 50 // Number of bytes in a block
)
// encSel and decSel are used to handle the prefix encoding for tree selectors.
// The prefix encoding is as follows:
//
// Code TreeIdx
// 0 <=> 0
// 10 <=> 1
// 110 <=> 2
// 1110 <=> 3
// 11110 <=> 4
// 111110 <=> 5
// 111111 <=> 6 Invalid tree index, so should fail
//
var encSel, decSel = func() (e prefix.Encoder, d prefix.Decoder) {
var selCodes [maxNumTrees + 1]prefix.PrefixCode
for i := range selCodes {
selCodes[i] = prefix.PrefixCode{Sym: uint32(i), Len: uint32(i + 1)}
}
selCodes[maxNumTrees] = prefix.PrefixCode{Sym: maxNumTrees, Len: maxNumTrees}
prefix.GeneratePrefixes(selCodes[:])
e.Init(selCodes[:])
d.Init(selCodes[:])
return
}()
type prefixReader struct{ prefix.Reader }
func (pr *prefixReader) Init(r io.Reader) {
pr.Reader.Init(r, true)
}
func (pr *prefixReader) ReadBitsBE64(nb uint) uint64 {
if nb <= 32 {
v := uint32(pr.ReadBits(nb))
return uint64(internal.ReverseUint32N(v, nb))
}
v0 := internal.ReverseUint32(uint32(pr.ReadBits(32)))
v1 := internal.ReverseUint32(uint32(pr.ReadBits(nb - 32)))
v := uint64(v0)<<32 | uint64(v1)
return v >> (64 - nb)
}
func (pr *prefixReader) ReadPrefixCodes(codes []prefix.PrefixCodes, trees []prefix.Decoder) {
for i, pc := range codes {
clen := int(pr.ReadBitsBE64(5))
sum := 1 << maxPrefixBits
for sym := range pc {
for {
if clen < 1 || clen > maxPrefixBits {
panicf(errors.Corrupted, "invalid prefix bit-length: %d", clen)
}
b, ok := pr.TryReadBits(1)
if !ok {
b = pr.ReadBits(1)
}
if b == 0 {
break
}
b, ok = pr.TryReadBits(1)
if !ok {
b = pr.ReadBits(1)
}
clen -= int(b*2) - 1 // +1 or -1
}
pc[sym] = prefix.PrefixCode{Sym: uint32(sym), Len: uint32(clen)}
sum -= (1 << maxPrefixBits) >> uint(clen)
}
if sum == 0 {
// Fast path, but only handles complete trees.
if err := prefix.GeneratePrefixes(pc); err != nil {
errors.Panic(err) // Using complete trees; should never fail
}
} else {
// Slow path, but handles anything.
pc = handleDegenerateCodes(pc) // Never fails, but may fail later
codes[i] = pc
}
trees[i].Init(pc)
}
}
type prefixWriter struct{ prefix.Writer }
func (pw *prefixWriter) Init(w io.Writer) {
pw.Writer.Init(w, true)
}
func (pw *prefixWriter) WriteBitsBE64(v uint64, nb uint) {
if nb <= 32 {
v := internal.ReverseUint32N(uint32(v), nb)
pw.WriteBits(uint(v), nb)
return
}
v <<= (64 - nb)
v0 := internal.ReverseUint32(uint32(v >> 32))
v1 := internal.ReverseUint32(uint32(v))
pw.WriteBits(uint(v0), 32)
pw.WriteBits(uint(v1), nb-32)
return
}
func (pw *prefixWriter) WritePrefixCodes(codes []prefix.PrefixCodes, trees []prefix.Encoder) {
for i, pc := range codes {
if err := prefix.GeneratePrefixes(pc); err != nil {
errors.Panic(err) // Using complete trees; should never fail
}
trees[i].Init(pc)
clen := int(pc[0].Len)
pw.WriteBitsBE64(uint64(clen), 5)
for _, c := range pc {
for int(c.Len) < clen {
pw.WriteBits(3, 2) // 11
clen--
}
for int(c.Len) > clen {
pw.WriteBits(1, 2) // 10
clen++
}
pw.WriteBits(0, 1)
}
}
}
// handleDegenerateCodes converts a degenerate tree into a canonical tree.
//
// For example, when the input is an under-subscribed tree:
// input: []PrefixCode{
// {Sym: 0, Len: 3},
// {Sym: 1, Len: 4},
// {Sym: 2, Len: 3},
// }
// output: []PrefixCode{
// {Sym: 0, Len: 3, Val: 0}, // 000
// {Sym: 1, Len: 4, Val: 2}, // 0010
// {Sym: 2, Len: 3, Val: 4}, // 100
// {Sym: 258, Len: 4, Val: 10}, // 1010
// {Sym: 259, Len: 3, Val: 6}, // 110
// {Sym: 260, Len: 1, Val: 1}, // 1
// }
//
// For example, when the input is an over-subscribed tree:
// input: []PrefixCode{
// {Sym: 0, Len: 1},
// {Sym: 1, Len: 3},
// {Sym: 2, Len: 4},
// {Sym: 3, Len: 3},
// {Sym: 4, Len: 2},
// }
// output: []PrefixCode{
// {Sym: 0, Len: 1, Val: 0}, // 0
// {Sym: 1, Len: 3, Val: 3}, // 011
// {Sym: 3, Len: 3, Val: 7}, // 111
// {Sym: 4, Len: 2, Val: 1}, // 01
// }
func handleDegenerateCodes(codes prefix.PrefixCodes) prefix.PrefixCodes {
// Since there is no formal definition for the BZip2 format, there is no
// specification that says that the code lengths must form a complete
// prefix tree (IE: it is neither over-subscribed nor under-subscribed).
// Thus, the original C implementation becomes the reference for how prefix
// decoding is done in these edge cases. Unfortunately, the C version does
// not error when an invalid tree is used, but rather allows decoding to
// continue and only errors if some bit pattern happens to cause an error.
// Thus, it is possible for an invalid tree to end up decoding an input
// "properly" so long as invalid bit patterns are not present. In order to
// replicate this non-specified behavior, we use a ported version of the
// C code to generate the codes as a valid canonical tree by substituting
// invalid nodes with invalid symbols.
//
// ====================================================
// This program, "bzip2", the associated library "libbzip2", and all
// documentation, are copyright (C) 1996-2010 Julian R Seward. All
// rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. The origin of this software must not be misrepresented; you must
// not claim that you wrote the original software. If you use this
// software in a product, an acknowledgment in the product
// documentation would be appreciated but is not required.
//
// 3. Altered source versions must be plainly marked as such, and must
// not be misrepresented as being the original software.
//
// 4. The name of the author may not be used to endorse or promote
// products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Julian Seward, jseward@bzip.org
// bzip2/libbzip2 version 1.0.6 of 6 September 2010
// ====================================================
var (
limits [maxPrefixBits + 2]int32
bases [maxPrefixBits + 2]int32
perms [maxNumSyms]int32
minLen = uint32(maxPrefixBits)
maxLen = uint32(0)
)
const (
statusOkay = iota
statusInvalid
statusNeedBits
statusMaxBits
)
// createTables is the BZ2_hbCreateDecodeTables function from the C code.
createTables := func(codes []prefix.PrefixCode) {
for _, c := range codes {
if c.Len > maxLen {
maxLen = c.Len
}
if c.Len < minLen {
minLen = c.Len
}
}
var pp int
for i := minLen; i <= maxLen; i++ {
for j, c := range codes {
if c.Len == i {
perms[pp] = int32(j)
pp++
}
}
}
var vec int32
for _, c := range codes {
bases[c.Len+1]++
}
for i := 1; i < len(bases); i++ {
bases[i] += bases[i-1]
}
for i := minLen; i <= maxLen; i++ {
vec += bases[i+1] - bases[i]
limits[i] = vec - 1
vec <<= 1
}
for i := minLen + 1; i <= maxLen; i++ {
bases[i] = ((limits[i-1] + 1) << 1) - bases[i]
}
}
// getSymbol is the GET_MTF_VAL macro from the C code.
getSymbol := func(c prefix.PrefixCode) (uint32, int) {
v := internal.ReverseUint32(c.Val)
n := c.Len
zn := minLen
if zn > n {
return 0, statusNeedBits
}
zvec := int32(v >> (32 - zn))
v <<= zn
for {
if zn > maxLen {
return 0, statusMaxBits
}
if zvec <= limits[zn] {
break
}
zn++
if zn > n {
return 0, statusNeedBits
}
zvec = (zvec << 1) | int32(v>>31)
v <<= 1
}
if zvec-bases[zn] < 0 || zvec-bases[zn] >= maxNumSyms {
return 0, statusInvalid
}
return uint32(perms[zvec-bases[zn]]), statusOkay
}
// Step 1: Create the prefix trees using the C algorithm.
createTables(codes)
// Step 2: Starting with the shortest bit pattern, explore the whole tree.
// If tree is under-subscribed, the worst-case runtime is O(1< 0 {
codes = append(codes, c)
}
}
return codes
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/reader.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import (
"io"
"github.com/dsnet/compress/internal"
"github.com/dsnet/compress/internal/errors"
"github.com/dsnet/compress/internal/prefix"
)
type Reader struct {
InputOffset int64 // Total number of bytes read from underlying io.Reader
OutputOffset int64 // Total number of bytes emitted from Read
rd prefixReader
err error
level int // The current compression level
rdHdrFtr int // Number of times we read the stream header and footer
blkCRC uint32 // CRC-32 IEEE of each block (as stored)
endCRC uint32 // Checksum of all blocks using bzip2's custom method
crc crc
mtf moveToFront
bwt burrowsWheelerTransform
rle runLengthEncoding
// These fields are allocated with Reader and re-used later.
treeSels []uint8
codes2D [maxNumTrees][maxNumSyms]prefix.PrefixCode
codes1D [maxNumTrees]prefix.PrefixCodes
trees1D [maxNumTrees]prefix.Decoder
syms []uint16
fuzzReader // Exported functionality when fuzz testing
}
type ReaderConfig struct {
_ struct{} // Blank field to prevent unkeyed struct literals
}
func NewReader(r io.Reader, conf *ReaderConfig) (*Reader, error) {
zr := new(Reader)
zr.Reset(r)
return zr, nil
}
func (zr *Reader) Reset(r io.Reader) error {
*zr = Reader{
rd: zr.rd,
mtf: zr.mtf,
bwt: zr.bwt,
rle: zr.rle,
treeSels: zr.treeSels,
trees1D: zr.trees1D,
syms: zr.syms,
}
zr.rd.Init(r)
return nil
}
func (zr *Reader) Read(buf []byte) (int, error) {
for {
cnt, err := zr.rle.Read(buf)
if err != rleDone && zr.err == nil {
zr.err = err
}
if cnt > 0 {
zr.crc.update(buf[:cnt])
zr.OutputOffset += int64(cnt)
return cnt, nil
}
if zr.err != nil || len(buf) == 0 {
return 0, zr.err
}
// Read the next chunk.
zr.rd.Offset = zr.InputOffset
func() {
defer errors.Recover(&zr.err)
if zr.rdHdrFtr%2 == 0 {
// Check if we are already at EOF.
if err := zr.rd.PullBits(1); err != nil {
if err == io.ErrUnexpectedEOF && zr.rdHdrFtr > 0 {
err = io.EOF // EOF is okay if we read at least one stream
}
errors.Panic(err)
}
// Read stream header.
if zr.rd.ReadBitsBE64(16) != hdrMagic {
panicf(errors.Corrupted, "invalid stream magic")
}
if ver := zr.rd.ReadBitsBE64(8); ver != 'h' {
if ver == '0' {
panicf(errors.Deprecated, "bzip1 format is not supported")
}
panicf(errors.Corrupted, "invalid version: %q", ver)
}
lvl := int(zr.rd.ReadBitsBE64(8)) - '0'
if lvl < BestSpeed || lvl > BestCompression {
panicf(errors.Corrupted, "invalid block size: %d", lvl*blockSize)
}
zr.level = lvl
zr.rdHdrFtr++
} else {
// Check and update the CRC.
if internal.GoFuzz {
zr.updateChecksum(-1, zr.crc.val) // Update with value
zr.blkCRC = zr.crc.val // Suppress CRC failures
}
if zr.blkCRC != zr.crc.val {
panicf(errors.Corrupted, "mismatching block checksum")
}
zr.endCRC = (zr.endCRC<<1 | zr.endCRC>>31) ^ zr.blkCRC
}
buf := zr.decodeBlock()
zr.rle.Init(buf)
}()
if zr.InputOffset, err = zr.rd.Flush(); zr.err == nil {
zr.err = err
}
if zr.err != nil {
zr.err = errWrap(zr.err, errors.Corrupted)
return 0, zr.err
}
}
}
func (zr *Reader) Close() error {
if zr.err == io.EOF || zr.err == errClosed {
zr.rle.Init(nil) // Make sure future reads fail
zr.err = errClosed
return nil
}
return zr.err // Return the persistent error
}
func (zr *Reader) decodeBlock() []byte {
if magic := zr.rd.ReadBitsBE64(48); magic != blkMagic {
if magic == endMagic {
endCRC := uint32(zr.rd.ReadBitsBE64(32))
if internal.GoFuzz {
zr.updateChecksum(zr.rd.BitsRead()-32, zr.endCRC)
endCRC = zr.endCRC // Suppress CRC failures
}
if zr.endCRC != endCRC {
panicf(errors.Corrupted, "mismatching stream checksum")
}
zr.endCRC = 0
zr.rd.ReadPads()
zr.rdHdrFtr++
return nil
}
panicf(errors.Corrupted, "invalid block or footer magic")
}
zr.crc.val = 0
zr.blkCRC = uint32(zr.rd.ReadBitsBE64(32))
if internal.GoFuzz {
zr.updateChecksum(zr.rd.BitsRead()-32, 0) // Record offset only
}
if zr.rd.ReadBitsBE64(1) != 0 {
panicf(errors.Deprecated, "block randomization is not supported")
}
// Read BWT related fields.
ptr := int(zr.rd.ReadBitsBE64(24)) // BWT origin pointer
// Read MTF related fields.
var dictArr [256]uint8
dict := dictArr[:0]
bmapHi := uint16(zr.rd.ReadBits(16))
for i := 0; i < 256; i, bmapHi = i+16, bmapHi>>1 {
if bmapHi&1 > 0 {
bmapLo := uint16(zr.rd.ReadBits(16))
for j := 0; j < 16; j, bmapLo = j+1, bmapLo>>1 {
if bmapLo&1 > 0 {
dict = append(dict, uint8(i+j))
}
}
}
}
// Step 1: Prefix encoding.
syms := zr.decodePrefix(len(dict))
// Step 2: Move-to-front transform and run-length encoding.
zr.mtf.Init(dict, zr.level*blockSize)
buf := zr.mtf.Decode(syms)
// Step 3: Burrows-Wheeler transformation.
if ptr >= len(buf) {
panicf(errors.Corrupted, "origin pointer (0x%06x) exceeds block size: %d", ptr, len(buf))
}
zr.bwt.Decode(buf, ptr)
return buf
}
func (zr *Reader) decodePrefix(numSyms int) (syms []uint16) {
numSyms += 2 // Remove 0 symbol, add RUNA, RUNB, and EOF symbols
if numSyms < 3 {
panicf(errors.Corrupted, "not enough prefix symbols: %d", numSyms)
}
// Read information about the trees and tree selectors.
var mtf internal.MoveToFront
numTrees := int(zr.rd.ReadBitsBE64(3))
if numTrees < minNumTrees || numTrees > maxNumTrees {
panicf(errors.Corrupted, "invalid number of prefix trees: %d", numTrees)
}
numSels := int(zr.rd.ReadBitsBE64(15))
if cap(zr.treeSels) < numSels {
zr.treeSels = make([]uint8, numSels)
}
treeSels := zr.treeSels[:numSels]
for i := range treeSels {
sym, ok := zr.rd.TryReadSymbol(&decSel)
if !ok {
sym = zr.rd.ReadSymbol(&decSel)
}
if int(sym) >= numTrees {
panicf(errors.Corrupted, "invalid prefix tree selector: %d", sym)
}
treeSels[i] = uint8(sym)
}
mtf.Decode(treeSels)
zr.treeSels = treeSels
// Initialize prefix codes.
for i := range zr.codes2D[:numTrees] {
zr.codes1D[i] = zr.codes2D[i][:numSyms]
}
zr.rd.ReadPrefixCodes(zr.codes1D[:numTrees], zr.trees1D[:numTrees])
// Read prefix encoded symbols of compressed data.
var tree *prefix.Decoder
var blkLen, selIdx int
syms = zr.syms[:0]
for {
if blkLen == 0 {
blkLen = numBlockSyms
if selIdx >= len(treeSels) {
panicf(errors.Corrupted, "not enough prefix tree selectors")
}
tree = &zr.trees1D[treeSels[selIdx]]
selIdx++
}
blkLen--
sym, ok := zr.rd.TryReadSymbol(tree)
if !ok {
sym = zr.rd.ReadSymbol(tree)
}
if int(sym) == numSyms-1 {
break // EOF marker
}
if int(sym) >= numSyms {
panicf(errors.Corrupted, "invalid prefix symbol: %d", sym)
}
if len(syms) >= zr.level*blockSize {
panicf(errors.Corrupted, "number of prefix symbols exceeds block size")
}
syms = append(syms, uint16(sym))
}
zr.syms = syms
return syms
}
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/rle1.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import "github.com/dsnet/compress/internal/errors"
// rleDone is a special "error" to indicate that the RLE stage is done.
var rleDone = errorf(errors.Unknown, "RLE1 stage is completed")
// runLengthEncoding implements the first RLE stage of bzip2. Every sequence
// of 4..255 duplicated bytes is replaced by only the first 4 bytes, and a
// single byte representing the repeat length. Similar to the C bzip2
// implementation, the encoder will always terminate repeat sequences with a
// count (even if it is the end of the buffer), and it will also never produce
// run lengths of 256..259. The decoder can handle the latter case.
//
// For example, if the input was:
// input: "AAAAAAABBBBCCCD"
//
// Then the output will be:
// output: "AAAA\x03BBBB\x00CCCD"
type runLengthEncoding struct {
buf []byte
idx int
lastVal byte
lastCnt int
}
func (rle *runLengthEncoding) Init(buf []byte) {
*rle = runLengthEncoding{buf: buf}
}
func (rle *runLengthEncoding) Write(buf []byte) (int, error) {
for i, b := range buf {
if rle.lastVal != b {
rle.lastCnt = 0
}
rle.lastCnt++
switch {
case rle.lastCnt < 4:
if rle.idx >= len(rle.buf) {
return i, rleDone
}
rle.buf[rle.idx] = b
rle.idx++
case rle.lastCnt == 4:
if rle.idx+1 >= len(rle.buf) {
return i, rleDone
}
rle.buf[rle.idx] = b
rle.idx++
rle.buf[rle.idx] = 0
rle.idx++
case rle.lastCnt < 256:
rle.buf[rle.idx-1]++
default:
if rle.idx >= len(rle.buf) {
return i, rleDone
}
rle.lastCnt = 1
rle.buf[rle.idx] = b
rle.idx++
}
rle.lastVal = b
}
return len(buf), nil
}
func (rle *runLengthEncoding) Read(buf []byte) (int, error) {
for i := range buf {
switch {
case rle.lastCnt == -4:
if rle.idx >= len(rle.buf) {
return i, errorf(errors.Corrupted, "missing terminating run-length repeater")
}
rle.lastCnt = int(rle.buf[rle.idx])
rle.idx++
if rle.lastCnt > 0 {
break // Break the switch
}
fallthrough // Count was zero, continue the work
case rle.lastCnt <= 0:
if rle.idx >= len(rle.buf) {
return i, rleDone
}
b := rle.buf[rle.idx]
rle.idx++
if b != rle.lastVal {
rle.lastCnt = 0
rle.lastVal = b
}
}
buf[i] = rle.lastVal
rle.lastCnt--
}
return len(buf), nil
}
func (rle *runLengthEncoding) Bytes() []byte { return rle.buf[:rle.idx] }
================================================
FILE: vendor/github.com/dsnet/compress/bzip2/writer.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package bzip2
import (
"io"
"github.com/dsnet/compress/internal"
"github.com/dsnet/compress/internal/errors"
"github.com/dsnet/compress/internal/prefix"
)
type Writer struct {
InputOffset int64 // Total number of bytes issued to Write
OutputOffset int64 // Total number of bytes written to underlying io.Writer
wr prefixWriter
err error
level int // The current compression level
wrHdr bool // Have we written the stream header?
blkCRC uint32 // CRC-32 IEEE of each block
endCRC uint32 // Checksum of all blocks using bzip2's custom method
crc crc
rle runLengthEncoding
bwt burrowsWheelerTransform
mtf moveToFront
// These fields are allocated with Writer and re-used later.
buf []byte
treeSels []uint8
treeSelsMTF []uint8
codes2D [maxNumTrees][maxNumSyms]prefix.PrefixCode
codes1D [maxNumTrees]prefix.PrefixCodes
trees1D [maxNumTrees]prefix.Encoder
}
type WriterConfig struct {
Level int
_ struct{} // Blank field to prevent unkeyed struct literals
}
func NewWriter(w io.Writer, conf *WriterConfig) (*Writer, error) {
var lvl int
if conf != nil {
lvl = conf.Level
}
if lvl == 0 {
lvl = DefaultCompression
}
if lvl < BestSpeed || lvl > BestCompression {
return nil, errorf(errors.Invalid, "compression level: %d", lvl)
}
zw := new(Writer)
zw.level = lvl
zw.Reset(w)
return zw, nil
}
func (zw *Writer) Reset(w io.Writer) error {
*zw = Writer{
wr: zw.wr,
level: zw.level,
rle: zw.rle,
bwt: zw.bwt,
mtf: zw.mtf,
buf: zw.buf,
treeSels: zw.treeSels,
treeSelsMTF: zw.treeSelsMTF,
trees1D: zw.trees1D,
}
zw.wr.Init(w)
if len(zw.buf) != zw.level*blockSize {
zw.buf = make([]byte, zw.level*blockSize)
}
zw.rle.Init(zw.buf)
return nil
}
func (zw *Writer) Write(buf []byte) (int, error) {
if zw.err != nil {
return 0, zw.err
}
cnt := len(buf)
for {
wrCnt, err := zw.rle.Write(buf)
if err != rleDone && zw.err == nil {
zw.err = err
}
zw.crc.update(buf[:wrCnt])
buf = buf[wrCnt:]
if len(buf) == 0 {
zw.InputOffset += int64(cnt)
return cnt, nil
}
if zw.err = zw.flush(); zw.err != nil {
return 0, zw.err
}
}
}
func (zw *Writer) flush() error {
vals := zw.rle.Bytes()
if len(vals) == 0 {
return nil
}
zw.wr.Offset = zw.OutputOffset
func() {
defer errors.Recover(&zw.err)
if !zw.wrHdr {
// Write stream header.
zw.wr.WriteBitsBE64(hdrMagic, 16)
zw.wr.WriteBitsBE64('h', 8)
zw.wr.WriteBitsBE64(uint64('0'+zw.level), 8)
zw.wrHdr = true
}
zw.encodeBlock(vals)
}()
var err error
if zw.OutputOffset, err = zw.wr.Flush(); zw.err == nil {
zw.err = err
}
if zw.err != nil {
zw.err = errWrap(zw.err, errors.Internal)
return zw.err
}
zw.endCRC = (zw.endCRC<<1 | zw.endCRC>>31) ^ zw.blkCRC
zw.blkCRC = 0
zw.rle.Init(zw.buf)
return nil
}
func (zw *Writer) Close() error {
if zw.err == errClosed {
return nil
}
// Flush RLE buffer if there is left-over data.
if zw.err = zw.flush(); zw.err != nil {
return zw.err
}
// Write stream footer.
zw.wr.Offset = zw.OutputOffset
func() {
defer errors.Recover(&zw.err)
if !zw.wrHdr {
// Write stream header.
zw.wr.WriteBitsBE64(hdrMagic, 16)
zw.wr.WriteBitsBE64('h', 8)
zw.wr.WriteBitsBE64(uint64('0'+zw.level), 8)
zw.wrHdr = true
}
zw.wr.WriteBitsBE64(endMagic, 48)
zw.wr.WriteBitsBE64(uint64(zw.endCRC), 32)
zw.wr.WritePads(0)
}()
var err error
if zw.OutputOffset, err = zw.wr.Flush(); zw.err == nil {
zw.err = err
}
if zw.err != nil {
zw.err = errWrap(zw.err, errors.Internal)
return zw.err
}
zw.err = errClosed
return nil
}
func (zw *Writer) encodeBlock(buf []byte) {
zw.blkCRC = zw.crc.val
zw.wr.WriteBitsBE64(blkMagic, 48)
zw.wr.WriteBitsBE64(uint64(zw.blkCRC), 32)
zw.wr.WriteBitsBE64(0, 1)
zw.crc.val = 0
// Step 1: Burrows-Wheeler transformation.
ptr := zw.bwt.Encode(buf)
zw.wr.WriteBitsBE64(uint64(ptr), 24)
// Step 2: Move-to-front transform and run-length encoding.
var dictMap [256]bool
for _, c := range buf {
dictMap[c] = true
}
var dictArr [256]uint8
var bmapLo [16]uint16
dict := dictArr[:0]
bmapHi := uint16(0)
for i, b := range dictMap {
if b {
c := uint8(i)
dict = append(dict, c)
bmapHi |= 1 << (c >> 4)
bmapLo[c>>4] |= 1 << (c & 0xf)
}
}
zw.wr.WriteBits(uint(bmapHi), 16)
for _, m := range bmapLo {
if m > 0 {
zw.wr.WriteBits(uint(m), 16)
}
}
zw.mtf.Init(dict, len(buf))
syms := zw.mtf.Encode(buf)
// Step 3: Prefix encoding.
zw.encodePrefix(syms, len(dict))
}
func (zw *Writer) encodePrefix(syms []uint16, numSyms int) {
numSyms += 2 // Remove 0 symbol, add RUNA, RUNB, and EOB symbols
if numSyms < 3 {
panicf(errors.Internal, "unable to encode EOB marker")
}
syms = append(syms, uint16(numSyms-1)) // EOB marker
// Compute number of prefix trees needed.
numTrees := maxNumTrees
for i, lim := range []int{200, 600, 1200, 2400} {
if len(syms) < lim {
numTrees = minNumTrees + i
break
}
}
// Compute number of block selectors.
numSels := (len(syms) + numBlockSyms - 1) / numBlockSyms
if cap(zw.treeSels) < numSels {
zw.treeSels = make([]uint8, numSels)
}
treeSels := zw.treeSels[:numSels]
for i := range treeSels {
treeSels[i] = uint8(i % numTrees)
}
// Initialize prefix codes.
for i := range zw.codes2D[:numTrees] {
pc := zw.codes2D[i][:numSyms]
for j := range pc {
pc[j] = prefix.PrefixCode{Sym: uint32(j)}
}
zw.codes1D[i] = pc
}
// First cut at assigning prefix trees to each group.
var codes prefix.PrefixCodes
var blkLen, selIdx int
for _, sym := range syms {
if blkLen == 0 {
blkLen = numBlockSyms
codes = zw.codes2D[treeSels[selIdx]][:numSyms]
selIdx++
}
blkLen--
codes[sym].Cnt++
}
// TODO(dsnet): Use K-means to cluster groups to each prefix tree.
// Generate lengths and prefixes based on symbol frequencies.
for i := range zw.trees1D[:numTrees] {
pc := prefix.PrefixCodes(zw.codes2D[i][:numSyms])
pc.SortByCount()
if err := prefix.GenerateLengths(pc, maxPrefixBits); err != nil {
errors.Panic(err)
}
pc.SortBySymbol()
}
// Write out information about the trees and tree selectors.
var mtf internal.MoveToFront
zw.wr.WriteBitsBE64(uint64(numTrees), 3)
zw.wr.WriteBitsBE64(uint64(numSels), 15)
zw.treeSelsMTF = append(zw.treeSelsMTF[:0], treeSels...)
mtf.Encode(zw.treeSelsMTF)
for _, sym := range zw.treeSelsMTF {
zw.wr.WriteSymbol(uint(sym), &encSel)
}
zw.wr.WritePrefixCodes(zw.codes1D[:numTrees], zw.trees1D[:numTrees])
// Write out prefix encoded symbols of compressed data.
var tree *prefix.Encoder
blkLen, selIdx = 0, 0
for _, sym := range syms {
if blkLen == 0 {
blkLen = numBlockSyms
tree = &zw.trees1D[treeSels[selIdx]]
selIdx++
}
blkLen--
ok := zw.wr.TryWriteSymbol(uint(sym), tree)
if !ok {
zw.wr.WriteSymbol(uint(sym), tree)
}
}
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/common.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Package internal is a collection of common compression algorithms.
//
// For performance reasons, these packages lack strong error checking and
// require that the caller to ensure that strict invariants are kept.
package internal
var (
// IdentityLUT returns the input key itself.
IdentityLUT = func() (lut [256]byte) {
for i := range lut {
lut[i] = uint8(i)
}
return lut
}()
// ReverseLUT returns the input key with its bits reversed.
ReverseLUT = func() (lut [256]byte) {
for i := range lut {
b := uint8(i)
b = (b&0xaa)>>1 | (b&0x55)<<1
b = (b&0xcc)>>2 | (b&0x33)<<2
b = (b&0xf0)>>4 | (b&0x0f)<<4
lut[i] = b
}
return lut
}()
)
// ReverseUint32 reverses all bits of v.
func ReverseUint32(v uint32) (x uint32) {
x |= uint32(ReverseLUT[byte(v>>0)]) << 24
x |= uint32(ReverseLUT[byte(v>>8)]) << 16
x |= uint32(ReverseLUT[byte(v>>16)]) << 8
x |= uint32(ReverseLUT[byte(v>>24)]) << 0
return x
}
// ReverseUint32N reverses the lower n bits of v.
func ReverseUint32N(v uint32, n uint) (x uint32) {
return ReverseUint32(v << (32 - n))
}
// ReverseUint64 reverses all bits of v.
func ReverseUint64(v uint64) (x uint64) {
x |= uint64(ReverseLUT[byte(v>>0)]) << 56
x |= uint64(ReverseLUT[byte(v>>8)]) << 48
x |= uint64(ReverseLUT[byte(v>>16)]) << 40
x |= uint64(ReverseLUT[byte(v>>24)]) << 32
x |= uint64(ReverseLUT[byte(v>>32)]) << 24
x |= uint64(ReverseLUT[byte(v>>40)]) << 16
x |= uint64(ReverseLUT[byte(v>>48)]) << 8
x |= uint64(ReverseLUT[byte(v>>56)]) << 0
return x
}
// ReverseUint64N reverses the lower n bits of v.
func ReverseUint64N(v uint64, n uint) (x uint64) {
return ReverseUint64(v << (64 - n))
}
// MoveToFront is a data structure that allows for more efficient move-to-front
// transformations. This specific implementation assumes that the alphabet is
// densely packed within 0..255.
type MoveToFront struct {
dict [256]uint8 // Mapping from indexes to values
tail int // Number of tail bytes that are already ordered
}
func (m *MoveToFront) Encode(vals []uint8) {
copy(m.dict[:], IdentityLUT[:256-m.tail]) // Reset dict to be identity
var max int
for i, val := range vals {
var idx uint8 // Reverse lookup idx in dict
for di, dv := range m.dict {
if dv == val {
idx = uint8(di)
break
}
}
vals[i] = idx
max |= int(idx)
copy(m.dict[1:], m.dict[:idx])
m.dict[0] = val
}
m.tail = 256 - max - 1
}
func (m *MoveToFront) Decode(idxs []uint8) {
copy(m.dict[:], IdentityLUT[:256-m.tail]) // Reset dict to be identity
var max int
for i, idx := range idxs {
val := m.dict[idx] // Forward lookup val in dict
idxs[i] = val
max |= int(idx)
copy(m.dict[1:], m.dict[:idx])
m.dict[0] = val
}
m.tail = 256 - max - 1
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/debug.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build debug,!gofuzz
package internal
const (
Debug = true
GoFuzz = false
)
================================================
FILE: vendor/github.com/dsnet/compress/internal/errors/errors.go
================================================
// Copyright 2016, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// Package errors implements functions to manipulate compression errors.
//
// In idiomatic Go, it is an anti-pattern to use panics as a form of error
// reporting in the API. Instead, the expected way to transmit errors is by
// returning an error value. Unfortunately, the checking of "err != nil" in
// tight loops commonly found in compression causes non-negligible performance
// degradation. While this may not be idiomatic, the internal packages of this
// repository rely on panics as a normal means to convey errors. In order to
// ensure that these panics do not leak across the public API, the public
// packages must recover from these panics and present an error value.
//
// The Panic and Recover functions in this package provide a safe way to
// recover from errors only generated from within this repository.
//
// Example usage:
// func Foo() (err error) {
// defer errors.Recover(&err)
//
// if rand.Intn(2) == 0 {
// // Unexpected panics will not be caught by Recover.
// io.Closer(nil).Close()
// } else {
// // Errors thrown by Panic will be caught by Recover.
// errors.Panic(errors.New("whoopsie"))
// }
// }
//
package errors
import "strings"
const (
// Unknown indicates that there is no classification for this error.
Unknown = iota
// Internal indicates that this error is due to an internal bug.
// Users should file a issue report if this type of error is encountered.
Internal
// Invalid indicates that this error is due to the user misusing the API
// and is indicative of a bug on the user's part.
Invalid
// Deprecated indicates the use of a deprecated and unsupported feature.
Deprecated
// Corrupted indicates that the input stream is corrupted.
Corrupted
// Closed indicates that the handlers are closed.
Closed
)
var codeMap = map[int]string{
Unknown: "unknown error",
Internal: "internal error",
Invalid: "invalid argument",
Deprecated: "deprecated format",
Corrupted: "corrupted input",
Closed: "closed handler",
}
type Error struct {
Code int // The error type
Pkg string // Name of the package where the error originated
Msg string // Descriptive message about the error (optional)
}
func (e Error) Error() string {
var ss []string
for _, s := range []string{e.Pkg, codeMap[e.Code], e.Msg} {
if s != "" {
ss = append(ss, s)
}
}
return strings.Join(ss, ": ")
}
func (e Error) CompressError() {}
func (e Error) IsInternal() bool { return e.Code == Internal }
func (e Error) IsInvalid() bool { return e.Code == Invalid }
func (e Error) IsDeprecated() bool { return e.Code == Deprecated }
func (e Error) IsCorrupted() bool { return e.Code == Corrupted }
func (e Error) IsClosed() bool { return e.Code == Closed }
func IsInternal(err error) bool { return isCode(err, Internal) }
func IsInvalid(err error) bool { return isCode(err, Invalid) }
func IsDeprecated(err error) bool { return isCode(err, Deprecated) }
func IsCorrupted(err error) bool { return isCode(err, Corrupted) }
func IsClosed(err error) bool { return isCode(err, Closed) }
func isCode(err error, code int) bool {
if cerr, ok := err.(Error); ok && cerr.Code == code {
return true
}
return false
}
// errWrap is used by Panic and Recover to ensure that only errors raised by
// Panic are recovered by Recover.
type errWrap struct{ e *error }
func Recover(err *error) {
switch ex := recover().(type) {
case nil:
// Do nothing.
case errWrap:
*err = *ex.e
default:
panic(ex)
}
}
func Panic(err error) {
panic(errWrap{&err})
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/gofuzz.go
================================================
// Copyright 2016, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build gofuzz
package internal
const (
Debug = true
GoFuzz = true
)
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/debug.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build debug
package prefix
import (
"fmt"
"math"
"strings"
)
func max(a, b int) int {
if a > b {
return a
}
return b
}
func lenBase2(n uint) int {
return int(math.Ceil(math.Log2(float64(n + 1))))
}
func padBase2(v, n uint, m int) string {
s := fmt.Sprintf("%b", 1< 0 {
return strings.Repeat(" ", pad) + s
}
return s
}
func lenBase10(n int) int {
return int(math.Ceil(math.Log10(float64(n + 1))))
}
func padBase10(n, m int) string {
s := fmt.Sprintf("%d", n)
if pad := m - len(s); pad > 0 {
return strings.Repeat(" ", pad) + s
}
return s
}
func (rc RangeCodes) String() string {
var maxLen, maxBase int
for _, c := range rc {
maxLen = max(maxLen, int(c.Len))
maxBase = max(maxBase, int(c.Base))
}
var ss []string
ss = append(ss, "{")
for i, c := range rc {
base := padBase10(int(c.Base), lenBase10(maxBase))
if c.Len > 0 {
base += fmt.Sprintf("-%d", c.End()-1)
}
ss = append(ss, fmt.Sprintf("\t%s: {len: %s, range: %s},",
padBase10(int(i), lenBase10(len(rc)-1)),
padBase10(int(c.Len), lenBase10(maxLen)),
base,
))
}
ss = append(ss, "}")
return strings.Join(ss, "\n")
}
func (pc PrefixCodes) String() string {
var maxSym, maxLen, maxCnt int
for _, c := range pc {
maxSym = max(maxSym, int(c.Sym))
maxLen = max(maxLen, int(c.Len))
maxCnt = max(maxCnt, int(c.Cnt))
}
var ss []string
ss = append(ss, "{")
for _, c := range pc {
var cntStr string
if maxCnt > 0 {
cnt := int(32*float32(c.Cnt)/float32(maxCnt) + 0.5)
cntStr = fmt.Sprintf("%s |%s",
padBase10(int(c.Cnt), lenBase10(maxCnt)),
strings.Repeat("#", cnt),
)
}
ss = append(ss, fmt.Sprintf("\t%s: %s, %s",
padBase10(int(c.Sym), lenBase10(maxSym)),
padBase2(uint(c.Val), uint(c.Len), maxLen),
cntStr,
))
}
ss = append(ss, "}")
return strings.Join(ss, "\n")
}
func (pd Decoder) String() string {
var ss []string
ss = append(ss, "{")
if len(pd.chunks) > 0 {
ss = append(ss, "\tchunks: {")
for i, c := range pd.chunks {
label := "sym"
if uint(c&countMask) > uint(pd.chunkBits) {
label = "idx"
}
ss = append(ss, fmt.Sprintf("\t\t%s: {%s: %s, len: %s}",
padBase2(uint(i), uint(pd.chunkBits), int(pd.chunkBits)),
label, padBase10(int(c>>countBits), 3),
padBase10(int(c&countMask), 2),
))
}
ss = append(ss, "\t},")
for j, links := range pd.links {
ss = append(ss, fmt.Sprintf("\tlinks[%d]: {", j))
linkBits := lenBase2(uint(pd.linkMask))
for i, c := range links {
ss = append(ss, fmt.Sprintf("\t\t%s: {sym: %s, len: %s},",
padBase2(uint(i), uint(linkBits), int(linkBits)),
padBase10(int(c>>countBits), 3),
padBase10(int(c&countMask), 2),
))
}
ss = append(ss, "\t},")
}
}
ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pd.chunkMask))
ss = append(ss, fmt.Sprintf("\tlinkMask: %b,", pd.linkMask))
ss = append(ss, fmt.Sprintf("\tchunkBits: %d,", pd.chunkBits))
ss = append(ss, fmt.Sprintf("\tMinBits: %d,", pd.MinBits))
ss = append(ss, fmt.Sprintf("\tNumSyms: %d,", pd.NumSyms))
ss = append(ss, "}")
return strings.Join(ss, "\n")
}
func (pe Encoder) String() string {
var maxLen int
for _, c := range pe.chunks {
maxLen = max(maxLen, int(c&countMask))
}
var ss []string
ss = append(ss, "{")
if len(pe.chunks) > 0 {
ss = append(ss, "\tchunks: {")
for i, c := range pe.chunks {
ss = append(ss, fmt.Sprintf("\t\t%s: %s,",
padBase10(i, 3),
padBase2(uint(c>>countBits), uint(c&countMask), maxLen),
))
}
ss = append(ss, "\t},")
}
ss = append(ss, fmt.Sprintf("\tchunkMask: %b,", pe.chunkMask))
ss = append(ss, fmt.Sprintf("\tNumSyms: %d,", pe.NumSyms))
ss = append(ss, "}")
return strings.Join(ss, "\n")
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/decoder.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
import (
"sort"
"github.com/dsnet/compress/internal"
)
// The algorithm used to decode variable length codes is based on the lookup
// method in zlib. If the code is less-than-or-equal to maxChunkBits,
// then the symbol can be decoded using a single lookup into the chunks table.
// Otherwise, the links table will be used for a second level lookup.
//
// The chunks slice is keyed by the contents of the bit buffer ANDed with
// the chunkMask to avoid a out-of-bounds lookup. The value of chunks is a tuple
// that is decoded as follow:
//
// var length = chunks[bitBuffer&chunkMask] & countMask
// var symbol = chunks[bitBuffer&chunkMask] >> countBits
//
// If the decoded length is larger than chunkBits, then an overflow link table
// must be used for further decoding. In this case, the symbol is actually the
// index into the links tables. The second-level links table returned is
// processed in the same way as the chunks table.
//
// if length > chunkBits {
// var index = symbol // Previous symbol is index into links tables
// length = links[index][bitBuffer>>chunkBits & linkMask] & countMask
// symbol = links[index][bitBuffer>>chunkBits & linkMask] >> countBits
// }
//
// See the following:
// http://www.gzip.org/algorithm.txt
type Decoder struct {
chunks []uint32 // First-level lookup map
links [][]uint32 // Second-level lookup map
chunkMask uint32 // Mask the length of the chunks table
linkMask uint32 // Mask the length of the link table
chunkBits uint32 // Bit-length of the chunks table
MinBits uint32 // The minimum number of bits to safely make progress
NumSyms uint32 // Number of symbols
}
// Init initializes Decoder according to the codes provided.
func (pd *Decoder) Init(codes PrefixCodes) {
// Handle special case trees.
if len(codes) <= 1 {
switch {
case len(codes) == 0: // Empty tree (should error if used later)
*pd = Decoder{chunks: pd.chunks[:0], links: pd.links[:0], NumSyms: 0}
case len(codes) == 1 && codes[0].Len == 0: // Single code tree (bit-length of zero)
pd.chunks = append(pd.chunks[:0], codes[0].Sym< c.Len {
minBits = c.Len
}
if maxBits < c.Len {
maxBits = c.Len
}
}
// Allocate chunks table as needed.
const maxChunkBits = 9 // This can be tuned for better performance
pd.NumSyms = uint32(len(codes))
pd.MinBits = minBits
pd.chunkBits = maxBits
if pd.chunkBits > maxChunkBits {
pd.chunkBits = maxChunkBits
}
numChunks := 1 << pd.chunkBits
pd.chunks = allocUint32s(pd.chunks, numChunks)
pd.chunkMask = uint32(numChunks - 1)
// Allocate links tables as needed.
pd.links = pd.links[:0]
pd.linkMask = 0
if pd.chunkBits < maxBits {
numLinks := 1 << (maxBits - pd.chunkBits)
pd.linkMask = uint32(numLinks - 1)
var linkIdx uint32
for i := range pd.chunks {
pd.chunks[i] = 0 // Logic below relies on zero value as uninitialized
}
for _, c := range codes {
if c.Len > pd.chunkBits && pd.chunks[c.Val&pd.chunkMask] == 0 {
pd.chunks[c.Val&pd.chunkMask] = (linkIdx << countBits) | (pd.chunkBits + 1)
linkIdx++
}
}
pd.links = extendSliceUint32s(pd.links, int(linkIdx))
linksFlat := allocUint32s(pd.links[0], numLinks*int(linkIdx))
for i, j := 0, 0; i < len(pd.links); i, j = i+1, j+numLinks {
pd.links[i] = linksFlat[j : j+numLinks]
}
}
// Fill out chunks and links tables with values.
for _, c := range codes {
chunk := c.Sym<> countBits
links := pd.links[linkIdx]
skip := 1 << uint(c.Len-pd.chunkBits)
for j := int(c.Val >> pd.chunkBits); j < len(links); j += skip {
links[j] = chunk
}
}
}
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/encoder.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
import (
"sort"
"github.com/dsnet/compress/internal"
)
type Encoder struct {
chunks []uint32 // First-level lookup map
chunkMask uint32 // Mask the length of the chunks table
NumSyms uint32 // Number of symbols
}
// Init initializes Encoder according to the codes provided.
func (pe *Encoder) Init(codes PrefixCodes) {
// Handle special case trees.
if len(codes) <= 1 {
switch {
case len(codes) == 0: // Empty tree (should error if used later)
*pe = Encoder{chunks: pe.chunks[:0], NumSyms: 0}
case len(codes) == 1 && codes[0].Len == 0: // Single code tree (bit-length of zero)
pe.chunks = append(pe.chunks[:0], codes[0].Val< 0; n >>= 1 {
numChunks <<= 1
}
pe.NumSyms = uint32(len(codes))
retry:
// Allocate and reset chunks.
pe.chunks = allocUint32s(pe.chunks, numChunks)
pe.chunkMask = uint32(numChunks - 1)
for i := range pe.chunks {
pe.chunks[i] = 0 // Logic below relies on zero value as uninitialized
}
// Insert each symbol, checking that there are no conflicts.
for _, c := range codes {
if pe.chunks[c.Sym&pe.chunkMask] > 0 {
// Collision found our "hash" table, so grow and try again.
numChunks <<= 1
goto retry
}
pe.chunks[c.Sym&pe.chunkMask] = c.Val<> uint(c.Len)
}
return sum == 0 || len(pc) == 0
}
// checkPrefixes reports whether all codes have non-overlapping prefixes.
func (pc PrefixCodes) checkPrefixes() bool {
for i, c1 := range pc {
for j, c2 := range pc {
mask := uint32(1)< 0 {
c.Val = internal.ReverseUint32N(c.Val, uint(c.Len))
if vals[c.Len].Cnt > 0 && vals[c.Len].Val+1 != c.Val {
return false
}
vals[c.Len].Val = c.Val
vals[c.Len].Cnt++
}
}
// Rule 2.
var last PrefixCode
for _, v := range vals {
if v.Cnt > 0 {
curVal := v.Val - v.Cnt + 1
if last.Cnt != 0 && last.Val >= curVal {
return false
}
last = v
}
}
return true
}
// GenerateLengths assigns non-zero bit-lengths to all codes. Codes with high
// frequency counts will be assigned shorter codes to reduce bit entropy.
// This function is used primarily by compressors.
//
// The input codes must have the Cnt field populated, be sorted by count.
// Even if a code has a count of 0, a non-zero bit-length will be assigned.
//
// The result will have the Len field populated. The algorithm used guarantees
// that Len <= maxBits and that it is a complete prefix tree. The resulting
// codes will remain sorted by count.
func GenerateLengths(codes PrefixCodes, maxBits uint) error {
if len(codes) <= 1 {
if len(codes) == 1 {
codes[0].Len = 0
}
return nil
}
// Verify that the codes are in ascending order by count.
cntLast := codes[0].Cnt
for _, c := range codes[1:] {
if c.Cnt < cntLast {
return errorf(errors.Invalid, "non-monotonically increasing symbol counts")
}
cntLast = c.Cnt
}
// Construct a Huffman tree used to generate the bit-lengths.
//
// The Huffman tree is a binary tree where each symbol lies as a leaf node
// on this tree. The length of the prefix code to assign is the depth of
// that leaf from the root. The Huffman algorithm, which runs in O(n),
// is used to generate the tree. It assumes that codes are sorted in
// increasing order of frequency.
//
// The algorithm is as follows:
// 1. Start with two queues, F and Q, where F contains all of the starting
// symbols sorted such that symbols with lowest counts come first.
// 2. While len(F)+len(Q) > 1:
// 2a. Dequeue the node from F or Q that has the lowest weight as N0.
// 2b. Dequeue the node from F or Q that has the lowest weight as N1.
// 2c. Create a new node N that has N0 and N1 as its children.
// 2d. Enqueue N into the back of Q.
// 3. The tree's root node is Q[0].
type node struct {
cnt uint32
// n0 or c0 represent the left child of this node.
// Since Go does not have unions, only one of these will be set.
// Similarly, n1 or c1 represent the right child of this node.
//
// If n0 or n1 is set, then it represents a "pointer" to another
// node in the Huffman tree. Since Go's pointer analysis cannot reason
// that these node pointers do not escape (golang.org/issue/13493),
// we use an index to a node in the nodes slice as a pseudo-pointer.
//
// If c0 or c1 is set, then it represents a leaf "node" in the
// Huffman tree. The leaves are the PrefixCode values themselves.
n0, n1 int // Index to child nodes
c0, c1 *PrefixCode
}
var nodeIdx int
var nodeArr [1024]node // Large enough to handle most cases on the stack
nodes := nodeArr[:]
if len(nodes) < len(codes) {
nodes = make([]node, len(codes)) // Number of internal nodes < number of leaves
}
freqs, queue := codes, nodes[:0]
for len(freqs)+len(queue) > 1 {
// These are the two smallest nodes at the front of freqs and queue.
var n node
if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
n.c0, freqs = &freqs[0], freqs[1:]
n.cnt += n.c0.Cnt
} else {
n.cnt += queue[0].cnt
n.n0 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
nodeIdx++
queue = queue[1:]
}
if len(queue) == 0 || (len(freqs) > 0 && freqs[0].Cnt <= queue[0].cnt) {
n.c1, freqs = &freqs[0], freqs[1:]
n.cnt += n.c1.Cnt
} else {
n.cnt += queue[0].cnt
n.n1 = nodeIdx // nodeIdx is same as &queue[0] - &nodes[0]
nodeIdx++
queue = queue[1:]
}
queue = append(queue, n)
}
rootIdx := nodeIdx
// Search the whole binary tree, noting when we hit each leaf node.
// We do not care about the exact Huffman tree structure, but rather we only
// care about depth of each of the leaf nodes. That is, the depth determines
// how long each symbol is in bits.
//
// Since the number of leaves is n, there is at most n internal nodes.
// Thus, this algorithm runs in O(n).
var fixBits bool
var explore func(int, uint)
explore = func(rootIdx int, level uint) {
root := &nodes[rootIdx]
// Explore left branch.
if root.c0 == nil {
explore(root.n0, level+1)
} else {
fixBits = fixBits || (level > maxBits)
root.c0.Len = uint32(level)
}
// Explore right branch.
if root.c1 == nil {
explore(root.n1, level+1)
} else {
fixBits = fixBits || (level > maxBits)
root.c1.Len = uint32(level)
}
}
explore(rootIdx, 1)
// Fix the bit-lengths if we violate the maxBits requirement.
if fixBits {
// Create histogram for number of symbols with each bit-length.
var symBitsArr [valueBits + 1]uint32
symBits := symBitsArr[:] // symBits[nb] indicates number of symbols using nb bits
for _, c := range codes {
for int(c.Len) >= len(symBits) {
symBits = append(symBits, 0)
}
symBits[c.Len]++
}
// Fudge the tree such that the largest bit-length is <= maxBits.
// This is accomplish by effectively doing a tree rotation. That is, we
// increase the bit-length of some higher frequency code, so that the
// bit-lengths of lower frequency codes can be decreased.
//
// Visually, this looks like the following transform:
//
// Level Before After
// __ ___
// / \ / \
// n-1 X / \ /\ /\
// n X /\ X X X X
// n+1 X X
//
var treeRotate func(uint)
treeRotate = func(nb uint) {
if symBits[nb-1] == 0 {
treeRotate(nb - 1)
}
symBits[nb-1] -= 1 // Push this node to the level below
symBits[nb] += 3 // This level gets one node from above, two from below
symBits[nb+1] -= 2 // Push two nodes to the level above
}
for i := uint(len(symBits)) - 1; i > maxBits; i-- {
for symBits[i] > 0 {
treeRotate(i - 1)
}
}
// Assign bit-lengths to each code. Since codes is sorted in increasing
// order of frequency, that means that the most frequently used symbols
// should have the shortest bit-lengths. Thus, we copy symbols to codes
// from the back of codes first.
cs := codes
for nb, cnt := range symBits {
if cnt > 0 {
pos := len(cs) - int(cnt)
cs2 := cs[pos:]
for i := range cs2 {
cs2[i].Len = uint32(nb)
}
cs = cs[:pos]
}
}
if len(cs) != 0 {
panic("not all codes were used up")
}
}
if internal.Debug && !codes.checkLengths() {
panic("incomplete prefix tree detected")
}
return nil
}
// GeneratePrefixes assigns a prefix value to all codes according to the
// bit-lengths. This function is used by both compressors and decompressors.
//
// The input codes must have the Sym and Len fields populated and be
// sorted by symbol. The bit-lengths of each code must be properly allocated,
// such that it forms a complete tree.
//
// The result will have the Val field populated and will produce a canonical
// prefix tree. The resulting codes will remain sorted by symbol.
func GeneratePrefixes(codes PrefixCodes) error {
if len(codes) <= 1 {
if len(codes) == 1 {
if codes[0].Len != 0 {
return errorf(errors.Invalid, "degenerate prefix tree with one node")
}
codes[0].Val = 0
}
return nil
}
// Compute basic statistics on the symbols.
var bitCnts [valueBits + 1]uint
c0 := codes[0]
bitCnts[c0.Len]++
minBits, maxBits, symLast := c0.Len, c0.Len, c0.Sym
for _, c := range codes[1:] {
if c.Sym <= symLast {
return errorf(errors.Invalid, "non-unique or non-monotonically increasing symbols")
}
if minBits > c.Len {
minBits = c.Len
}
if maxBits < c.Len {
maxBits = c.Len
}
bitCnts[c.Len]++ // Histogram of bit counts
symLast = c.Sym // Keep track of last symbol
}
if minBits == 0 {
return errorf(errors.Invalid, "invalid prefix bit-length")
}
// Compute the next code for a symbol of a given bit length.
var nextCodes [valueBits + 1]uint
var code uint
for i := minBits; i <= maxBits; i++ {
code <<= 1
nextCodes[i] = code
code += bitCnts[i]
}
if code != 1<= n {
return s[:n]
}
return make([]uint32, n, n*3/2)
}
func extendSliceUint32s(s [][]uint32, n int) [][]uint32 {
if cap(s) >= n {
return s[:n]
}
ss := make([][]uint32, n, n*3/2)
copy(ss, s[:cap(s)])
return ss
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/range.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
type RangeCode struct {
Base uint32 // Starting base offset of the range
Len uint32 // Bit-length of a subsequent integer to add to base offset
}
type RangeCodes []RangeCode
type RangeEncoder struct {
rcs RangeCodes
lut [1024]uint32
minBase uint
}
// End reports the non-inclusive ending range.
func (rc RangeCode) End() uint32 { return rc.Base + (1 << rc.Len) }
// MakeRangeCodes creates a RangeCodes, where each region is assumed to be
// contiguously stacked, without any gaps, with bit-lengths taken from bits.
func MakeRangeCodes(minBase uint, bits []uint) (rc RangeCodes) {
for _, nb := range bits {
rc = append(rc, RangeCode{Base: uint32(minBase), Len: uint32(nb)})
minBase += 1 << nb
}
return rc
}
// Base reports the inclusive starting range for all ranges.
func (rcs RangeCodes) Base() uint32 { return rcs[0].Base }
// End reports the non-inclusive ending range for all ranges.
func (rcs RangeCodes) End() uint32 { return rcs[len(rcs)-1].End() }
// checkValid reports whether the RangeCodes is valid. In order to be valid,
// the following must hold true:
// rcs[i-1].Base <= rcs[i].Base
// rcs[i-1].End <= rcs[i].End
// rcs[i-1].End >= rcs[i].Base
//
// Practically speaking, each range must be increasing and must not have any
// gaps in between. It is okay for ranges to overlap.
func (rcs RangeCodes) checkValid() bool {
if len(rcs) == 0 {
return false
}
pre := rcs[0]
for _, cur := range rcs[1:] {
preBase, preEnd := pre.Base, pre.End()
curBase, curEnd := cur.Base, cur.End()
if preBase > curBase || preEnd > curEnd || preEnd < curBase {
return false
}
pre = cur
}
return true
}
func (re *RangeEncoder) Init(rcs RangeCodes) {
if !rcs.checkValid() {
panic("invalid range codes")
}
*re = RangeEncoder{rcs: rcs, minBase: uint(rcs.Base())}
for sym, rc := range rcs {
base := int(rc.Base) - int(re.minBase)
end := int(rc.End()) - int(re.minBase)
if base >= len(re.lut) {
break
}
if end > len(re.lut) {
end = len(re.lut)
}
for i := base; i < end; i++ {
re.lut[i] = uint32(sym)
}
}
}
func (re *RangeEncoder) Encode(offset uint) (sym uint) {
if idx := int(offset - re.minBase); idx < len(re.lut) {
return uint(re.lut[idx])
}
sym = uint(re.lut[len(re.lut)-1])
retry:
if int(sym) >= len(re.rcs) || re.rcs[sym].Base > uint32(offset) {
return sym - 1
}
sym++
goto retry // Avoid for-loop so that this function can be inlined
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/reader.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
import (
"bufio"
"bytes"
"encoding/binary"
"io"
"strings"
"github.com/dsnet/compress"
"github.com/dsnet/compress/internal"
"github.com/dsnet/compress/internal/errors"
)
// Reader implements a prefix decoder. If the input io.Reader satisfies the
// compress.ByteReader or compress.BufferedReader interface, then it also
// guarantees that it will never read more bytes than is necessary.
//
// For high performance, provide an io.Reader that satisfies the
// compress.BufferedReader interface. If the input does not satisfy either
// compress.ByteReader or compress.BufferedReader, then it will be internally
// wrapped with a bufio.Reader.
type Reader struct {
Offset int64 // Number of bytes read from the underlying io.Reader
rd io.Reader
byteRd compress.ByteReader // Set if rd is a ByteReader
bufRd compress.BufferedReader // Set if rd is a BufferedReader
bufBits uint64 // Buffer to hold some bits
numBits uint // Number of valid bits in bufBits
bigEndian bool // Do we treat input bytes as big endian?
// These fields are only used if rd is a compress.BufferedReader.
bufPeek []byte // Buffer for the Peek data
discardBits int // Number of bits to discard from reader
fedBits uint // Number of bits fed in last call to PullBits
// These fields are used to reduce allocations.
bb *buffer
br *bytesReader
sr *stringReader
bu *bufio.Reader
}
// Init initializes the bit Reader to read from r. If bigEndian is true, then
// bits will be read starting from the most-significant bits of a byte
// (as done in bzip2), otherwise it will read starting from the
// least-significant bits of a byte (such as for deflate and brotli).
func (pr *Reader) Init(r io.Reader, bigEndian bool) {
*pr = Reader{
rd: r,
bigEndian: bigEndian,
bb: pr.bb,
br: pr.br,
sr: pr.sr,
bu: pr.bu,
}
switch rr := r.(type) {
case *bytes.Buffer:
if pr.bb == nil {
pr.bb = new(buffer)
}
*pr.bb = buffer{Buffer: rr}
pr.bufRd = pr.bb
case *bytes.Reader:
if pr.br == nil {
pr.br = new(bytesReader)
}
*pr.br = bytesReader{Reader: rr}
pr.bufRd = pr.br
case *strings.Reader:
if pr.sr == nil {
pr.sr = new(stringReader)
}
*pr.sr = stringReader{Reader: rr}
pr.bufRd = pr.sr
case compress.BufferedReader:
pr.bufRd = rr
case compress.ByteReader:
pr.byteRd = rr
default:
if pr.bu == nil {
pr.bu = bufio.NewReader(nil)
}
pr.bu.Reset(r)
pr.rd, pr.bufRd = pr.bu, pr.bu
}
}
// BitsRead reports the total number of bits emitted from any Read method.
func (pr *Reader) BitsRead() int64 {
offset := 8*pr.Offset - int64(pr.numBits)
if pr.bufRd != nil {
discardBits := pr.discardBits + int(pr.fedBits-pr.numBits)
offset = 8*pr.Offset + int64(discardBits)
}
return offset
}
// IsBufferedReader reports whether the underlying io.Reader is also a
// compress.BufferedReader.
func (pr *Reader) IsBufferedReader() bool {
return pr.bufRd != nil
}
// ReadPads reads 0-7 bits from the bit buffer to achieve byte-alignment.
func (pr *Reader) ReadPads() uint {
nb := pr.numBits % 8
val := uint(pr.bufBits & uint64(1<>= nb
pr.numBits -= nb
return val
}
// Read reads bytes into buf.
// The bit-ordering mode does not affect this method.
func (pr *Reader) Read(buf []byte) (cnt int, err error) {
if pr.numBits > 0 {
if pr.numBits%8 != 0 {
return 0, errorf(errors.Invalid, "non-aligned bit buffer")
}
for cnt = 0; len(buf) > cnt && pr.numBits > 0; cnt++ {
if pr.bigEndian {
buf[cnt] = internal.ReverseLUT[byte(pr.bufBits)]
} else {
buf[cnt] = byte(pr.bufBits)
}
pr.bufBits >>= 8
pr.numBits -= 8
}
return cnt, nil
}
if _, err := pr.Flush(); err != nil {
return 0, err
}
cnt, err = pr.rd.Read(buf)
pr.Offset += int64(cnt)
return cnt, err
}
// ReadOffset reads an offset value using the provided RangeCodes indexed by
// the symbol read.
func (pr *Reader) ReadOffset(pd *Decoder, rcs RangeCodes) uint {
rc := rcs[pr.ReadSymbol(pd)]
return uint(rc.Base) + pr.ReadBits(uint(rc.Len))
}
// TryReadBits attempts to read nb bits using the contents of the bit buffer
// alone. It returns the value and whether it succeeded.
//
// This method is designed to be inlined for performance reasons.
func (pr *Reader) TryReadBits(nb uint) (uint, bool) {
if pr.numBits < nb {
return 0, false
}
val := uint(pr.bufBits & uint64(1<>= nb
pr.numBits -= nb
return val, true
}
// ReadBits reads nb bits in from the underlying reader.
func (pr *Reader) ReadBits(nb uint) uint {
if err := pr.PullBits(nb); err != nil {
errors.Panic(err)
}
val := uint(pr.bufBits & uint64(1<>= nb
pr.numBits -= nb
return val
}
// TryReadSymbol attempts to decode the next symbol using the contents of the
// bit buffer alone. It returns the decoded symbol and whether it succeeded.
//
// This method is designed to be inlined for performance reasons.
func (pr *Reader) TryReadSymbol(pd *Decoder) (uint, bool) {
if pr.numBits < uint(pd.MinBits) || len(pd.chunks) == 0 {
return 0, false
}
chunk := pd.chunks[uint32(pr.bufBits)&pd.chunkMask]
nb := uint(chunk & countMask)
if nb > pr.numBits || nb > uint(pd.chunkBits) {
return 0, false
}
pr.bufBits >>= nb
pr.numBits -= nb
return uint(chunk >> countBits), true
}
// ReadSymbol reads the next symbol using the provided prefix Decoder.
func (pr *Reader) ReadSymbol(pd *Decoder) uint {
if len(pd.chunks) == 0 {
panicf(errors.Invalid, "decode with empty prefix tree")
}
nb := uint(pd.MinBits)
for {
if err := pr.PullBits(nb); err != nil {
errors.Panic(err)
}
chunk := pd.chunks[uint32(pr.bufBits)&pd.chunkMask]
nb = uint(chunk & countMask)
if nb > uint(pd.chunkBits) {
linkIdx := chunk >> countBits
chunk = pd.links[linkIdx][uint32(pr.bufBits>>pd.chunkBits)&pd.linkMask]
nb = uint(chunk & countMask)
}
if nb <= pr.numBits {
pr.bufBits >>= nb
pr.numBits -= nb
return uint(chunk >> countBits)
}
}
}
// Flush updates the read offset of the underlying ByteReader.
// If reader is a compress.BufferedReader, then this calls Discard to update
// the read offset.
func (pr *Reader) Flush() (int64, error) {
if pr.bufRd == nil {
return pr.Offset, nil
}
// Update the number of total bits to discard.
pr.discardBits += int(pr.fedBits - pr.numBits)
pr.fedBits = pr.numBits
// Discard some bytes to update read offset.
var err error
nd := (pr.discardBits + 7) / 8 // Round up to nearest byte
nd, err = pr.bufRd.Discard(nd)
pr.discardBits -= nd * 8 // -7..0
pr.Offset += int64(nd)
// These are invalid after Discard.
pr.bufPeek = nil
return pr.Offset, err
}
// PullBits ensures that at least nb bits exist in the bit buffer.
// If the underlying reader is a compress.BufferedReader, then this will fill
// the bit buffer with as many bits as possible, relying on Peek and Discard to
// properly advance the read offset. Otherwise, it will use ReadByte to fill the
// buffer with just the right number of bits.
func (pr *Reader) PullBits(nb uint) error {
if pr.bufRd != nil {
pr.discardBits += int(pr.fedBits - pr.numBits)
for {
if len(pr.bufPeek) == 0 {
pr.fedBits = pr.numBits // Don't discard bits just added
if _, err := pr.Flush(); err != nil {
return err
}
// Peek no more bytes than necessary.
// The computation for cntPeek computes the minimum number of
// bytes to Peek to fill nb bits.
var err error
cntPeek := int(nb+(-nb&7)) / 8
if cntPeek < pr.bufRd.Buffered() {
cntPeek = pr.bufRd.Buffered()
}
pr.bufPeek, err = pr.bufRd.Peek(cntPeek)
pr.bufPeek = pr.bufPeek[int(pr.numBits/8):] // Skip buffered bits
if len(pr.bufPeek) == 0 {
if pr.numBits >= nb {
break
}
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
}
n := int(64-pr.numBits) / 8 // Number of bytes to copy to bit buffer
if len(pr.bufPeek) >= 8 {
// Starting with Go 1.7, the compiler should use a wide integer
// load here if the architecture supports it.
u := binary.LittleEndian.Uint64(pr.bufPeek)
if pr.bigEndian {
// Swap all the bits within each byte.
u = (u&0xaaaaaaaaaaaaaaaa)>>1 | (u&0x5555555555555555)<<1
u = (u&0xcccccccccccccccc)>>2 | (u&0x3333333333333333)<<2
u = (u&0xf0f0f0f0f0f0f0f0)>>4 | (u&0x0f0f0f0f0f0f0f0f)<<4
}
pr.bufBits |= u << pr.numBits
pr.numBits += uint(n * 8)
pr.bufPeek = pr.bufPeek[n:]
break
} else {
if n > len(pr.bufPeek) {
n = len(pr.bufPeek)
}
for _, c := range pr.bufPeek[:n] {
if pr.bigEndian {
c = internal.ReverseLUT[c]
}
pr.bufBits |= uint64(c) << pr.numBits
pr.numBits += 8
}
pr.bufPeek = pr.bufPeek[n:]
if pr.numBits > 56 {
break
}
}
}
pr.fedBits = pr.numBits
} else {
for pr.numBits < nb {
c, err := pr.byteRd.ReadByte()
if err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
if pr.bigEndian {
c = internal.ReverseLUT[c]
}
pr.bufBits |= uint64(c) << pr.numBits
pr.numBits += 8
pr.Offset++
}
}
return nil
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/wrap.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
import (
"bytes"
"io"
"strings"
)
// For some of the common Readers, we wrap and extend them to satisfy the
// compress.BufferedReader interface to improve performance.
type buffer struct {
*bytes.Buffer
}
type bytesReader struct {
*bytes.Reader
pos int64
buf []byte
arr [512]byte
}
type stringReader struct {
*strings.Reader
pos int64
buf []byte
arr [512]byte
}
func (r *buffer) Buffered() int {
return r.Len()
}
func (r *buffer) Peek(n int) ([]byte, error) {
b := r.Bytes()
if len(b) < n {
return b, io.EOF
}
return b[:n], nil
}
func (r *buffer) Discard(n int) (int, error) {
b := r.Next(n)
if len(b) < n {
return len(b), io.EOF
}
return n, nil
}
func (r *bytesReader) Buffered() int {
r.update()
if r.Len() > len(r.buf) {
return len(r.buf)
}
return r.Len()
}
func (r *bytesReader) Peek(n int) ([]byte, error) {
if n > len(r.arr) {
return nil, io.ErrShortBuffer
}
// Return sub-slice of local buffer if possible.
r.update()
if len(r.buf) >= n {
return r.buf[:n], nil
}
// Fill entire local buffer, and return appropriate sub-slice.
cnt, err := r.ReadAt(r.arr[:], r.pos)
r.buf = r.arr[:cnt]
if cnt < n {
return r.arr[:cnt], err
}
return r.arr[:n], nil
}
func (r *bytesReader) Discard(n int) (int, error) {
var err error
if n > r.Len() {
n, err = r.Len(), io.EOF
}
r.Seek(int64(n), io.SeekCurrent)
return n, err
}
// update reslices the internal buffer to be consistent with the read offset.
func (r *bytesReader) update() {
pos, _ := r.Seek(0, io.SeekCurrent)
if off := pos - r.pos; off >= 0 && off < int64(len(r.buf)) {
r.buf, r.pos = r.buf[off:], pos
} else {
r.buf, r.pos = nil, pos
}
}
func (r *stringReader) Buffered() int {
r.update()
if r.Len() > len(r.buf) {
return len(r.buf)
}
return r.Len()
}
func (r *stringReader) Peek(n int) ([]byte, error) {
if n > len(r.arr) {
return nil, io.ErrShortBuffer
}
// Return sub-slice of local buffer if possible.
r.update()
if len(r.buf) >= n {
return r.buf[:n], nil
}
// Fill entire local buffer, and return appropriate sub-slice.
cnt, err := r.ReadAt(r.arr[:], r.pos)
r.buf = r.arr[:cnt]
if cnt < n {
return r.arr[:cnt], err
}
return r.arr[:n], nil
}
func (r *stringReader) Discard(n int) (int, error) {
var err error
if n > r.Len() {
n, err = r.Len(), io.EOF
}
r.Seek(int64(n), io.SeekCurrent)
return n, err
}
// update reslices the internal buffer to be consistent with the read offset.
func (r *stringReader) update() {
pos, _ := r.Seek(0, io.SeekCurrent)
if off := pos - r.pos; off >= 0 && off < int64(len(r.buf)) {
r.buf, r.pos = r.buf[off:], pos
} else {
r.buf, r.pos = nil, pos
}
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/prefix/writer.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
package prefix
import (
"encoding/binary"
"io"
"github.com/dsnet/compress/internal/errors"
)
// Writer implements a prefix encoder. For performance reasons, Writer will not
// write bytes immediately to the underlying stream.
type Writer struct {
Offset int64 // Number of bytes written to the underlying io.Writer
wr io.Writer
bufBits uint64 // Buffer to hold some bits
numBits uint // Number of valid bits in bufBits
bigEndian bool // Are bits written in big-endian order?
buf [512]byte
cntBuf int
}
// Init initializes the bit Writer to write to w. If bigEndian is true, then
// bits will be written starting from the most-significant bits of a byte
// (as done in bzip2), otherwise it will write starting from the
// least-significant bits of a byte (such as for deflate and brotli).
func (pw *Writer) Init(w io.Writer, bigEndian bool) {
*pw = Writer{wr: w, bigEndian: bigEndian}
return
}
// BitsWritten reports the total number of bits issued to any Write method.
func (pw *Writer) BitsWritten() int64 {
return 8*pw.Offset + 8*int64(pw.cntBuf) + int64(pw.numBits)
}
// WritePads writes 0-7 bits to the bit buffer to achieve byte-alignment.
func (pw *Writer) WritePads(v uint) {
nb := -pw.numBits & 7
pw.bufBits |= uint64(v) << pw.numBits
pw.numBits += nb
}
// Write writes bytes from buf.
// The bit-ordering mode does not affect this method.
func (pw *Writer) Write(buf []byte) (cnt int, err error) {
if pw.numBits > 0 || pw.cntBuf > 0 {
if pw.numBits%8 != 0 {
return 0, errorf(errors.Invalid, "non-aligned bit buffer")
}
if _, err := pw.Flush(); err != nil {
return 0, err
}
}
cnt, err = pw.wr.Write(buf)
pw.Offset += int64(cnt)
return cnt, err
}
// WriteOffset writes ofs in a (sym, extra) fashion using the provided prefix
// Encoder and RangeEncoder.
func (pw *Writer) WriteOffset(ofs uint, pe *Encoder, re *RangeEncoder) {
sym := re.Encode(ofs)
pw.WriteSymbol(sym, pe)
rc := re.rcs[sym]
pw.WriteBits(ofs-uint(rc.Base), uint(rc.Len))
}
// TryWriteBits attempts to write nb bits using the contents of the bit buffer
// alone. It reports whether it succeeded.
//
// This method is designed to be inlined for performance reasons.
func (pw *Writer) TryWriteBits(v, nb uint) bool {
if 64-pw.numBits < nb {
return false
}
pw.bufBits |= uint64(v) << pw.numBits
pw.numBits += nb
return true
}
// WriteBits writes nb bits of v to the underlying writer.
func (pw *Writer) WriteBits(v, nb uint) {
if _, err := pw.PushBits(); err != nil {
errors.Panic(err)
}
pw.bufBits |= uint64(v) << pw.numBits
pw.numBits += nb
}
// TryWriteSymbol attempts to encode the next symbol using the contents of the
// bit buffer alone. It reports whether it succeeded.
//
// This method is designed to be inlined for performance reasons.
func (pw *Writer) TryWriteSymbol(sym uint, pe *Encoder) bool {
chunk := pe.chunks[uint32(sym)&pe.chunkMask]
nb := uint(chunk & countMask)
if 64-pw.numBits < nb {
return false
}
pw.bufBits |= uint64(chunk>>countBits) << pw.numBits
pw.numBits += nb
return true
}
// WriteSymbol writes the symbol using the provided prefix Encoder.
func (pw *Writer) WriteSymbol(sym uint, pe *Encoder) {
if _, err := pw.PushBits(); err != nil {
errors.Panic(err)
}
chunk := pe.chunks[uint32(sym)&pe.chunkMask]
nb := uint(chunk & countMask)
pw.bufBits |= uint64(chunk>>countBits) << pw.numBits
pw.numBits += nb
}
// Flush flushes all complete bytes from the bit buffer to the byte buffer, and
// then flushes all bytes in the byte buffer to the underlying writer.
// After this call, the bit Writer is will only withhold 7 bits at most.
func (pw *Writer) Flush() (int64, error) {
if pw.numBits < 8 && pw.cntBuf == 0 {
return pw.Offset, nil
}
if _, err := pw.PushBits(); err != nil {
return pw.Offset, err
}
cnt, err := pw.wr.Write(pw.buf[:pw.cntBuf])
pw.cntBuf -= cnt
pw.Offset += int64(cnt)
return pw.Offset, err
}
// PushBits pushes as many bytes as possible from the bit buffer to the byte
// buffer, reporting the number of bits pushed.
func (pw *Writer) PushBits() (uint, error) {
if pw.cntBuf >= len(pw.buf)-8 {
cnt, err := pw.wr.Write(pw.buf[:pw.cntBuf])
pw.cntBuf -= cnt
pw.Offset += int64(cnt)
if err != nil {
return 0, err
}
}
u := pw.bufBits
if pw.bigEndian {
// Swap all the bits within each byte.
u = (u&0xaaaaaaaaaaaaaaaa)>>1 | (u&0x5555555555555555)<<1
u = (u&0xcccccccccccccccc)>>2 | (u&0x3333333333333333)<<2
u = (u&0xf0f0f0f0f0f0f0f0)>>4 | (u&0x0f0f0f0f0f0f0f0f)<<4
}
// Starting with Go 1.7, the compiler should use a wide integer
// store here if the architecture supports it.
binary.LittleEndian.PutUint64(pw.buf[pw.cntBuf:], u)
nb := pw.numBits / 8 // Number of bytes to copy from bit buffer
pw.cntBuf += int(nb)
pw.bufBits >>= 8 * nb
pw.numBits -= 8 * nb
return 8 * nb, nil
}
================================================
FILE: vendor/github.com/dsnet/compress/internal/release.go
================================================
// Copyright 2015, Joe Tsai. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE.md file.
// +build !debug,!gofuzz
package internal
// Debug indicates whether the debug build tag was set.
//
// If set, programs may choose to print with more human-readable
// debug information and also perform sanity checks that would otherwise be too
// expensive to run in a release build.
const Debug = false
// GoFuzz indicates whether the gofuzz build tag was set.
//
// If set, programs may choose to disable certain checks (like checksums) that
// would be nearly impossible for gofuzz to properly get right.
// If GoFuzz is set, it implies that Debug is set as well.
const GoFuzz = false
================================================
FILE: vendor/github.com/dsnet/compress/zbench.sh
================================================
#!/bin/bash
#
# Copyright 2017, Joe Tsai. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE.md file.
# zbench wraps internal/tool/bench and is useful for comparing benchmarks from
# the implementations in this repository relative to other implementations.
#
# See internal/tool/bench/main.go for more details.
cd $(dirname "${BASH_SOURCE[0]}")/internal/tool/bench
go run $(go list -f '{{ join .GoFiles "\n" }}') "$@"
================================================
FILE: vendor/github.com/dsnet/compress/zfuzz.sh
================================================
#!/bin/bash
#
# Copyright 2017, Joe Tsai. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE.md file.
# zfuzz wraps internal/tool/fuzz and is useful for fuzz testing each of
# the implementations in this repository.
cd $(dirname "${BASH_SOURCE[0]}")/internal/tool/fuzz
./fuzz.sh "$@"
================================================
FILE: vendor/github.com/dsnet/compress/zprof.sh
================================================
#!/bin/bash
#
# Copyright 2017, Joe Tsai. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE.md file.
if [ $# == 0 ]; then
echo "Usage: $0 PKG_PATH TEST_ARGS..."
echo ""
echo "Runs coverage and performance benchmarks for a given package."
echo "The results are stored in the _zprof_ directory."
echo ""
echo "Example:"
echo " $0 flate -test.bench=Decode/Twain/Default"
exit 1
fi
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PKG_PATH=$1
PKG_NAME=$(basename $PKG_PATH)
shift
TMPDIR=$(mktemp -d)
trap "rm -rf $TMPDIR $PKG_PATH/$PKG_NAME.test" SIGINT SIGTERM EXIT
(
cd $DIR/$PKG_PATH
# Print the go version.
go version
# Perform coverage profiling.
go test github.com/dsnet/compress/$PKG_PATH -coverprofile $TMPDIR/cover.profile
if [ $? != 0 ]; then exit 1; fi
go tool cover -html $TMPDIR/cover.profile -o cover.html
# Perform performance profiling.
if [ $# != 0 ]; then
go test -c github.com/dsnet/compress/$PKG_PATH
if [ $? != 0 ]; then exit 1; fi
./$PKG_NAME.test -test.cpuprofile $TMPDIR/cpu.profile -test.memprofile $TMPDIR/mem.profile -test.run - "$@"
PPROF="go tool pprof"
$PPROF -output=cpu.svg -web $PKG_NAME.test $TMPDIR/cpu.profile 2> /dev/null
$PPROF -output=cpu.html -weblist=. $PKG_NAME.test $TMPDIR/cpu.profile 2> /dev/null
$PPROF -output=mem_objects.svg -alloc_objects -web $PKG_NAME.test $TMPDIR/mem.profile 2> /dev/null
$PPROF -output=mem_objects.html -alloc_objects -weblist=. $PKG_NAME.test $TMPDIR/mem.profile 2> /dev/null
$PPROF -output=mem_space.svg -alloc_space -web $PKG_NAME.test $TMPDIR/mem.profile 2> /dev/null
$PPROF -output=mem_space.html -alloc_space -weblist=. $PKG_NAME.test $TMPDIR/mem.profile 2> /dev/null
fi
rm -rf $DIR/_zprof_/$PKG_NAME
mkdir -p $DIR/_zprof_/$PKG_NAME
mv *.html *.svg $DIR/_zprof_/$PKG_NAME 2> /dev/null
)
================================================
FILE: vendor/github.com/dsnet/compress/ztest.sh
================================================
#!/bin/bash
#
# Copyright 2017, Joe Tsai. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE.md file.
cd $(go list -f '{{ .Dir }}' github.com/dsnet/compress)
BOLD="\x1b[1mRunning: "
PASS="\x1b[32mPASS"
FAIL="\x1b[31mFAIL"
RESET="\x1b[0m"
echo -e "${BOLD}fmt${RESET}"
RET_FMT=$(find . -name "*.go" | egrep -v "/(_.*_|\..*|testdata)/" | xargs gofmt -d)
if [[ ! -z "$RET_FMT" ]]; then echo "$RET_FMT"; echo; fi
echo -e "${BOLD}test${RESET}"
RET_TEST=$(go test -race ./... | egrep -v "^(ok|[?])\s+")
if [[ ! -z "$RET_TEST" ]]; then echo "$RET_TEST"; echo; fi
echo -e "${BOLD}staticcheck${RESET}"
RET_SCHK=$(staticcheck \
-ignore "
github.com/dsnet/compress/brotli/*.go:SA4016
github.com/dsnet/compress/brotli/*.go:S1023
github.com/dsnet/compress/brotli/*.go:U1000
github.com/dsnet/compress/bzip2/*.go:S1023
github.com/dsnet/compress/flate/*.go:U1000
github.com/dsnet/compress/internal/cgo/lzma/*.go:SA4000
github.com/dsnet/compress/internal/prefix/*.go:S1004
github.com/dsnet/compress/internal/prefix/*.go:S1023
github.com/dsnet/compress/internal/prefix/*.go:SA4016
github.com/dsnet/compress/internal/tool/bench/*.go:S1007
github.com/dsnet/compress/xflate/internal/meta/*.go:S1023
" ./... 2>&1)
if [[ ! -z "$RET_SCHK" ]]; then echo "$RET_SCHK"; echo; fi
echo -e "${BOLD}lint${RESET}"
RET_LINT=$(golint ./... 2>&1 |
egrep -v "^vendor/" |
egrep -v "should have comment(.*)or be unexported" |
egrep -v "^(.*)type name will be used as(.*)by other packages" |
egrep -v "^brotli/transform.go:(.*)replace i [+]= 1 with i[+]{2}" |
egrep -v "^internal/prefix/prefix.go:(.*)replace symBits(.*) [-]= 1 with symBits(.*)[-]{2}" |
egrep -v "^xflate/common.go:(.*)NoCompression should be of the form" |
egrep -v "^exit status")
if [[ ! -z "$RET_LINT" ]]; then echo "$RET_LINT"; echo; fi
if [[ ! -z "$RET_FMT" ]] || [ ! -z "$RET_TEST" ] || [[ ! -z "$RET_SCHK" ]] || [[ ! -z "$RET_LINT" ]]; then
echo -e "${FAIL}${RESET}"; exit 1
else
echo -e "${PASS}${RESET}"; exit 0
fi
================================================
FILE: vendor/github.com/elliotchance/orderedmap/.editorconfig
================================================
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.go]
indent_style = tab
indent_size = 4
max_line_length = 80
================================================
FILE: vendor/github.com/elliotchance/orderedmap/.gitignore
================================================
/.idea
================================================
FILE: vendor/github.com/elliotchance/orderedmap/LICENSE
================================================
MIT License
Copyright (c) 2020 Elliot Chance
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: vendor/github.com/elliotchance/orderedmap/README.md
================================================
# 🔃 github.com/elliotchance/orderedmap/v2 [](https://godoc.org/github.com/elliotchance/orderedmap/v2)
## Basic Usage
An `*OrderedMap` is a high performance ordered map that maintains amortized O(1)
for `Set`, `Get`, `Delete` and `Len`:
```go
import "github.com/elliotchance/orderedmap/v2"
func main() {
m := orderedmap.NewOrderedMap[string, any]()
m.Set("foo", "bar")
m.Set("qux", 1.23)
m.Set("123", true)
m.Delete("qux")
}
```
*Note: v2 requires Go v1.18 for generics.* If you need to support Go 1.17 or
below, you can use v1.
Internally an `*OrderedMap` uses the composite type
[map](https://go.dev/blog/maps) combined with a
trimmed down linked list to maintain the order.
## Iterating
Be careful using `Keys()` as it will create a copy of all of the keys so it's
only suitable for a small number of items:
```go
for _, key := range m.Keys() {
value, _:= m.Get(key)
fmt.Println(key, value)
}
```
For larger maps you should use `Front()` or `Back()` to iterate per element:
```go
// Iterate through all elements from oldest to newest:
for el := m.Front(); el != nil; el = el.Next() {
fmt.Println(el.Key, el.Value)
}
// You can also use Back and Prev to iterate in reverse:
for el := m.Back(); el != nil; el = el.Prev() {
fmt.Println(el.Key, el.Value)
}
```
The iterator is safe to use bidirectionally, and will return `nil` once it goes
beyond the first or last item.
If the map is changing while the iteration is in-flight it may produce
unexpected behavior.
================================================
FILE: vendor/github.com/elliotchance/orderedmap/list.go
================================================
package orderedmap
// Element is an element of a null terminated (non circular) intrusive doubly linked list that contains the key of the correspondent element in the ordered map too.
type Element struct {
// Next and previous pointers in the doubly-linked list of elements.
// To simplify the implementation, internally a list l is implemented
// as a ring, such that &l.root is both the next element of the last
// list element (l.Back()) and the previous element of the first list
// element (l.Front()).
next, prev *Element
// The key that corresponds to this element in the ordered map.
Key interface{}
// The value stored with this element.
Value interface{}
}
// Next returns the next list element or nil.
func (e *Element) Next() *Element {
return e.next
}
// Prev returns the previous list element or nil.
func (e *Element) Prev() *Element {
return e.prev
}
// list represents a null terminated (non circular) intrusive doubly linked list.
// The list is immediately usable after instantiation without the need of a dedicated initialization.
type list struct {
root Element // list head and tail
}
func (l *list) IsEmpty() bool {
return l.root.next == nil
}
// Front returns the first element of list l or nil if the list is empty.
func (l *list) Front() *Element {
return l.root.next
}
// Back returns the last element of list l or nil if the list is empty.
func (l *list) Back() *Element {
return l.root.prev
}
// Remove removes e from its list
func (l *list) Remove(e *Element) {
if e.prev == nil {
l.root.next = e.next
} else {
e.prev.next = e.next
}
if e.next == nil {
l.root.prev = e.prev
} else {
e.next.prev = e.prev
}
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
}
// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *list) PushFront(key interface{}, value interface{}) *Element {
e := &Element{Key: key, Value: value}
if l.root.next == nil {
// It's the first element
l.root.next = e
l.root.prev = e
return e
}
e.next = l.root.next
l.root.next.prev = e
l.root.next = e
return e
}
// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *list) PushBack(key interface{}, value interface{}) *Element {
e := &Element{Key: key, Value: value}
if l.root.prev == nil {
// It's the first element
l.root.next = e
l.root.prev = e
return e
}
e.prev = l.root.prev
l.root.prev.next = e
l.root.prev = e
return e
}
================================================
FILE: vendor/github.com/elliotchance/orderedmap/orderedmap.go
================================================
package orderedmap
type OrderedMap struct {
kv map[interface{}]*Element
ll list
}
func NewOrderedMap() *OrderedMap {
return &OrderedMap{
kv: make(map[interface{}]*Element),
}
}
// Get returns the value for a key. If the key does not exist, the second return
// parameter will be false and the value will be nil.
func (m *OrderedMap) Get(key interface{}) (interface{}, bool) {
element, ok := m.kv[key]
if ok {
return element.Value, true
}
return nil, false
}
// Set will set (or replace) a value for a key. If the key was new, then true
// will be returned. The returned value will be false if the value was replaced
// (even if the value was the same).
func (m *OrderedMap) Set(key, value interface{}) bool {
_, alreadyExist := m.kv[key]
if alreadyExist {
m.kv[key].Value = value
return false
}
element := m.ll.PushBack(key, value)
m.kv[key] = element
return true
}
// GetOrDefault returns the value for a key. If the key does not exist, returns
// the default value instead.
func (m *OrderedMap) GetOrDefault(key, defaultValue interface{}) interface{} {
if element, ok := m.kv[key]; ok {
return element.Value
}
return defaultValue
}
// GetElement returns the element for a key. If the key does not exist, the
// pointer will be nil.
func (m *OrderedMap) GetElement(key interface{}) *Element {
element, ok := m.kv[key]
if ok {
return element
}
return nil
}
// Len returns the number of elements in the map.
func (m *OrderedMap) Len() int {
return len(m.kv)
}
// Keys returns all of the keys in the order they were inserted. If a key was
// replaced it will retain the same position. To ensure most recently set keys
// are always at the end you must always Delete before Set.
func (m *OrderedMap) Keys() (keys []interface{}) {
keys = make([]interface{}, 0, m.Len())
for el := m.Front(); el != nil; el = el.Next() {
keys = append(keys, el.Key)
}
return keys
}
// Delete will remove a key from the map. It will return true if the key was
// removed (the key did exist).
func (m *OrderedMap) Delete(key interface{}) (didDelete bool) {
element, ok := m.kv[key]
if ok {
m.ll.Remove(element)
delete(m.kv, key)
}
return ok
}
// Front will return the element that is the first (oldest Set element). If
// there are no elements this will return nil.
func (m *OrderedMap) Front() *Element {
return m.ll.Front()
}
// Back will return the element that is the last (most recent Set element). If
// there are no elements this will return nil.
func (m *OrderedMap) Back() *Element {
return m.ll.Back()
}
// Copy returns a new OrderedMap with the same elements.
// Using Copy while there are concurrent writes may mangle the result.
func (m *OrderedMap) Copy() *OrderedMap {
m2 := NewOrderedMap()
for el := m.Front(); el != nil; el = el.Next() {
m2.Set(el.Key, el.Value)
}
return m2
}
================================================
FILE: vendor/github.com/emirpasic/gods/LICENSE
================================================
Copyright (c) 2015, Emir Pasic
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-------------------------------------------------------------------------------
AVL Tree:
Copyright (c) 2017 Benjamin Scher Purcell
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
================================================
FILE: vendor/github.com/emirpasic/gods/containers/containers.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package containers provides core interfaces and functions for data structures.
//
// Container is the base interface for all data structures to implement.
//
// Iterators provide stateful iterators.
//
// Enumerable provides Ruby inspired (each, select, map, find, any?, etc.) container functions.
//
// Serialization provides serializers (marshalers) and deserializers (unmarshalers).
package containers
import "github.com/emirpasic/gods/utils"
// Container is base interface that all data structures implement.
type Container interface {
Empty() bool
Size() int
Clear()
Values() []interface{}
String() string
}
// GetSortedValues returns sorted container's elements with respect to the passed comparator.
// Does not affect the ordering of elements within the container.
func GetSortedValues(container Container, comparator utils.Comparator) []interface{} {
values := container.Values()
if len(values) < 2 {
return values
}
utils.Sort(values, comparator)
return values
}
================================================
FILE: vendor/github.com/emirpasic/gods/containers/enumerable.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package containers
// EnumerableWithIndex provides functions for ordered containers whose values can be fetched by an index.
type EnumerableWithIndex interface {
// Each calls the given function once for each element, passing that element's index and value.
Each(func(index int, value interface{}))
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
// Map(func(index int, value interface{}) interface{}) Container
// Select returns a new container containing all elements for which the given function returns a true value.
// Select(func(index int, value interface{}) bool) Container
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
Any(func(index int, value interface{}) bool) bool
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
All(func(index int, value interface{}) bool) bool
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
Find(func(index int, value interface{}) bool) (int, interface{})
}
// EnumerableWithKey provides functions for ordered containers whose values whose elements are key/value pairs.
type EnumerableWithKey interface {
// Each calls the given function once for each element, passing that element's key and value.
Each(func(key interface{}, value interface{}))
// Map invokes the given function once for each element and returns a container
// containing the values returned by the given function as key/value pairs.
// Map(func(key interface{}, value interface{}) (interface{}, interface{})) Container
// Select returns a new container containing all elements for which the given function returns a true value.
// Select(func(key interface{}, value interface{}) bool) Container
// Any passes each element of the container to the given function and
// returns true if the function ever returns true for any element.
Any(func(key interface{}, value interface{}) bool) bool
// All passes each element of the container to the given function and
// returns true if the function returns true for all elements.
All(func(key interface{}, value interface{}) bool) bool
// Find passes each element of the container to the given function and returns
// the first (key,value) for which the function is true or nil,nil otherwise if no element
// matches the criteria.
Find(func(key interface{}, value interface{}) bool) (interface{}, interface{})
}
================================================
FILE: vendor/github.com/emirpasic/gods/containers/iterator.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package containers
// IteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
type IteratorWithIndex interface {
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
Next() bool
// Value returns the current element's value.
// Does not modify the state of the iterator.
Value() interface{}
// Index returns the current element's index.
// Does not modify the state of the iterator.
Index() int
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
Begin()
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
First() bool
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
NextTo(func(index int, value interface{}) bool) bool
}
// IteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
type IteratorWithKey interface {
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
Next() bool
// Value returns the current element's value.
// Does not modify the state of the iterator.
Value() interface{}
// Key returns the current element's key.
// Does not modify the state of the iterator.
Key() interface{}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
Begin()
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
First() bool
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
NextTo(func(key interface{}, value interface{}) bool) bool
}
// ReverseIteratorWithIndex is stateful iterator for ordered containers whose values can be fetched by an index.
//
// Essentially it is the same as IteratorWithIndex, but provides additional:
//
// Prev() function to enable traversal in reverse
//
// Last() function to move the iterator to the last element.
//
// End() function to move the iterator past the last element (one-past-the-end).
type ReverseIteratorWithIndex interface {
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
Prev() bool
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
End()
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
Last() bool
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
PrevTo(func(index int, value interface{}) bool) bool
IteratorWithIndex
}
// ReverseIteratorWithKey is a stateful iterator for ordered containers whose elements are key value pairs.
//
// Essentially it is the same as IteratorWithKey, but provides additional:
//
// Prev() function to enable traversal in reverse
//
// Last() function to move the iterator to the last element.
type ReverseIteratorWithKey interface {
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
Prev() bool
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
End()
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
Last() bool
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
// Modifies the state of the iterator.
PrevTo(func(key interface{}, value interface{}) bool) bool
IteratorWithKey
}
================================================
FILE: vendor/github.com/emirpasic/gods/containers/serialization.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package containers
// JSONSerializer provides JSON serialization
type JSONSerializer interface {
// ToJSON outputs the JSON representation of containers's elements.
ToJSON() ([]byte, error)
// MarshalJSON @implements json.Marshaler
MarshalJSON() ([]byte, error)
}
// JSONDeserializer provides JSON deserialization
type JSONDeserializer interface {
// FromJSON populates containers's elements from the input JSON representation.
FromJSON([]byte) error
// UnmarshalJSON @implements json.Unmarshaler
UnmarshalJSON([]byte) error
}
================================================
FILE: vendor/github.com/emirpasic/gods/lists/arraylist/arraylist.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package arraylist implements the array list.
//
// Structure is not thread safe.
//
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
package arraylist
import (
"fmt"
"strings"
"github.com/emirpasic/gods/lists"
"github.com/emirpasic/gods/utils"
)
// Assert List implementation
var _ lists.List = (*List)(nil)
// List holds the elements in a slice
type List struct {
elements []interface{}
size int
}
const (
growthFactor = float32(2.0) // growth by 100%
shrinkFactor = float32(0.25) // shrink when size is 25% of capacity (0 means never shrink)
)
// New instantiates a new list and adds the passed values, if any, to the list
func New(values ...interface{}) *List {
list := &List{}
if len(values) > 0 {
list.Add(values...)
}
return list
}
// Add appends a value at the end of the list
func (list *List) Add(values ...interface{}) {
list.growBy(len(values))
for _, value := range values {
list.elements[list.size] = value
list.size++
}
}
// Get returns the element at index.
// Second return parameter is true if index is within bounds of the array and array is not empty, otherwise false.
func (list *List) Get(index int) (interface{}, bool) {
if !list.withinRange(index) {
return nil, false
}
return list.elements[index], true
}
// Remove removes the element at the given index from the list.
func (list *List) Remove(index int) {
if !list.withinRange(index) {
return
}
list.elements[index] = nil // cleanup reference
copy(list.elements[index:], list.elements[index+1:list.size]) // shift to the left by one (slow operation, need ways to optimize this)
list.size--
list.shrink()
}
// Contains checks if elements (one or more) are present in the set.
// All elements have to be present in the set for the method to return true.
// Performance time complexity of n^2.
// Returns true if no arguments are passed at all, i.e. set is always super-set of empty set.
func (list *List) Contains(values ...interface{}) bool {
for _, searchValue := range values {
found := false
for index := 0; index < list.size; index++ {
if list.elements[index] == searchValue {
found = true
break
}
}
if !found {
return false
}
}
return true
}
// Values returns all elements in the list.
func (list *List) Values() []interface{} {
newElements := make([]interface{}, list.size, list.size)
copy(newElements, list.elements[:list.size])
return newElements
}
//IndexOf returns index of provided element
func (list *List) IndexOf(value interface{}) int {
if list.size == 0 {
return -1
}
for index, element := range list.elements {
if element == value {
return index
}
}
return -1
}
// Empty returns true if list does not contain any elements.
func (list *List) Empty() bool {
return list.size == 0
}
// Size returns number of elements within the list.
func (list *List) Size() int {
return list.size
}
// Clear removes all elements from the list.
func (list *List) Clear() {
list.size = 0
list.elements = []interface{}{}
}
// Sort sorts values (in-place) using.
func (list *List) Sort(comparator utils.Comparator) {
if len(list.elements) < 2 {
return
}
utils.Sort(list.elements[:list.size], comparator)
}
// Swap swaps the two values at the specified positions.
func (list *List) Swap(i, j int) {
if list.withinRange(i) && list.withinRange(j) {
list.elements[i], list.elements[j] = list.elements[j], list.elements[i]
}
}
// Insert inserts values at specified index position shifting the value at that position (if any) and any subsequent elements to the right.
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Insert(index int, values ...interface{}) {
if !list.withinRange(index) {
// Append
if index == list.size {
list.Add(values...)
}
return
}
l := len(values)
list.growBy(l)
list.size += l
copy(list.elements[index+l:], list.elements[index:list.size-l])
copy(list.elements[index:], values)
}
// Set the value at specified index
// Does not do anything if position is negative or bigger than list's size
// Note: position equal to list's size is valid, i.e. append.
func (list *List) Set(index int, value interface{}) {
if !list.withinRange(index) {
// Append
if index == list.size {
list.Add(value)
}
return
}
list.elements[index] = value
}
// String returns a string representation of container
func (list *List) String() string {
str := "ArrayList\n"
values := []string{}
for _, value := range list.elements[:list.size] {
values = append(values, fmt.Sprintf("%v", value))
}
str += strings.Join(values, ", ")
return str
}
// Check that the index is within bounds of the list
func (list *List) withinRange(index int) bool {
return index >= 0 && index < list.size
}
func (list *List) resize(cap int) {
newElements := make([]interface{}, cap, cap)
copy(newElements, list.elements)
list.elements = newElements
}
// Expand the array if necessary, i.e. capacity will be reached if we add n elements
func (list *List) growBy(n int) {
// When capacity is reached, grow by a factor of growthFactor and add number of elements
currentCapacity := cap(list.elements)
if list.size+n >= currentCapacity {
newCapacity := int(growthFactor * float32(currentCapacity+n))
list.resize(newCapacity)
}
}
// Shrink the array if necessary, i.e. when size is shrinkFactor percent of current capacity
func (list *List) shrink() {
if shrinkFactor == 0.0 {
return
}
// Shrink when size is at shrinkFactor * capacity
currentCapacity := cap(list.elements)
if list.size <= int(float32(currentCapacity)*shrinkFactor) {
list.resize(list.size)
}
}
================================================
FILE: vendor/github.com/emirpasic/gods/lists/arraylist/enumerable.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package arraylist
import "github.com/emirpasic/gods/containers"
// Assert Enumerable implementation
var _ containers.EnumerableWithIndex = (*List)(nil)
// Each calls the given function once for each element, passing that element's index and value.
func (list *List) Each(f func(index int, value interface{})) {
iterator := list.Iterator()
for iterator.Next() {
f(iterator.Index(), iterator.Value())
}
}
// Map invokes the given function once for each element and returns a
// container containing the values returned by the given function.
func (list *List) Map(f func(index int, value interface{}) interface{}) *List {
newList := &List{}
iterator := list.Iterator()
for iterator.Next() {
newList.Add(f(iterator.Index(), iterator.Value()))
}
return newList
}
// Select returns a new container containing all elements for which the given function returns a true value.
func (list *List) Select(f func(index int, value interface{}) bool) *List {
newList := &List{}
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
newList.Add(iterator.Value())
}
}
return newList
}
// Any passes each element of the collection to the given function and
// returns true if the function ever returns true for any element.
func (list *List) Any(f func(index int, value interface{}) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return true
}
}
return false
}
// All passes each element of the collection to the given function and
// returns true if the function returns true for all elements.
func (list *List) All(f func(index int, value interface{}) bool) bool {
iterator := list.Iterator()
for iterator.Next() {
if !f(iterator.Index(), iterator.Value()) {
return false
}
}
return true
}
// Find passes each element of the container to the given function and returns
// the first (index,value) for which the function is true or -1,nil otherwise
// if no element matches the criteria.
func (list *List) Find(f func(index int, value interface{}) bool) (int, interface{}) {
iterator := list.Iterator()
for iterator.Next() {
if f(iterator.Index(), iterator.Value()) {
return iterator.Index(), iterator.Value()
}
}
return -1, nil
}
================================================
FILE: vendor/github.com/emirpasic/gods/lists/arraylist/iterator.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package arraylist
import "github.com/emirpasic/gods/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
// Iterator holding the iterator's state
type Iterator struct {
list *List
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (list *List) Iterator() Iterator {
return Iterator{list: list, index: -1}
}
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
func (iterator *Iterator) Next() bool {
if iterator.index < iterator.list.size {
iterator.index++
}
return iterator.list.withinRange(iterator.index)
}
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
return iterator.list.withinRange(iterator.index)
}
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
return iterator.list.elements[iterator.index]
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
iterator.index = -1
}
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
func (iterator *Iterator) End() {
iterator.index = iterator.list.size
}
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
iterator.Begin()
return iterator.Next()
}
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
iterator.End()
return iterator.Prev()
}
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
================================================
FILE: vendor/github.com/emirpasic/gods/lists/arraylist/serialization.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package arraylist
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*List)(nil)
var _ containers.JSONDeserializer = (*List)(nil)
// ToJSON outputs the JSON representation of list's elements.
func (list *List) ToJSON() ([]byte, error) {
return json.Marshal(list.elements[:list.size])
}
// FromJSON populates list's elements from the input JSON representation.
func (list *List) FromJSON(data []byte) error {
err := json.Unmarshal(data, &list.elements)
if err == nil {
list.size = len(list.elements)
}
return err
}
// UnmarshalJSON @implements json.Unmarshaler
func (list *List) UnmarshalJSON(bytes []byte) error {
return list.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (list *List) MarshalJSON() ([]byte, error) {
return list.ToJSON()
}
================================================
FILE: vendor/github.com/emirpasic/gods/lists/lists.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package lists provides an abstract List interface.
//
// In computer science, a list or sequence is an abstract data type that represents an ordered sequence of values, where the same value may occur more than once. An instance of a list is a computer representation of the mathematical concept of a finite sequence; the (potentially) infinite analog of a list is a stream. Lists are a basic example of containers, as they contain other values. If the same value occurs multiple times, each occurrence is considered a distinct item.
//
// Reference: https://en.wikipedia.org/wiki/List_%28abstract_data_type%29
package lists
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/utils"
)
// List interface that all lists implement
type List interface {
Get(index int) (interface{}, bool)
Remove(index int)
Add(values ...interface{})
Contains(values ...interface{}) bool
Sort(comparator utils.Comparator)
Swap(index1, index2 int)
Insert(index int, values ...interface{})
Set(index int, value interface{})
containers.Container
// Empty() bool
// Size() int
// Clear()
// Values() []interface{}
// String() string
}
================================================
FILE: vendor/github.com/emirpasic/gods/trees/binaryheap/binaryheap.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package binaryheap implements a binary heap backed by array list.
//
// Comparator defines this heap as either min or max heap.
//
// Structure is not thread safe.
//
// References: http://en.wikipedia.org/wiki/Binary_heap
package binaryheap
import (
"fmt"
"github.com/emirpasic/gods/lists/arraylist"
"github.com/emirpasic/gods/trees"
"github.com/emirpasic/gods/utils"
"strings"
)
// Assert Tree implementation
var _ trees.Tree = (*Heap)(nil)
// Heap holds elements in an array-list
type Heap struct {
list *arraylist.List
Comparator utils.Comparator
}
// NewWith instantiates a new empty heap tree with the custom comparator.
func NewWith(comparator utils.Comparator) *Heap {
return &Heap{list: arraylist.New(), Comparator: comparator}
}
// NewWithIntComparator instantiates a new empty heap with the IntComparator, i.e. elements are of type int.
func NewWithIntComparator() *Heap {
return &Heap{list: arraylist.New(), Comparator: utils.IntComparator}
}
// NewWithStringComparator instantiates a new empty heap with the StringComparator, i.e. elements are of type string.
func NewWithStringComparator() *Heap {
return &Heap{list: arraylist.New(), Comparator: utils.StringComparator}
}
// Push adds a value onto the heap and bubbles it up accordingly.
func (heap *Heap) Push(values ...interface{}) {
if len(values) == 1 {
heap.list.Add(values[0])
heap.bubbleUp()
} else {
// Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap
for _, value := range values {
heap.list.Add(value)
}
size := heap.list.Size()/2 + 1
for i := size; i >= 0; i-- {
heap.bubbleDownIndex(i)
}
}
}
// Pop removes top element on heap and returns it, or nil if heap is empty.
// Second return parameter is true, unless the heap was empty and there was nothing to pop.
func (heap *Heap) Pop() (value interface{}, ok bool) {
value, ok = heap.list.Get(0)
if !ok {
return
}
lastIndex := heap.list.Size() - 1
heap.list.Swap(0, lastIndex)
heap.list.Remove(lastIndex)
heap.bubbleDown()
return
}
// Peek returns top element on the heap without removing it, or nil if heap is empty.
// Second return parameter is true, unless the heap was empty and there was nothing to peek.
func (heap *Heap) Peek() (value interface{}, ok bool) {
return heap.list.Get(0)
}
// Empty returns true if heap does not contain any elements.
func (heap *Heap) Empty() bool {
return heap.list.Empty()
}
// Size returns number of elements within the heap.
func (heap *Heap) Size() int {
return heap.list.Size()
}
// Clear removes all elements from the heap.
func (heap *Heap) Clear() {
heap.list.Clear()
}
// Values returns all elements in the heap.
func (heap *Heap) Values() []interface{} {
values := make([]interface{}, heap.list.Size(), heap.list.Size())
for it := heap.Iterator(); it.Next(); {
values[it.Index()] = it.Value()
}
return values
}
// String returns a string representation of container
func (heap *Heap) String() string {
str := "BinaryHeap\n"
values := []string{}
for it := heap.Iterator(); it.Next(); {
values = append(values, fmt.Sprintf("%v", it.Value()))
}
str += strings.Join(values, ", ")
return str
}
// Performs the "bubble down" operation. This is to place the element that is at the root
// of the heap in its correct place so that the heap maintains the min/max-heap order property.
func (heap *Heap) bubbleDown() {
heap.bubbleDownIndex(0)
}
// Performs the "bubble down" operation. This is to place the element that is at the index
// of the heap in its correct place so that the heap maintains the min/max-heap order property.
func (heap *Heap) bubbleDownIndex(index int) {
size := heap.list.Size()
for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 {
rightIndex := index<<1 + 2
smallerIndex := leftIndex
leftValue, _ := heap.list.Get(leftIndex)
rightValue, _ := heap.list.Get(rightIndex)
if rightIndex < size && heap.Comparator(leftValue, rightValue) > 0 {
smallerIndex = rightIndex
}
indexValue, _ := heap.list.Get(index)
smallerValue, _ := heap.list.Get(smallerIndex)
if heap.Comparator(indexValue, smallerValue) > 0 {
heap.list.Swap(index, smallerIndex)
} else {
break
}
index = smallerIndex
}
}
// Performs the "bubble up" operation. This is to place a newly inserted
// element (i.e. last element in the list) in its correct place so that
// the heap maintains the min/max-heap order property.
func (heap *Heap) bubbleUp() {
index := heap.list.Size() - 1
for parentIndex := (index - 1) >> 1; index > 0; parentIndex = (index - 1) >> 1 {
indexValue, _ := heap.list.Get(index)
parentValue, _ := heap.list.Get(parentIndex)
if heap.Comparator(parentValue, indexValue) <= 0 {
break
}
heap.list.Swap(index, parentIndex)
index = parentIndex
}
}
// Check that the index is within bounds of the list
func (heap *Heap) withinRange(index int) bool {
return index >= 0 && index < heap.list.Size()
}
================================================
FILE: vendor/github.com/emirpasic/gods/trees/binaryheap/iterator.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package binaryheap
import (
"github.com/emirpasic/gods/containers"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
heap *Heap
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (heap *Heap) Iterator() Iterator {
return Iterator{heap: heap, index: -1}
}
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
func (iterator *Iterator) Next() bool {
if iterator.index < iterator.heap.Size() {
iterator.index++
}
return iterator.heap.withinRange(iterator.index)
}
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
return iterator.heap.withinRange(iterator.index)
}
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
start, end := evaluateRange(iterator.index)
if end > iterator.heap.Size() {
end = iterator.heap.Size()
}
tmpHeap := NewWith(iterator.heap.Comparator)
for n := start; n < end; n++ {
value, _ := iterator.heap.list.Get(n)
tmpHeap.Push(value)
}
for n := 0; n < iterator.index-start; n++ {
tmpHeap.Pop()
}
value, _ := tmpHeap.Pop()
return value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
iterator.index = -1
}
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
func (iterator *Iterator) End() {
iterator.index = iterator.heap.Size()
}
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
iterator.Begin()
return iterator.Next()
}
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
iterator.End()
return iterator.Prev()
}
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
// numOfBits counts the number of bits of an int
func numOfBits(n int) uint {
var count uint
for n != 0 {
count++
n >>= 1
}
return count
}
// evaluateRange evaluates the index range [start,end) of same level nodes in the heap as the index
func evaluateRange(index int) (start int, end int) {
bits := numOfBits(index+1) - 1
start = 1< b
type Comparator func(a, b interface{}) int
// StringComparator provides a fast comparison on strings
func StringComparator(a, b interface{}) int {
s1 := a.(string)
s2 := b.(string)
min := len(s2)
if len(s1) < len(s2) {
min = len(s1)
}
diff := 0
for i := 0; i < min && diff == 0; i++ {
diff = int(s1[i]) - int(s2[i])
}
if diff == 0 {
diff = len(s1) - len(s2)
}
if diff < 0 {
return -1
}
if diff > 0 {
return 1
}
return 0
}
// IntComparator provides a basic comparison on int
func IntComparator(a, b interface{}) int {
aAsserted := a.(int)
bAsserted := b.(int)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Int8Comparator provides a basic comparison on int8
func Int8Comparator(a, b interface{}) int {
aAsserted := a.(int8)
bAsserted := b.(int8)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Int16Comparator provides a basic comparison on int16
func Int16Comparator(a, b interface{}) int {
aAsserted := a.(int16)
bAsserted := b.(int16)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Int32Comparator provides a basic comparison on int32
func Int32Comparator(a, b interface{}) int {
aAsserted := a.(int32)
bAsserted := b.(int32)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Int64Comparator provides a basic comparison on int64
func Int64Comparator(a, b interface{}) int {
aAsserted := a.(int64)
bAsserted := b.(int64)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// UIntComparator provides a basic comparison on uint
func UIntComparator(a, b interface{}) int {
aAsserted := a.(uint)
bAsserted := b.(uint)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// UInt8Comparator provides a basic comparison on uint8
func UInt8Comparator(a, b interface{}) int {
aAsserted := a.(uint8)
bAsserted := b.(uint8)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// UInt16Comparator provides a basic comparison on uint16
func UInt16Comparator(a, b interface{}) int {
aAsserted := a.(uint16)
bAsserted := b.(uint16)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// UInt32Comparator provides a basic comparison on uint32
func UInt32Comparator(a, b interface{}) int {
aAsserted := a.(uint32)
bAsserted := b.(uint32)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// UInt64Comparator provides a basic comparison on uint64
func UInt64Comparator(a, b interface{}) int {
aAsserted := a.(uint64)
bAsserted := b.(uint64)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Float32Comparator provides a basic comparison on float32
func Float32Comparator(a, b interface{}) int {
aAsserted := a.(float32)
bAsserted := b.(float32)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// Float64Comparator provides a basic comparison on float64
func Float64Comparator(a, b interface{}) int {
aAsserted := a.(float64)
bAsserted := b.(float64)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// ByteComparator provides a basic comparison on byte
func ByteComparator(a, b interface{}) int {
aAsserted := a.(byte)
bAsserted := b.(byte)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// RuneComparator provides a basic comparison on rune
func RuneComparator(a, b interface{}) int {
aAsserted := a.(rune)
bAsserted := b.(rune)
switch {
case aAsserted > bAsserted:
return 1
case aAsserted < bAsserted:
return -1
default:
return 0
}
}
// TimeComparator provides a basic comparison on time.Time
func TimeComparator(a, b interface{}) int {
aAsserted := a.(time.Time)
bAsserted := b.(time.Time)
switch {
case aAsserted.After(bAsserted):
return 1
case aAsserted.Before(bAsserted):
return -1
default:
return 0
}
}
================================================
FILE: vendor/github.com/emirpasic/gods/utils/sort.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package utils
import "sort"
// Sort sorts values (in-place) with respect to the given comparator.
//
// Uses Go's sort (hybrid of quicksort for large and then insertion sort for smaller slices).
func Sort(values []interface{}, comparator Comparator) {
sort.Sort(sortable{values, comparator})
}
type sortable struct {
values []interface{}
comparator Comparator
}
func (s sortable) Len() int {
return len(s.values)
}
func (s sortable) Swap(i, j int) {
s.values[i], s.values[j] = s.values[j], s.values[i]
}
func (s sortable) Less(i, j int) bool {
return s.comparator(s.values[i], s.values[j]) < 0
}
================================================
FILE: vendor/github.com/emirpasic/gods/utils/utils.go
================================================
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package utils provides common utility functions.
//
// Provided functionalities:
// - sorting
// - comparators
package utils
import (
"fmt"
"strconv"
)
// ToString converts a value to string.
func ToString(value interface{}) string {
switch value := value.(type) {
case string:
return value
case int8:
return strconv.FormatInt(int64(value), 10)
case int16:
return strconv.FormatInt(int64(value), 10)
case int32:
return strconv.FormatInt(int64(value), 10)
case int64:
return strconv.FormatInt(value, 10)
case uint8:
return strconv.FormatUint(uint64(value), 10)
case uint16:
return strconv.FormatUint(uint64(value), 10)
case uint32:
return strconv.FormatUint(uint64(value), 10)
case uint64:
return strconv.FormatUint(value, 10)
case float32:
return strconv.FormatFloat(float64(value), 'g', -1, 64)
case float64:
return strconv.FormatFloat(value, 'g', -1, 64)
case bool:
return strconv.FormatBool(value)
default:
return fmt.Sprintf("%+v", value)
}
}
================================================
FILE: vendor/github.com/fatih/color/LICENSE.md
================================================
The MIT License (MIT)
Copyright (c) 2013 Fatih Arslan
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: vendor/github.com/fatih/color/README.md
================================================
# color [](https://github.com/fatih/color/actions) [](https://pkg.go.dev/github.com/fatih/color)
Color lets you use colorized outputs in terms of [ANSI Escape
Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It
has support for Windows too! The API can be used in several ways, pick one that
suits you.

## Install
```bash
go get github.com/fatih/color
```
## Examples
### Standard colors
```go
// Print with default helper functions
color.Cyan("Prints text in cyan.")
// A newline will be appended automatically
color.Blue("Prints %s in blue.", "text")
// These are using the default foreground colors
color.Red("We have red")
color.Magenta("And many others ..")
```
### Mix and reuse colors
```go
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")
// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")
// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)
boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with white background.")
```
### Use your own output (io.Writer)
```go
// Use your own io.Writer output
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
blue := color.New(color.FgBlue)
blue.Fprint(writer, "This will print text in blue.")
```
### Custom print functions (PrintFunc)
```go
// Create a custom print function for convenience
red := color.New(color.FgRed).PrintfFunc()
red("Warning")
red("Error: %s", err)
// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("Don't forget this...")
```
### Custom fprint functions (FprintFunc)
```go
blue := color.New(color.FgBlue).FprintfFunc()
blue(myWriter, "important notice: %s", stars)
// Mix up with multiple attributes
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
success(myWriter, "Don't forget this...")
```
### Insert into noncolor strings (SprintFunc)
```go
// Create SprintXxx functions to mix strings with other non-colorized strings:
yellow := color.New(color.FgYellow).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
fmt.Printf("This is a %s and this is %s.\n", yellow("warning"), red("error"))
info := color.New(color.FgWhite, color.BgGreen).SprintFunc()
fmt.Printf("This %s rocks!\n", info("package"))
// Use helper functions
fmt.Println("This", color.RedString("warning"), "should be not neglected.")
fmt.Printf("%v %v\n", color.GreenString("Info:"), "an important message.")
// Windows supported too! Just don't forget to change the output to color.Output
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
```
### Plug into existing code
```go
// Use handy standard colors
color.Set(color.FgYellow)
fmt.Println("Existing text will now be in yellow")
fmt.Printf("This one %s\n", "too")
color.Unset() // Don't forget to unset
// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // Use it in your function
fmt.Println("All text will now be bold magenta.")
```
### Disable/Enable color
There might be a case where you want to explicitly disable/enable color output. the
`go-isatty` package will automatically disable color output for non-tty output streams
(for example if the output were piped directly to `less`).
The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment
variable is set to a non-empty string.
`Color` has support to disable/enable colors programmatically both globally and
for single color definitions. For example suppose you have a CLI app and a
`-no-color` bool flag. You can easily disable the color output with:
```go
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
color.NoColor = true // disables colorized output
}
```
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
```go
c := color.New(color.FgCyan)
c.Println("Prints cyan text")
c.DisableColor()
c.Println("This is printed without any color")
c.EnableColor()
c.Println("This prints again cyan...")
```
## GitHub Actions
To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams.
## Todo
* Save/Return previous values
* Evaluate fmt.Formatter interface
## Credits
* [Fatih Arslan](https://github.com/fatih)
* Windows support via @mattn: [colorable](https://github.com/mattn/go-colorable)
## License
The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details
================================================
FILE: vendor/github.com/fatih/color/color.go
================================================
package color
import (
"fmt"
"io"
"os"
"strconv"
"strings"
"sync"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
var (
// NoColor defines if the output is colorized or not. It's dynamically set to
// false or true based on the stdout's file descriptor referring to a terminal
// or not. It's also set to true if the NO_COLOR environment variable is
// set (regardless of its value). This is a global option and affects all
// colors. For more control over each color block use the methods
// DisableColor() individually.
NoColor = noColorIsSet() || os.Getenv("TERM") == "dumb" ||
(!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd()))
// Output defines the standard output of the print functions. By default,
// os.Stdout is used.
Output = colorable.NewColorableStdout()
// Error defines a color supporting writer for os.Stderr.
Error = colorable.NewColorableStderr()
// colorsCache is used to reduce the count of created Color objects and
// allows to reuse already created objects with required Attribute.
colorsCache = make(map[Attribute]*Color)
colorsCacheMu sync.Mutex // protects colorsCache
)
// noColorIsSet returns true if the environment variable NO_COLOR is set to a non-empty string.
func noColorIsSet() bool {
return os.Getenv("NO_COLOR") != ""
}
// Color defines a custom color object which is defined by SGR parameters.
type Color struct {
params []Attribute
noColor *bool
}
// Attribute defines a single SGR Code
type Attribute int
const escape = "\x1b"
// Base attributes
const (
Reset Attribute = iota
Bold
Faint
Italic
Underline
BlinkSlow
BlinkRapid
ReverseVideo
Concealed
CrossedOut
)
const (
ResetBold Attribute = iota + 22
ResetItalic
ResetUnderline
ResetBlinking
_
ResetReversed
ResetConcealed
ResetCrossedOut
)
var mapResetAttributes map[Attribute]Attribute = map[Attribute]Attribute{
Bold: ResetBold,
Faint: ResetBold,
Italic: ResetItalic,
Underline: ResetUnderline,
BlinkSlow: ResetBlinking,
BlinkRapid: ResetBlinking,
ReverseVideo: ResetReversed,
Concealed: ResetConcealed,
CrossedOut: ResetCrossedOut,
}
// Foreground text colors
const (
FgBlack Attribute = iota + 30
FgRed
FgGreen
FgYellow
FgBlue
FgMagenta
FgCyan
FgWhite
)
// Foreground Hi-Intensity text colors
const (
FgHiBlack Attribute = iota + 90
FgHiRed
FgHiGreen
FgHiYellow
FgHiBlue
FgHiMagenta
FgHiCyan
FgHiWhite
)
// Background text colors
const (
BgBlack Attribute = iota + 40
BgRed
BgGreen
BgYellow
BgBlue
BgMagenta
BgCyan
BgWhite
)
// Background Hi-Intensity text colors
const (
BgHiBlack Attribute = iota + 100
BgHiRed
BgHiGreen
BgHiYellow
BgHiBlue
BgHiMagenta
BgHiCyan
BgHiWhite
)
// New returns a newly created color object.
func New(value ...Attribute) *Color {
c := &Color{
params: make([]Attribute, 0),
}
if noColorIsSet() {
c.noColor = boolPtr(true)
}
c.Add(value...)
return c
}
// Set sets the given parameters immediately. It will change the color of
// output with the given SGR parameters until color.Unset() is called.
func Set(p ...Attribute) *Color {
c := New(p...)
c.Set()
return c
}
// Unset resets all escape attributes and clears the output. Usually should
// be called after Set().
func Unset() {
if NoColor {
return
}
fmt.Fprintf(Output, "%s[%dm", escape, Reset)
}
// Set sets the SGR sequence.
func (c *Color) Set() *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprint(Output, c.format())
return c
}
func (c *Color) unset() {
if c.isNoColorSet() {
return
}
Unset()
}
// SetWriter is used to set the SGR sequence with the given io.Writer. This is
// a low-level function, and users should use the higher-level functions, such
// as color.Fprint, color.Print, etc.
func (c *Color) SetWriter(w io.Writer) *Color {
if c.isNoColorSet() {
return c
}
fmt.Fprint(w, c.format())
return c
}
// UnsetWriter resets all escape attributes and clears the output with the give
// io.Writer. Usually should be called after SetWriter().
func (c *Color) UnsetWriter(w io.Writer) {
if c.isNoColorSet() {
return
}
if NoColor {
return
}
fmt.Fprintf(w, "%s[%dm", escape, Reset)
}
// Add is used to chain SGR parameters. Use as many as parameters to combine
// and create custom color objects. Example: Add(color.FgRed, color.Underline).
func (c *Color) Add(value ...Attribute) *Color {
c.params = append(c.params, value...)
return c
}
// Fprint formats using the default formats for its operands and writes to w.
// Spaces are added between operands when neither is a string.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
c.SetWriter(w)
defer c.UnsetWriter(w)
return fmt.Fprint(w, a...)
}
// Print formats using the default formats for its operands and writes to
// standard output. Spaces are added between operands when neither is a
// string. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Print(a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprint(Output, a...)
}
// Fprintf formats according to a format specifier and writes to w.
// It returns the number of bytes written and any write error encountered.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) {
c.SetWriter(w)
defer c.UnsetWriter(w)
return fmt.Fprintf(w, format, a...)
}
// Printf formats according to a format specifier and writes to standard output.
// It returns the number of bytes written and any write error encountered.
// This is the standard fmt.Printf() method wrapped with the given color.
func (c *Color) Printf(format string, a ...interface{}) (n int, err error) {
c.Set()
defer c.unset()
return fmt.Fprintf(Output, format, a...)
}
// Fprintln formats using the default formats for its operands and writes to w.
// Spaces are always added between operands and a newline is appended.
// On Windows, users should wrap w with colorable.NewColorable() if w is of
// type *os.File.
func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
return fmt.Fprintln(w, c.wrap(fmt.Sprint(a...)))
}
// Println formats using the default formats for its operands and writes to
// standard output. Spaces are always added between operands and a newline is
// appended. It returns the number of bytes written and any write error
// encountered. This is the standard fmt.Print() method wrapped with the given
// color.
func (c *Color) Println(a ...interface{}) (n int, err error) {
return fmt.Fprintln(Output, c.wrap(fmt.Sprint(a...)))
}
// Sprint is just like Print, but returns a string instead of printing it.
func (c *Color) Sprint(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
// Sprintln is just like Println, but returns a string instead of printing it.
func (c *Color) Sprintln(a ...interface{}) string {
return fmt.Sprintln(c.Sprint(a...))
}
// Sprintf is just like Printf, but returns a string instead of printing it.
func (c *Color) Sprintf(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
// FprintFunc returns a new function that prints the passed arguments as
// colorized with color.Fprint().
func (c *Color) FprintFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprint(w, a...)
}
}
// PrintFunc returns a new function that prints the passed arguments as
// colorized with color.Print().
func (c *Color) PrintFunc() func(a ...interface{}) {
return func(a ...interface{}) {
c.Print(a...)
}
}
// FprintfFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintf().
func (c *Color) FprintfFunc() func(w io.Writer, format string, a ...interface{}) {
return func(w io.Writer, format string, a ...interface{}) {
c.Fprintf(w, format, a...)
}
}
// PrintfFunc returns a new function that prints the passed arguments as
// colorized with color.Printf().
func (c *Color) PrintfFunc() func(format string, a ...interface{}) {
return func(format string, a ...interface{}) {
c.Printf(format, a...)
}
}
// FprintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Fprintln().
func (c *Color) FprintlnFunc() func(w io.Writer, a ...interface{}) {
return func(w io.Writer, a ...interface{}) {
c.Fprintln(w, a...)
}
}
// PrintlnFunc returns a new function that prints the passed arguments as
// colorized with color.Println().
func (c *Color) PrintlnFunc() func(a ...interface{}) {
return func(a ...interface{}) {
c.Println(a...)
}
}
// SprintFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprint(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output, example:
//
// put := New(FgYellow).SprintFunc()
// fmt.Fprintf(color.Output, "This is a %s", put("warning"))
func (c *Color) SprintFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return c.wrap(fmt.Sprint(a...))
}
}
// SprintfFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintf(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintfFunc() func(format string, a ...interface{}) string {
return func(format string, a ...interface{}) string {
return c.wrap(fmt.Sprintf(format, a...))
}
}
// SprintlnFunc returns a new function that returns colorized strings for the
// given arguments with fmt.Sprintln(). Useful to put into or mix into other
// string. Windows users should use this in conjunction with color.Output.
func (c *Color) SprintlnFunc() func(a ...interface{}) string {
return func(a ...interface{}) string {
return fmt.Sprintln(c.Sprint(a...))
}
}
// sequence returns a formatted SGR sequence to be plugged into a "\x1b[...m"
// an example output might be: "1;36" -> bold cyan
func (c *Color) sequence() string {
format := make([]string, len(c.params))
for i, v := range c.params {
format[i] = strconv.Itoa(int(v))
}
return strings.Join(format, ";")
}
// wrap wraps the s string with the colors attributes. The string is ready to
// be printed.
func (c *Color) wrap(s string) string {
if c.isNoColorSet() {
return s
}
return c.format() + s + c.unformat()
}
func (c *Color) format() string {
return fmt.Sprintf("%s[%sm", escape, c.sequence())
}
func (c *Color) unformat() string {
//return fmt.Sprintf("%s[%dm", escape, Reset)
//for each element in sequence let's use the speficic reset escape, ou the generic one if not found
format := make([]string, len(c.params))
for i, v := range c.params {
format[i] = strconv.Itoa(int(Reset))
ra, ok := mapResetAttributes[v]
if ok {
format[i] = strconv.Itoa(int(ra))
}
}
return fmt.Sprintf("%s[%sm", escape, strings.Join(format, ";"))
}
// DisableColor disables the color output. Useful to not change any existing
// code and still being able to output. Can be used for flags like
// "--no-color". To enable back use EnableColor() method.
func (c *Color) DisableColor() {
c.noColor = boolPtr(true)
}
// EnableColor enables the color output. Use it in conjunction with
// DisableColor(). Otherwise, this method has no side effects.
func (c *Color) EnableColor() {
c.noColor = boolPtr(false)
}
func (c *Color) isNoColorSet() bool {
// check first if we have user set action
if c.noColor != nil {
return *c.noColor
}
// if not return the global option, which is disabled by default
return NoColor
}
// Equals returns a boolean value indicating whether two colors are equal.
func (c *Color) Equals(c2 *Color) bool {
if c == nil && c2 == nil {
return true
}
if c == nil || c2 == nil {
return false
}
if len(c.params) != len(c2.params) {
return false
}
for _, attr := range c.params {
if !c2.attrExists(attr) {
return false
}
}
return true
}
func (c *Color) attrExists(a Attribute) bool {
for _, attr := range c.params {
if attr == a {
return true
}
}
return false
}
func boolPtr(v bool) *bool {
return &v
}
func getCachedColor(p Attribute) *Color {
colorsCacheMu.Lock()
defer colorsCacheMu.Unlock()
c, ok := colorsCache[p]
if !ok {
c = New(p)
colorsCache[p] = c
}
return c
}
func colorPrint(format string, p Attribute, a ...interface{}) {
c := getCachedColor(p)
if !strings.HasSuffix(format, "\n") {
format += "\n"
}
if len(a) == 0 {
c.Print(format)
} else {
c.Printf(format, a...)
}
}
func colorString(format string, p Attribute, a ...interface{}) string {
c := getCachedColor(p)
if len(a) == 0 {
return c.SprintFunc()(format)
}
return c.SprintfFunc()(format, a...)
}
// Black is a convenient helper function to print with black foreground. A
// newline is appended to format by default.
func Black(format string, a ...interface{}) { colorPrint(format, FgBlack, a...) }
// Red is a convenient helper function to print with red foreground. A
// newline is appended to format by default.
func Red(format string, a ...interface{}) { colorPrint(format, FgRed, a...) }
// Green is a convenient helper function to print with green foreground. A
// newline is appended to format by default.
func Green(format string, a ...interface{}) { colorPrint(format, FgGreen, a...) }
// Yellow is a convenient helper function to print with yellow foreground.
// A newline is appended to format by default.
func Yellow(format string, a ...interface{}) { colorPrint(format, FgYellow, a...) }
// Blue is a convenient helper function to print with blue foreground. A
// newline is appended to format by default.
func Blue(format string, a ...interface{}) { colorPrint(format, FgBlue, a...) }
// Magenta is a convenient helper function to print with magenta foreground.
// A newline is appended to format by default.
func Magenta(format string, a ...interface{}) { colorPrint(format, FgMagenta, a...) }
// Cyan is a convenient helper function to print with cyan foreground. A
// newline is appended to format by default.
func Cyan(format string, a ...interface{}) { colorPrint(format, FgCyan, a...) }
// White is a convenient helper function to print with white foreground. A
// newline is appended to format by default.
func White(format string, a ...interface{}) { colorPrint(format, FgWhite, a...) }
// BlackString is a convenient helper function to return a string with black
// foreground.
func BlackString(format string, a ...interface{}) string { return colorString(format, FgBlack, a...) }
// RedString is a convenient helper function to return a string with red
// foreground.
func RedString(format string, a ...interface{}) string { return colorString(format, FgRed, a...) }
// GreenString is a convenient helper function to return a string with green
// foreground.
func GreenString(format string, a ...interface{}) string { return colorString(format, FgGreen, a...) }
// YellowString is a convenient helper function to return a string with yellow
// foreground.
func YellowString(format string, a ...interface{}) string { return colorString(format, FgYellow, a...) }
// BlueString is a convenient helper function to return a string with blue
// foreground.
func BlueString(format string, a ...interface{}) string { return colorString(format, FgBlue, a...) }
// MagentaString is a convenient helper function to return a string with magenta
// foreground.
func MagentaString(format string, a ...interface{}) string {
return colorString(format, FgMagenta, a...)
}
// CyanString is a convenient helper function to return a string with cyan
// foreground.
func CyanString(format string, a ...interface{}) string { return colorString(format, FgCyan, a...) }
// WhiteString is a convenient helper function to return a string with white
// foreground.
func WhiteString(format string, a ...interface{}) string { return colorString(format, FgWhite, a...) }
// HiBlack is a convenient helper function to print with hi-intensity black foreground. A
// newline is appended to format by default.
func HiBlack(format string, a ...interface{}) { colorPrint(format, FgHiBlack, a...) }
// HiRed is a convenient helper function to print with hi-intensity red foreground. A
// newline is appended to format by default.
func HiRed(format string, a ...interface{}) { colorPrint(format, FgHiRed, a...) }
// HiGreen is a convenient helper function to print with hi-intensity green foreground. A
// newline is appended to format by default.
func HiGreen(format string, a ...interface{}) { colorPrint(format, FgHiGreen, a...) }
// HiYellow is a convenient helper function to print with hi-intensity yellow foreground.
// A newline is appended to format by default.
func HiYellow(format string, a ...interface{}) { colorPrint(format, FgHiYellow, a...) }
// HiBlue is a convenient helper function to print with hi-intensity blue foreground. A
// newline is appended to format by default.
func HiBlue(format string, a ...interface{}) { colorPrint(format, FgHiBlue, a...) }
// HiMagenta is a convenient helper function to print with hi-intensity magenta foreground.
// A newline is appended to format by default.
func HiMagenta(format string, a ...interface{}) { colorPrint(format, FgHiMagenta, a...) }
// HiCyan is a convenient helper function to print with hi-intensity cyan foreground. A
// newline is appended to format by default.
func HiCyan(format string, a ...interface{}) { colorPrint(format, FgHiCyan, a...) }
// HiWhite is a convenient helper function to print with hi-intensity white foreground. A
// newline is appended to format by default.
func HiWhite(format string, a ...interface{}) { colorPrint(format, FgHiWhite, a...) }
// HiBlackString is a convenient helper function to return a string with hi-intensity black
// foreground.
func HiBlackString(format string, a ...interface{}) string {
return colorString(format, FgHiBlack, a...)
}
// HiRedString is a convenient helper function to return a string with hi-intensity red
// foreground.
func HiRedString(format string, a ...interface{}) string { return colorString(format, FgHiRed, a...) }
// HiGreenString is a convenient helper function to return a string with hi-intensity green
// foreground.
func HiGreenString(format string, a ...interface{}) string {
return colorString(format, FgHiGreen, a...)
}
// HiYellowString is a convenient helper function to return a string with hi-intensity yellow
// foreground.
func HiYellowString(format string, a ...interface{}) string {
return colorString(format, FgHiYellow, a...)
}
// HiBlueString is a convenient helper function to return a string with hi-intensity blue
// foreground.
func HiBlueString(format string, a ...interface{}) string { return colorString(format, FgHiBlue, a...) }
// HiMagentaString is a convenient helper function to return a string with hi-intensity magenta
// foreground.
func HiMagentaString(format string, a ...interface{}) string {
return colorString(format, FgHiMagenta, a...)
}
// HiCyanString is a convenient helper function to return a string with hi-intensity cyan
// foreground.
func HiCyanString(format string, a ...interface{}) string { return colorString(format, FgHiCyan, a...) }
// HiWhiteString is a convenient helper function to return a string with hi-intensity white
// foreground.
func HiWhiteString(format string, a ...interface{}) string {
return colorString(format, FgHiWhite, a...)
}
================================================
FILE: vendor/github.com/fatih/color/color_windows.go
================================================
package color
import (
"os"
"golang.org/x/sys/windows"
)
func init() {
// Opt-in for ansi color support for current process.
// https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences#output-sequences
var outMode uint32
out := windows.Handle(os.Stdout.Fd())
if err := windows.GetConsoleMode(out, &outMode); err != nil {
return
}
outMode |= windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING
_ = windows.SetConsoleMode(out, outMode)
}
================================================
FILE: vendor/github.com/fatih/color/doc.go
================================================
/*
Package color is an ANSI color package to output colorized or SGR defined
output to the standard output. The API can be used in several way, pick one
that suits you.
Use simple and default helper functions with predefined foreground colors:
color.Cyan("Prints text in cyan.")
// a newline will be appended automatically
color.Blue("Prints %s in blue.", "text")
// More default foreground colors..
color.Red("We have red")
color.Yellow("Yellow color too!")
color.Magenta("And many others ..")
// Hi-intensity colors
color.HiGreen("Bright green color.")
color.HiBlack("Bright black means gray..")
color.HiWhite("Shiny white color!")
However, there are times when custom color mixes are required. Below are some
examples to create custom color objects and use the print functions of each
separate color object.
// Create a new color object
c := color.New(color.FgCyan).Add(color.Underline)
c.Println("Prints cyan text with an underline.")
// Or just add them to New()
d := color.New(color.FgCyan, color.Bold)
d.Printf("This prints bold cyan %s\n", "too!.")
// Mix up foreground and background colors, create new mixes!
red := color.New(color.FgRed)
boldRed := red.Add(color.Bold)
boldRed.Println("This will print text in bold red.")
whiteBackground := red.Add(color.BgWhite)
whiteBackground.Println("Red text with White background.")
// Use your own io.Writer output
color.New(color.FgBlue).Fprintln(myWriter, "blue color!")
blue := color.New(color.FgBlue)
blue.Fprint(myWriter, "This will print text in blue.")
You can create PrintXxx functions to simplify even more:
// Create a custom print function for convenient
red := color.New(color.FgRed).PrintfFunc()
red("warning")
red("error: %s", err)
// Mix up multiple attributes
notice := color.New(color.Bold, color.FgGreen).PrintlnFunc()
notice("don't forget this...")
You can also FprintXxx functions to pass your own io.Writer:
blue := color.New(FgBlue).FprintfFunc()
blue(myWriter, "important notice: %s", stars)
// Mix up with multiple attributes
success := color.New(color.Bold, color.FgGreen).FprintlnFunc()
success(myWriter, don't forget this...")
Or create SprintXxx functions to mix strings with other non-colorized strings:
yellow := New(FgYellow).SprintFunc()
red := New(FgRed).SprintFunc()
fmt.Printf("this is a %s and this is %s.\n", yellow("warning"), red("error"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Printf("this %s rocks!\n", info("package"))
Windows support is enabled by default. All Print functions work as intended.
However, only for color.SprintXXX functions, user should use fmt.FprintXXX and
set the output to color.Output:
fmt.Fprintf(color.Output, "Windows support: %s", color.GreenString("PASS"))
info := New(FgWhite, BgGreen).SprintFunc()
fmt.Fprintf(color.Output, "this %s rocks!\n", info("package"))
Using with existing code is possible. Just use the Set() method to set the
standard output to the given parameters. That way a rewrite of an existing
code is not required.
// Use handy standard colors.
color.Set(color.FgYellow)
fmt.Println("Existing text will be now in Yellow")
fmt.Printf("This one %s\n", "too")
color.Unset() // don't forget to unset
// You can mix up parameters
color.Set(color.FgMagenta, color.Bold)
defer color.Unset() // use it in your function
fmt.Println("All text will be now bold magenta.")
There might be a case where you want to disable color output (for example to
pipe the standard output of your app to somewhere else). `Color` has support to
disable colors both globally and for single color definition. For example
suppose you have a CLI app and a `--no-color` bool flag. You can easily disable
the color output with:
var flagNoColor = flag.Bool("no-color", false, "Disable color output")
if *flagNoColor {
color.NoColor = true // disables colorized output
}
You can also disable the color by setting the NO_COLOR environment variable to any value.
It also has support for single color definitions (local). You can
disable/enable color output on the fly:
c := color.New(color.FgCyan)
c.Println("Prints cyan text")
c.DisableColor()
c.Println("This is printed without any color")
c.EnableColor()
c.Println("This prints again cyan...")
*/
package color
================================================
FILE: vendor/github.com/go-git/gcfg/.gitignore
================================================
coverage.out
================================================
FILE: vendor/github.com/go-git/gcfg/LICENSE
================================================
Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go
Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================
FILE: vendor/github.com/go-git/gcfg/Makefile
================================================
# General
WORKDIR = $(PWD)
# Go parameters
GOCMD = go
GOTEST = $(GOCMD) test
# Coverage
COVERAGE_REPORT = coverage.out
COVERAGE_MODE = count
test:
$(GOTEST) ./...
test-coverage:
echo "" > $(COVERAGE_REPORT); \
$(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./...
================================================
FILE: vendor/github.com/go-git/gcfg/README
================================================
Gcfg reads INI-style configuration files into Go structs;
supports user-defined types and subsections.
Package docs: https://godoc.org/gopkg.in/gcfg.v1
================================================
FILE: vendor/github.com/go-git/gcfg/doc.go
================================================
// Package gcfg reads "INI-style" text-based configuration files with
// "name=value" pairs grouped into sections (gcfg files).
//
// This package is still a work in progress; see the sections below for planned
// changes.
//
// Syntax
//
// The syntax is based on that used by git config:
// http://git-scm.com/docs/git-config#_syntax .
// There are some (planned) differences compared to the git config format:
// - improve data portability:
// - must be encoded in UTF-8 (for now) and must not contain the 0 byte
// - include and "path" type is not supported
// (path type may be implementable as a user-defined type)
// - internationalization
// - section and variable names can contain unicode letters, unicode digits
// (as defined in http://golang.org/ref/spec#Characters ) and hyphens
// (U+002D), starting with a unicode letter
// - disallow potentially ambiguous or misleading definitions:
// - `[sec.sub]` format is not allowed (deprecated in gitconfig)
// - `[sec ""]` is not allowed
// - use `[sec]` for section name "sec" and empty subsection name
// - (planned) within a single file, definitions must be contiguous for each:
// - section: '[secA]' -> '[secB]' -> '[secA]' is an error
// - subsection: '[sec "A"]' -> '[sec "B"]' -> '[sec "A"]' is an error
// - multivalued variable: 'multi=a' -> 'other=x' -> 'multi=b' is an error
//
// Data structure
//
// The functions in this package read values into a user-defined struct.
// Each section corresponds to a struct field in the config struct, and each
// variable in a section corresponds to a data field in the section struct.
// The mapping of each section or variable name to fields is done either based
// on the "gcfg" struct tag or by matching the name of the section or variable,
// ignoring case. In the latter case, hyphens '-' in section and variable names
// correspond to underscores '_' in field names.
// Fields must be exported; to use a section or variable name starting with a
// letter that is neither upper- or lower-case, prefix the field name with 'X'.
// (See https://code.google.com/p/go/issues/detail?id=5763#c4 .)
//
// For sections with subsections, the corresponding field in config must be a
// map, rather than a struct, with string keys and pointer-to-struct values.
// Values for subsection variables are stored in the map with the subsection
// name used as the map key.
// (Note that unlike section and variable names, subsection names are case
// sensitive.)
// When using a map, and there is a section with the same section name but
// without a subsection name, its values are stored with the empty string used
// as the key.
// It is possible to provide default values for subsections in the section
// "default-" (or by setting values in the corresponding struct
// field "Default_").
//
// The functions in this package panic if config is not a pointer to a struct,
// or when a field is not of a suitable type (either a struct or a map with
// string keys and pointer-to-struct values).
//
// Parsing of values
//
// The section structs in the config struct may contain single-valued or
// multi-valued variables. Variables of unnamed slice type (that is, a type
// starting with `[]`) are treated as multi-value; all others (including named
// slice types) are treated as single-valued variables.
//
// Single-valued variables are handled based on the type as follows.
// Unnamed pointer types (that is, types starting with `*`) are dereferenced,
// and if necessary, a new instance is allocated.
//
// For types implementing the encoding.TextUnmarshaler interface, the
// UnmarshalText method is used to set the value. Implementing this method is
// the recommended way for parsing user-defined types.
//
// For fields of string kind, the value string is assigned to the field, after
// unquoting and unescaping as needed.
// For fields of bool kind, the field is set to true if the value is "true",
// "yes", "on" or "1", and set to false if the value is "false", "no", "off" or
// "0", ignoring case. In addition, single-valued bool fields can be specified
// with a "blank" value (variable name without equals sign and value); in such
// case the value is set to true.
//
// Predefined integer types [u]int(|8|16|32|64) and big.Int are parsed as
// decimal or hexadecimal (if having '0x' prefix). (This is to prevent
// unintuitively handling zero-padded numbers as octal.) Other types having
// [u]int* as the underlying type, such as os.FileMode and uintptr allow
// decimal, hexadecimal, or octal values.
// Parsing mode for integer types can be overridden using the struct tag option
// ",int=mode" where mode is a combination of the 'd', 'h', and 'o' characters
// (each standing for decimal, hexadecimal, and octal, respectively.)
//
// All other types are parsed using fmt.Sscanf with the "%v" verb.
//
// For multi-valued variables, each individual value is parsed as above and
// appended to the slice. If the first value is specified as a "blank" value
// (variable name without equals sign and value), a new slice is allocated;
// that is any values previously set in the slice will be ignored.
//
// The types subpackage for provides helpers for parsing "enum-like" and integer
// types.
//
// Error handling
//
// There are 3 types of errors:
//
// - programmer errors / panics:
// - invalid configuration structure
// - data errors:
// - fatal errors:
// - invalid configuration syntax
// - warnings:
// - data that doesn't belong to any part of the config structure
//
// Programmer errors trigger panics. These are should be fixed by the programmer
// before releasing code that uses gcfg.
//
// Data errors cause gcfg to return a non-nil error value. This includes the
// case when there are extra unknown key-value definitions in the configuration
// data (extra data).
// However, in some occasions it is desirable to be able to proceed in
// situations when the only data error is that of extra data.
// These errors are handled at a different (warning) priority and can be
// filtered out programmatically. To ignore extra data warnings, wrap the
// gcfg.Read*Into invocation into a call to gcfg.FatalOnly.
//
// TODO
//
// The following is a list of changes under consideration:
// - documentation
// - self-contained syntax documentation
// - more practical examples
// - move TODOs to issue tracker (eventually)
// - syntax
// - reconsider valid escape sequences
// (gitconfig doesn't support \r in value, \t in subsection name, etc.)
// - reading / parsing gcfg files
// - define internal representation structure
// - support multiple inputs (readers, strings, files)
// - support declaring encoding (?)
// - support varying fields sets for subsections (?)
// - writing gcfg files
// - error handling
// - make error context accessible programmatically?
// - limit input size?
//
package gcfg // import "github.com/go-git/gcfg"
================================================
FILE: vendor/github.com/go-git/gcfg/errors.go
================================================
package gcfg
import (
"gopkg.in/warnings.v0"
)
// FatalOnly filters the results of a Read*Into invocation and returns only
// fatal errors. That is, errors (warnings) indicating data for unknown
// sections / variables is ignored. Example invocation:
//
// err := gcfg.FatalOnly(gcfg.ReadFileInto(&cfg, configFile))
// if err != nil {
// ...
//
func FatalOnly(err error) error {
return warnings.FatalOnly(err)
}
func isFatal(err error) bool {
_, ok := err.(extraData)
return !ok
}
type extraData struct {
section string
subsection *string
variable *string
}
func (e extraData) Error() string {
s := "can't store data at section \"" + e.section + "\""
if e.subsection != nil {
s += ", subsection \"" + *e.subsection + "\""
}
if e.variable != nil {
s += ", variable \"" + *e.variable + "\""
}
return s
}
var _ error = extraData{}
================================================
FILE: vendor/github.com/go-git/gcfg/read.go
================================================
package gcfg
import (
"fmt"
"io"
"os"
"strings"
"gopkg.in/warnings.v0"
"github.com/go-git/gcfg/scanner"
"github.com/go-git/gcfg/token"
)
var unescape = map[rune]rune{'\\': '\\', '"': '"', 'n': '\n', 't': '\t', 'b': '\b', '\n': '\n'}
// no error: invalid literals should be caught by scanner
func unquote(s string) string {
u, q, esc := make([]rune, 0, len(s)), false, false
for _, c := range s {
if esc {
uc, ok := unescape[c]
switch {
case ok:
u = append(u, uc)
fallthrough
case !q && c == '\n':
esc = false
continue
}
panic("invalid escape sequence")
}
switch c {
case '"':
q = !q
case '\\':
esc = true
default:
u = append(u, c)
}
}
if q {
panic("missing end quote")
}
if esc {
panic("invalid escape sequence")
}
return string(u)
}
func read(c *warnings.Collector, callback func(string, string, string, string, bool) error,
fset *token.FileSet, file *token.File, src []byte) error {
//
var s scanner.Scanner
var errs scanner.ErrorList
s.Init(file, src, func(p token.Position, m string) { errs.Add(p, m) }, 0)
sect, sectsub := "", ""
pos, tok, lit := s.Scan()
errfn := func(msg string) error {
return fmt.Errorf("%s: %s", fset.Position(pos), msg)
}
for {
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
switch tok {
case token.EOF:
return nil
case token.EOL, token.COMMENT:
pos, tok, lit = s.Scan()
case token.LBRACK:
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
if tok != token.IDENT {
if err := c.Collect(errfn("expected section name")); err != nil {
return err
}
}
sect, sectsub = lit, ""
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
if tok == token.STRING {
sectsub = unquote(lit)
if sectsub == "" {
if err := c.Collect(errfn("empty subsection name")); err != nil {
return err
}
}
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
}
if tok != token.RBRACK {
if sectsub == "" {
if err := c.Collect(errfn("expected subsection name or right bracket")); err != nil {
return err
}
}
if err := c.Collect(errfn("expected right bracket")); err != nil {
return err
}
}
pos, tok, lit = s.Scan()
if tok != token.EOL && tok != token.EOF && tok != token.COMMENT {
if err := c.Collect(errfn("expected EOL, EOF, or comment")); err != nil {
return err
}
}
// If a section/subsection header was found, ensure a
// container object is created, even if there are no
// variables further down.
err := c.Collect(callback(sect, sectsub, "", "", true))
if err != nil {
return err
}
case token.IDENT:
if sect == "" {
if err := c.Collect(errfn("expected section header")); err != nil {
return err
}
}
n := lit
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
return errs.Err()
}
blank, v := tok == token.EOF || tok == token.EOL || tok == token.COMMENT, ""
if !blank {
if tok != token.ASSIGN {
if err := c.Collect(errfn("expected '='")); err != nil {
return err
}
}
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
if tok != token.STRING {
if err := c.Collect(errfn("expected value")); err != nil {
return err
}
}
v = unquote(lit)
pos, tok, lit = s.Scan()
if errs.Len() > 0 {
if err := c.Collect(errs.Err()); err != nil {
return err
}
}
if tok != token.EOL && tok != token.EOF && tok != token.COMMENT {
if err := c.Collect(errfn("expected EOL, EOF, or comment")); err != nil {
return err
}
}
}
err := c.Collect(callback(sect, sectsub, n, v, blank))
if err != nil {
return err
}
default:
if sect == "" {
if err := c.Collect(errfn("expected section header")); err != nil {
return err
}
}
if err := c.Collect(errfn("expected section header or variable declaration")); err != nil {
return err
}
}
}
panic("never reached")
}
func readInto(config interface{}, fset *token.FileSet, file *token.File,
src []byte) error {
//
c := warnings.NewCollector(isFatal)
firstPassCallback := func(s string, ss string, k string, v string, bv bool) error {
return set(c, config, s, ss, k, v, bv, false)
}
err := read(c, firstPassCallback, fset, file, src)
if err != nil {
return err
}
secondPassCallback := func(s string, ss string, k string, v string, bv bool) error {
return set(c, config, s, ss, k, v, bv, true)
}
err = read(c, secondPassCallback, fset, file, src)
if err != nil {
return err
}
return c.Done()
}
// ReadWithCallback reads gcfg formatted data from reader and calls
// callback with each section and option found.
//
// Callback is called with section, subsection, option key, option value
// and blank value flag as arguments.
//
// When a section is found, callback is called with nil subsection, option key
// and option value.
//
// When a subsection is found, callback is called with nil option key and
// option value.
//
// If blank value flag is true, it means that the value was not set for an option
// (as opposed to set to empty string).
//
// If callback returns an error, ReadWithCallback terminates with an error too.
func ReadWithCallback(reader io.Reader, callback func(string, string, string, string, bool) error) error {
src, err := io.ReadAll(reader)
if err != nil {
return err
}
fset := token.NewFileSet()
file := fset.AddFile("", fset.Base(), len(src))
c := warnings.NewCollector(isFatal)
return read(c, callback, fset, file, src)
}
// ReadInto reads gcfg formatted data from reader and sets the values into the
// corresponding fields in config.
func ReadInto(config interface{}, reader io.Reader) error {
src, err := io.ReadAll(reader)
if err != nil {
return err
}
fset := token.NewFileSet()
file := fset.AddFile("", fset.Base(), len(src))
return readInto(config, fset, file, src)
}
// ReadStringInto reads gcfg formatted data from str and sets the values into
// the corresponding fields in config.
func ReadStringInto(config interface{}, str string) error {
r := strings.NewReader(str)
return ReadInto(config, r)
}
// ReadFileInto reads gcfg formatted data from the file filename and sets the
// values into the corresponding fields in config.
func ReadFileInto(config interface{}, filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
src, err := io.ReadAll(f)
if err != nil {
return err
}
fset := token.NewFileSet()
file := fset.AddFile(filename, fset.Base(), len(src))
return readInto(config, fset, file, src)
}
================================================
FILE: vendor/github.com/go-git/gcfg/scanner/errors.go
================================================
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package scanner
import (
"fmt"
"io"
"sort"
)
import (
"github.com/go-git/gcfg/token"
)
// In an ErrorList, an error is represented by an *Error.
// The position Pos, if valid, points to the beginning of
// the offending token, and the error condition is described
// by Msg.
//
type Error struct {
Pos token.Position
Msg string
}
// Error implements the error interface.
func (e Error) Error() string {
if e.Pos.Filename != "" || e.Pos.IsValid() {
// don't print ""
// TODO(gri) reconsider the semantics of Position.IsValid
return e.Pos.String() + ": " + e.Msg
}
return e.Msg
}
// ErrorList is a list of *Errors.
// The zero value for an ErrorList is an empty ErrorList ready to use.
//
type ErrorList []*Error
// Add adds an Error with given position and error message to an ErrorList.
func (p *ErrorList) Add(pos token.Position, msg string) {
*p = append(*p, &Error{pos, msg})
}
// Reset resets an ErrorList to no errors.
func (p *ErrorList) Reset() { *p = (*p)[0:0] }
// ErrorList implements the sort Interface.
func (p ErrorList) Len() int { return len(p) }
func (p ErrorList) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p ErrorList) Less(i, j int) bool {
e := &p[i].Pos
f := &p[j].Pos
if e.Filename < f.Filename {
return true
}
if e.Filename == f.Filename {
return e.Offset < f.Offset
}
return false
}
// Sort sorts an ErrorList. *Error entries are sorted by position,
// other errors are sorted by error message, and before any *Error
// entry.
//
func (p ErrorList) Sort() {
sort.Sort(p)
}
// RemoveMultiples sorts an ErrorList and removes all but the first error per line.
func (p *ErrorList) RemoveMultiples() {
sort.Sort(p)
var last token.Position // initial last.Line is != any legal error line
i := 0
for _, e := range *p {
if e.Pos.Filename != last.Filename || e.Pos.Line != last.Line {
last = e.Pos
(*p)[i] = e
i++
}
}
(*p) = (*p)[0:i]
}
// An ErrorList implements the error interface.
func (p ErrorList) Error() string {
switch len(p) {
case 0:
return "no errors"
case 1:
return p[0].Error()
}
return fmt.Sprintf("%s (and %d more errors)", p[0], len(p)-1)
}
// Err returns an error equivalent to this error list.
// If the list is empty, Err returns nil.
func (p ErrorList) Err() error {
if len(p) == 0 {
return nil
}
return p
}
// PrintError is a utility function that prints a list of errors to w,
// one error per line, if the err parameter is an ErrorList. Otherwise
// it prints the err string.
//
func PrintError(w io.Writer, err error) {
if list, ok := err.(ErrorList); ok {
for _, e := range list {
fmt.Fprintf(w, "%s\n", e)
}
} else if err != nil {
fmt.Fprintf(w, "%s\n", err)
}
}
================================================
FILE: vendor/github.com/go-git/gcfg/scanner/scanner.go
================================================
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package scanner implements a scanner for gcfg configuration text.
// It takes a []byte as source which can then be tokenized
// through repeated calls to the Scan method.
//
// Note that the API for the scanner package may change to accommodate new
// features or implementation changes in gcfg.
package scanner
import (
"fmt"
"path/filepath"
"unicode"
"unicode/utf8"
"github.com/go-git/gcfg/token"
)
// An ErrorHandler may be provided to Scanner.Init. If a syntax error is
// encountered and a handler was installed, the handler is called with a
// position and an error message. The position points to the beginning of
// the offending token.
type ErrorHandler func(pos token.Position, msg string)
// A Scanner holds the scanner's internal state while processing
// a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use.
type Scanner struct {
// immutable state
file *token.File // source file handle
dir string // directory portion of file.Name()
src []byte // source
err ErrorHandler // error reporting; or nil
mode Mode // scanning mode
// scanning state
ch rune // current character
offset int // character offset
rdOffset int // reading offset (position after current character)
lineOffset int // current line offset
nextVal bool // next token is expected to be a value
// public state - ok to modify
ErrorCount int // number of errors encountered
}
// Read the next Unicode char into s.ch.
// s.ch < 0 means end-of-file.
func (s *Scanner) next() {
if s.rdOffset < len(s.src) {
s.offset = s.rdOffset
if s.ch == '\n' {
s.lineOffset = s.offset
s.file.AddLine(s.offset)
}
r, w := rune(s.src[s.rdOffset]), 1
switch {
case r == 0:
s.error(s.offset, "illegal character NUL")
case r >= 0x80:
// not ASCII
r, w = utf8.DecodeRune(s.src[s.rdOffset:])
if r == utf8.RuneError && w == 1 {
s.error(s.offset, "illegal UTF-8 encoding")
}
}
s.rdOffset += w
s.ch = r
} else {
s.offset = len(s.src)
if s.ch == '\n' {
s.lineOffset = s.offset
s.file.AddLine(s.offset)
}
s.ch = -1 // eof
}
}
// A mode value is a set of flags (or 0).
// They control scanner behavior.
type Mode uint
const (
ScanComments Mode = 1 << iota // return comments as COMMENT tokens
)
// Init prepares the scanner s to tokenize the text src by setting the
// scanner at the beginning of src. The scanner uses the file set file
// for position information and it adds line information for each line.
// It is ok to re-use the same file when re-scanning the same file as
// line information which is already present is ignored. Init causes a
// panic if the file size does not match the src size.
//
// Calls to Scan will invoke the error handler err if they encounter a
// syntax error and err is not nil. Also, for each error encountered,
// the Scanner field ErrorCount is incremented by one. The mode parameter
// determines how comments are handled.
//
// Note that Init may call err if there is an error in the first character
// of the file.
func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) {
// Explicitly initialize all fields since a scanner may be reused.
if file.Size() != len(src) {
panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src)))
}
s.file = file
s.dir, _ = filepath.Split(file.Name())
s.src = src
s.err = err
s.mode = mode
s.ch = ' '
s.offset = 0
s.rdOffset = 0
s.lineOffset = 0
s.ErrorCount = 0
s.nextVal = false
s.next()
}
func (s *Scanner) error(offs int, msg string) {
if s.err != nil {
s.err(s.file.Position(s.file.Pos(offs)), msg)
}
s.ErrorCount++
}
func (s *Scanner) scanComment() string {
// initial [;#] already consumed
offs := s.offset - 1 // position of initial [;#]
for s.ch != '\n' && s.ch >= 0 {
s.next()
}
return string(s.src[offs:s.offset])
}
func isLetter(ch rune) bool {
return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch >= 0x80 && unicode.IsLetter(ch)
}
func isDigit(ch rune) bool {
return '0' <= ch && ch <= '9' || ch >= 0x80 && unicode.IsDigit(ch)
}
func (s *Scanner) scanIdentifier() string {
offs := s.offset
for isLetter(s.ch) || isDigit(s.ch) || s.ch == '-' {
s.next()
}
return string(s.src[offs:s.offset])
}
// val indicate if we are scanning a value (vs a header)
func (s *Scanner) scanEscape(val bool) {
offs := s.offset
ch := s.ch
s.next() // always make progress
switch ch {
case '\\', '"', '\n':
// ok
case 'n', 't', 'b':
if val {
break // ok
}
fallthrough
default:
s.error(offs, "unknown escape sequence")
}
}
func (s *Scanner) scanString() string {
// '"' opening already consumed
offs := s.offset - 1
for s.ch != '"' {
ch := s.ch
s.next()
if ch == '\n' || ch < 0 {
s.error(offs, "string not terminated")
break
}
if ch == '\\' {
s.scanEscape(false)
}
}
s.next()
return string(s.src[offs:s.offset])
}
func stripCR(b []byte) []byte {
c := make([]byte, len(b))
i := 0
for _, ch := range b {
if ch != '\r' {
c[i] = ch
i++
}
}
return c[:i]
}
func (s *Scanner) scanValString() string {
offs := s.offset
hasCR := false
end := offs
inQuote := false
loop:
for inQuote || s.ch >= 0 && s.ch != '\n' && s.ch != ';' && s.ch != '#' {
ch := s.ch
s.next()
switch {
case inQuote && ch == '\\':
s.scanEscape(true)
case !inQuote && ch == '\\':
if s.ch == '\r' {
hasCR = true
s.next()
}
if s.ch != '\n' {
s.scanEscape(true)
} else {
s.next()
}
case ch == '"':
inQuote = !inQuote
case ch == '\r':
hasCR = true
case ch < 0 || inQuote && ch == '\n':
s.error(offs, "string not terminated")
break loop
}
if inQuote || !isWhiteSpace(ch) {
end = s.offset
}
}
lit := s.src[offs:end]
if hasCR {
lit = stripCR(lit)
}
return string(lit)
}
func isWhiteSpace(ch rune) bool {
return ch == ' ' || ch == '\t' || ch == '\r'
}
func (s *Scanner) skipWhitespace() {
for isWhiteSpace(s.ch) {
s.next()
}
}
// Scan scans the next token and returns the token position, the token,
// and its literal string if applicable. The source end is indicated by
// token.EOF.
//
// If the returned token is a literal (token.IDENT, token.STRING) or
// token.COMMENT, the literal string has the corresponding value.
//
// If the returned token is token.ILLEGAL, the literal string is the
// offending character.
//
// In all other cases, Scan returns an empty literal string.
//
// For more tolerant parsing, Scan will return a valid token if
// possible even if a syntax error was encountered. Thus, even
// if the resulting token sequence contains no illegal tokens,
// a client may not assume that no error occurred. Instead it
// must check the scanner's ErrorCount or the number of calls
// of the error handler, if there was one installed.
//
// Scan adds line information to the file added to the file
// set with Init. Token positions are relative to that file
// and thus relative to the file set.
func (s *Scanner) Scan() (pos token.Pos, tok token.Token, lit string) {
scanAgain:
s.skipWhitespace()
// current token start
pos = s.file.Pos(s.offset)
// determine token value
switch ch := s.ch; {
case s.nextVal:
lit = s.scanValString()
tok = token.STRING
s.nextVal = false
case isLetter(ch):
lit = s.scanIdentifier()
tok = token.IDENT
default:
s.next() // always make progress
switch ch {
case -1:
tok = token.EOF
case '\n':
tok = token.EOL
case '"':
tok = token.STRING
lit = s.scanString()
case '[':
tok = token.LBRACK
case ']':
tok = token.RBRACK
case ';', '#':
// comment
lit = s.scanComment()
if s.mode&ScanComments == 0 {
// skip comment
goto scanAgain
}
tok = token.COMMENT
case '=':
tok = token.ASSIGN
s.nextVal = true
default:
s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
tok = token.ILLEGAL
lit = string(ch)
}
}
return
}
================================================
FILE: vendor/github.com/go-git/gcfg/set.go
================================================
package gcfg
import (
"bytes"
"encoding"
"encoding/gob"
"fmt"
"math/big"
"reflect"
"strings"
"unicode"
"unicode/utf8"
"gopkg.in/warnings.v0"
"github.com/go-git/gcfg/types"
)
type tag struct {
ident string
intMode string
}
func newTag(ts string) tag {
t := tag{}
s := strings.Split(ts, ",")
t.ident = s[0]
for _, tse := range s[1:] {
if strings.HasPrefix(tse, "int=") {
t.intMode = tse[len("int="):]
}
}
return t
}
func fieldFold(v reflect.Value, name string) (reflect.Value, tag) {
var n string
r0, _ := utf8.DecodeRuneInString(name)
if unicode.IsLetter(r0) && !unicode.IsLower(r0) && !unicode.IsUpper(r0) {
n = "X"
}
n += strings.Replace(name, "-", "_", -1)
f, ok := v.Type().FieldByNameFunc(func(fieldName string) bool {
if !v.FieldByName(fieldName).CanSet() {
return false
}
f, _ := v.Type().FieldByName(fieldName)
t := newTag(f.Tag.Get("gcfg"))
if t.ident != "" {
return strings.EqualFold(t.ident, name)
}
return strings.EqualFold(n, fieldName)
})
if !ok {
return reflect.Value{}, tag{}
}
return v.FieldByName(f.Name), newTag(f.Tag.Get("gcfg"))
}
type setter func(destp interface{}, blank bool, val string, t tag) error
var errUnsupportedType = fmt.Errorf("unsupported type")
var errBlankUnsupported = fmt.Errorf("blank value not supported for type")
var setters = []setter{
typeSetter, textUnmarshalerSetter, kindSetter, scanSetter,
}
func textUnmarshalerSetter(d interface{}, blank bool, val string, t tag) error {
dtu, ok := d.(encoding.TextUnmarshaler)
if !ok {
return errUnsupportedType
}
if blank {
return errBlankUnsupported
}
return dtu.UnmarshalText([]byte(val))
}
func boolSetter(d interface{}, blank bool, val string, t tag) error {
if blank {
reflect.ValueOf(d).Elem().Set(reflect.ValueOf(true))
return nil
}
b, err := types.ParseBool(val)
if err == nil {
reflect.ValueOf(d).Elem().Set(reflect.ValueOf(b))
}
return err
}
func intMode(mode string) types.IntMode {
var m types.IntMode
if strings.ContainsAny(mode, "dD") {
m |= types.Dec
}
if strings.ContainsAny(mode, "hH") {
m |= types.Hex
}
if strings.ContainsAny(mode, "oO") {
m |= types.Oct
}
return m
}
var typeModes = map[reflect.Type]types.IntMode{
reflect.TypeOf(int(0)): types.Dec | types.Hex,
reflect.TypeOf(int8(0)): types.Dec | types.Hex,
reflect.TypeOf(int16(0)): types.Dec | types.Hex,
reflect.TypeOf(int32(0)): types.Dec | types.Hex,
reflect.TypeOf(int64(0)): types.Dec | types.Hex,
reflect.TypeOf(uint(0)): types.Dec | types.Hex,
reflect.TypeOf(uint8(0)): types.Dec | types.Hex,
reflect.TypeOf(uint16(0)): types.Dec | types.Hex,
reflect.TypeOf(uint32(0)): types.Dec | types.Hex,
reflect.TypeOf(uint64(0)): types.Dec | types.Hex,
// use default mode (allow dec/hex/oct) for uintptr type
reflect.TypeOf(big.Int{}): types.Dec | types.Hex,
}
func intModeDefault(t reflect.Type) types.IntMode {
m, ok := typeModes[t]
if !ok {
m = types.Dec | types.Hex | types.Oct
}
return m
}
func intSetter(d interface{}, blank bool, val string, t tag) error {
if blank {
return errBlankUnsupported
}
mode := intMode(t.intMode)
if mode == 0 {
mode = intModeDefault(reflect.TypeOf(d).Elem())
}
return types.ParseInt(d, val, mode)
}
func stringSetter(d interface{}, blank bool, val string, t tag) error {
if blank {
return errBlankUnsupported
}
dsp, ok := d.(*string)
if !ok {
return errUnsupportedType
}
*dsp = val
return nil
}
var kindSetters = map[reflect.Kind]setter{
reflect.String: stringSetter,
reflect.Bool: boolSetter,
reflect.Int: intSetter,
reflect.Int8: intSetter,
reflect.Int16: intSetter,
reflect.Int32: intSetter,
reflect.Int64: intSetter,
reflect.Uint: intSetter,
reflect.Uint8: intSetter,
reflect.Uint16: intSetter,
reflect.Uint32: intSetter,
reflect.Uint64: intSetter,
reflect.Uintptr: intSetter,
}
var typeSetters = map[reflect.Type]setter{
reflect.TypeOf(big.Int{}): intSetter,
}
func typeSetter(d interface{}, blank bool, val string, tt tag) error {
t := reflect.ValueOf(d).Type().Elem()
setter, ok := typeSetters[t]
if !ok {
return errUnsupportedType
}
return setter(d, blank, val, tt)
}
func kindSetter(d interface{}, blank bool, val string, tt tag) error {
k := reflect.ValueOf(d).Type().Elem().Kind()
setter, ok := kindSetters[k]
if !ok {
return errUnsupportedType
}
return setter(d, blank, val, tt)
}
func scanSetter(d interface{}, blank bool, val string, tt tag) error {
if blank {
return errBlankUnsupported
}
return types.ScanFully(d, val, 'v')
}
func newValue(c *warnings.Collector, sect string, vCfg reflect.Value,
vType reflect.Type) (reflect.Value, error) {
//
pv := reflect.New(vType)
dfltName := "default-" + sect
dfltField, _ := fieldFold(vCfg, dfltName)
var err error
if dfltField.IsValid() {
b := bytes.NewBuffer(nil)
ge := gob.NewEncoder(b)
if err = c.Collect(ge.EncodeValue(dfltField)); err != nil {
return pv, err
}
gd := gob.NewDecoder(bytes.NewReader(b.Bytes()))
if err = c.Collect(gd.DecodeValue(pv.Elem())); err != nil {
return pv, err
}
}
return pv, nil
}
func set(c *warnings.Collector, cfg interface{}, sect, sub, name string,
value string, blankValue bool, subsectPass bool) error {
//
vPCfg := reflect.ValueOf(cfg)
if vPCfg.Kind() != reflect.Ptr || vPCfg.Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("config must be a pointer to a struct"))
}
vCfg := vPCfg.Elem()
vSect, _ := fieldFold(vCfg, sect)
if !vSect.IsValid() {
err := extraData{section: sect}
return c.Collect(err)
}
isSubsect := vSect.Kind() == reflect.Map
if subsectPass != isSubsect {
return nil
}
if isSubsect {
vst := vSect.Type()
if vst.Key().Kind() != reflect.String ||
vst.Elem().Kind() != reflect.Ptr ||
vst.Elem().Elem().Kind() != reflect.Struct {
panic(fmt.Errorf("map field for section must have string keys and "+
" pointer-to-struct values: section %q", sect))
}
if vSect.IsNil() {
vSect.Set(reflect.MakeMap(vst))
}
k := reflect.ValueOf(sub)
pv := vSect.MapIndex(k)
if !pv.IsValid() {
vType := vSect.Type().Elem().Elem()
var err error
if pv, err = newValue(c, sect, vCfg, vType); err != nil {
return err
}
vSect.SetMapIndex(k, pv)
}
vSect = pv.Elem()
} else if vSect.Kind() != reflect.Struct {
panic(fmt.Errorf("field for section must be a map or a struct: "+
"section %q", sect))
} else if sub != "" {
err := extraData{section: sect, subsection: &sub}
return c.Collect(err)
}
// Empty name is a special value, meaning that only the
// section/subsection object is to be created, with no values set.
if name == "" {
return nil
}
vVar, t := fieldFold(vSect, name)
if !vVar.IsValid() {
var err error
if isSubsect {
err = extraData{section: sect, subsection: &sub, variable: &name}
} else {
err = extraData{section: sect, variable: &name}
}
return c.Collect(err)
}
// vVal is either single-valued var, or newly allocated value within multi-valued var
var vVal reflect.Value
// multi-value if unnamed slice type
isMulti := vVar.Type().Name() == "" && vVar.Kind() == reflect.Slice ||
vVar.Type().Name() == "" && vVar.Kind() == reflect.Ptr && vVar.Type().Elem().Name() == "" && vVar.Type().Elem().Kind() == reflect.Slice
if isMulti && vVar.Kind() == reflect.Ptr {
if vVar.IsNil() {
vVar.Set(reflect.New(vVar.Type().Elem()))
}
vVar = vVar.Elem()
}
if isMulti && blankValue {
vVar.Set(reflect.Zero(vVar.Type()))
return nil
}
if isMulti {
vVal = reflect.New(vVar.Type().Elem()).Elem()
} else {
vVal = vVar
}
isDeref := vVal.Type().Name() == "" && vVal.Type().Kind() == reflect.Ptr
isNew := isDeref && vVal.IsNil()
// vAddr is address of value to set (dereferenced & allocated as needed)
var vAddr reflect.Value
switch {
case isNew:
vAddr = reflect.New(vVal.Type().Elem())
case isDeref && !isNew:
vAddr = vVal
default:
vAddr = vVal.Addr()
}
vAddrI := vAddr.Interface()
err, ok := error(nil), false
for _, s := range setters {
err = s(vAddrI, blankValue, value, t)
if err == nil {
ok = true
break
}
if err != errUnsupportedType {
return err
}
}
if !ok {
// in case all setters returned errUnsupportedType
return err
}
if isNew { // set reference if it was dereferenced and newly allocated
vVal.Set(vAddr)
}
if isMulti { // append if multi-valued
vVar.Set(reflect.Append(vVar, vVal))
}
return nil
}
================================================
FILE: vendor/github.com/go-git/gcfg/token/position.go
================================================
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// TODO(gri) consider making this a separate package outside the go directory.
package token
import (
"fmt"
"sort"
"sync"
)
// -----------------------------------------------------------------------------
// Positions
// Position describes an arbitrary source position
// including the file, line, and column location.
// A Position is valid if the line number is > 0.
//
type Position struct {
Filename string // filename, if any
Offset int // offset, starting at 0
Line int // line number, starting at 1
Column int // column number, starting at 1 (character count)
}
// IsValid returns true if the position is valid.
func (pos *Position) IsValid() bool { return pos.Line > 0 }
// String returns a string in one of several forms:
//
// file:line:column valid position with file name
// line:column valid position without file name
// file invalid position with file name
// - invalid position without file name
//
func (pos Position) String() string {
s := pos.Filename
if pos.IsValid() {
if s != "" {
s += ":"
}
s += fmt.Sprintf("%d:%d", pos.Line, pos.Column)
}
if s == "" {
s = "-"
}
return s
}
// Pos is a compact encoding of a source position within a file set.
// It can be converted into a Position for a more convenient, but much
// larger, representation.
//
// The Pos value for a given file is a number in the range [base, base+size],
// where base and size are specified when adding the file to the file set via
// AddFile.
//
// To create the Pos value for a specific source offset, first add
// the respective file to the current file set (via FileSet.AddFile)
// and then call File.Pos(offset) for that file. Given a Pos value p
// for a specific file set fset, the corresponding Position value is
// obtained by calling fset.Position(p).
//
// Pos values can be compared directly with the usual comparison operators:
// If two Pos values p and q are in the same file, comparing p and q is
// equivalent to comparing the respective source file offsets. If p and q
// are in different files, p < q is true if the file implied by p was added
// to the respective file set before the file implied by q.
//
type Pos int
// The zero value for Pos is NoPos; there is no file and line information
// associated with it, and NoPos().IsValid() is false. NoPos is always
// smaller than any other Pos value. The corresponding Position value
// for NoPos is the zero value for Position.
//
const NoPos Pos = 0
// IsValid returns true if the position is valid.
func (p Pos) IsValid() bool {
return p != NoPos
}
// -----------------------------------------------------------------------------
// File
// A File is a handle for a file belonging to a FileSet.
// A File has a name, size, and line offset table.
//
type File struct {
set *FileSet
name string // file name as provided to AddFile
base int // Pos value range for this file is [base...base+size]
size int // file size as provided to AddFile
// lines and infos are protected by set.mutex
lines []int
infos []lineInfo
}
// Name returns the file name of file f as registered with AddFile.
func (f *File) Name() string {
return f.name
}
// Base returns the base offset of file f as registered with AddFile.
func (f *File) Base() int {
return f.base
}
// Size returns the size of file f as registered with AddFile.
func (f *File) Size() int {
return f.size
}
// LineCount returns the number of lines in file f.
func (f *File) LineCount() int {
f.set.mutex.RLock()
n := len(f.lines)
f.set.mutex.RUnlock()
return n
}
// AddLine adds the line offset for a new line.
// The line offset must be larger than the offset for the previous line
// and smaller than the file size; otherwise the line offset is ignored.
//
func (f *File) AddLine(offset int) {
f.set.mutex.Lock()
if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size {
f.lines = append(f.lines, offset)
}
f.set.mutex.Unlock()
}
// SetLines sets the line offsets for a file and returns true if successful.
// The line offsets are the offsets of the first character of each line;
// for instance for the content "ab\nc\n" the line offsets are {0, 3}.
// An empty file has an empty line offset table.
// Each line offset must be larger than the offset for the previous line
// and smaller than the file size; otherwise SetLines fails and returns
// false.
//
func (f *File) SetLines(lines []int) bool {
// verify validity of lines table
size := f.size
for i, offset := range lines {
if i > 0 && offset <= lines[i-1] || size <= offset {
return false
}
}
// set lines table
f.set.mutex.Lock()
f.lines = lines
f.set.mutex.Unlock()
return true
}
// SetLinesForContent sets the line offsets for the given file content.
func (f *File) SetLinesForContent(content []byte) {
var lines []int
line := 0
for offset, b := range content {
if line >= 0 {
lines = append(lines, line)
}
line = -1
if b == '\n' {
line = offset + 1
}
}
// set lines table
f.set.mutex.Lock()
f.lines = lines
f.set.mutex.Unlock()
}
// A lineInfo object describes alternative file and line number
// information (such as provided via a //line comment in a .go
// file) for a given file offset.
type lineInfo struct {
// fields are exported to make them accessible to gob
Offset int
Filename string
Line int
}
// AddLineInfo adds alternative file and line number information for
// a given file offset. The offset must be larger than the offset for
// the previously added alternative line info and smaller than the
// file size; otherwise the information is ignored.
//
// AddLineInfo is typically used to register alternative position
// information for //line filename:line comments in source files.
//
func (f *File) AddLineInfo(offset int, filename string, line int) {
f.set.mutex.Lock()
if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
f.infos = append(f.infos, lineInfo{offset, filename, line})
}
f.set.mutex.Unlock()
}
// Pos returns the Pos value for the given file offset;
// the offset must be <= f.Size().
// f.Pos(f.Offset(p)) == p.
//
func (f *File) Pos(offset int) Pos {
if offset > f.size {
panic("illegal file offset")
}
return Pos(f.base + offset)
}
// Offset returns the offset for the given file position p;
// p must be a valid Pos value in that file.
// f.Offset(f.Pos(offset)) == offset.
//
func (f *File) Offset(p Pos) int {
if int(p) < f.base || int(p) > f.base+f.size {
panic("illegal Pos value")
}
return int(p) - f.base
}
// Line returns the line number for the given file position p;
// p must be a Pos value in that file or NoPos.
//
func (f *File) Line(p Pos) int {
// TODO(gri) this can be implemented much more efficiently
return f.Position(p).Line
}
func searchLineInfos(a []lineInfo, x int) int {
return sort.Search(len(a), func(i int) bool { return a[i].Offset > x }) - 1
}
// info returns the file name, line, and column number for a file offset.
func (f *File) info(offset int) (filename string, line, column int) {
filename = f.name
if i := searchInts(f.lines, offset); i >= 0 {
line, column = i+1, offset-f.lines[i]+1
}
if len(f.infos) > 0 {
// almost no files have extra line infos
if i := searchLineInfos(f.infos, offset); i >= 0 {
alt := &f.infos[i]
filename = alt.Filename
if i := searchInts(f.lines, alt.Offset); i >= 0 {
line += alt.Line - i - 1
}
}
}
return
}
func (f *File) position(p Pos) (pos Position) {
offset := int(p) - f.base
pos.Offset = offset
pos.Filename, pos.Line, pos.Column = f.info(offset)
return
}
// Position returns the Position value for the given file position p;
// p must be a Pos value in that file or NoPos.
//
func (f *File) Position(p Pos) (pos Position) {
if p != NoPos {
if int(p) < f.base || int(p) > f.base+f.size {
panic("illegal Pos value")
}
pos = f.position(p)
}
return
}
// -----------------------------------------------------------------------------
// FileSet
// A FileSet represents a set of source files.
// Methods of file sets are synchronized; multiple goroutines
// may invoke them concurrently.
//
type FileSet struct {
mutex sync.RWMutex // protects the file set
base int // base offset for the next file
files []*File // list of files in the order added to the set
last *File // cache of last file looked up
}
// NewFileSet creates a new file set.
func NewFileSet() *FileSet {
s := new(FileSet)
s.base = 1 // 0 == NoPos
return s
}
// Base returns the minimum base offset that must be provided to
// AddFile when adding the next file.
//
func (s *FileSet) Base() int {
s.mutex.RLock()
b := s.base
s.mutex.RUnlock()
return b
}
// AddFile adds a new file with a given filename, base offset, and file size
// to the file set s and returns the file. Multiple files may have the same
// name. The base offset must not be smaller than the FileSet's Base(), and
// size must not be negative.
//
// Adding the file will set the file set's Base() value to base + size + 1
// as the minimum base value for the next file. The following relationship
// exists between a Pos value p for a given file offset offs:
//
// int(p) = base + offs
//
// with offs in the range [0, size] and thus p in the range [base, base+size].
// For convenience, File.Pos may be used to create file-specific position
// values from a file offset.
//
func (s *FileSet) AddFile(filename string, base, size int) *File {
s.mutex.Lock()
defer s.mutex.Unlock()
if base < s.base || size < 0 {
panic("illegal base or size")
}
// base >= s.base && size >= 0
f := &File{s, filename, base, size, []int{0}, nil}
base += size + 1 // +1 because EOF also has a position
if base < 0 {
panic("token.Pos offset overflow (> 2G of source code in file set)")
}
// add the file to the file set
s.base = base
s.files = append(s.files, f)
s.last = f
return f
}
// Iterate calls f for the files in the file set in the order they were added
// until f returns false.
//
func (s *FileSet) Iterate(f func(*File) bool) {
for i := 0; ; i++ {
var file *File
s.mutex.RLock()
if i < len(s.files) {
file = s.files[i]
}
s.mutex.RUnlock()
if file == nil || !f(file) {
break
}
}
}
func searchFiles(a []*File, x int) int {
return sort.Search(len(a), func(i int) bool { return a[i].base > x }) - 1
}
func (s *FileSet) file(p Pos) *File {
// common case: p is in last file
if f := s.last; f != nil && f.base <= int(p) && int(p) <= f.base+f.size {
return f
}
// p is not in last file - search all files
if i := searchFiles(s.files, int(p)); i >= 0 {
f := s.files[i]
// f.base <= int(p) by definition of searchFiles
if int(p) <= f.base+f.size {
s.last = f
return f
}
}
return nil
}
// File returns the file that contains the position p.
// If no such file is found (for instance for p == NoPos),
// the result is nil.
//
func (s *FileSet) File(p Pos) (f *File) {
if p != NoPos {
s.mutex.RLock()
f = s.file(p)
s.mutex.RUnlock()
}
return
}
// Position converts a Pos in the fileset into a general Position.
func (s *FileSet) Position(p Pos) (pos Position) {
if p != NoPos {
s.mutex.RLock()
if f := s.file(p); f != nil {
pos = f.position(p)
}
s.mutex.RUnlock()
}
return
}
// -----------------------------------------------------------------------------
// Helper functions
func searchInts(a []int, x int) int {
// This function body is a manually inlined version of:
//
// return sort.Search(len(a), func(i int) bool { return a[i] > x }) - 1
//
// With better compiler optimizations, this may not be needed in the
// future, but at the moment this change improves the go/printer
// benchmark performance by ~30%. This has a direct impact on the
// speed of gofmt and thus seems worthwhile (2011-04-29).
// TODO(gri): Remove this when compilers have caught up.
i, j := 0, len(a)
for i < j {
h := i + (j-i)/2 // avoid overflow when computing h
// i ≤ h < j
if a[h] <= x {
i = h + 1
} else {
j = h
}
}
return i - 1
}
================================================
FILE: vendor/github.com/go-git/gcfg/token/serialize.go
================================================
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package token
type serializedFile struct {
// fields correspond 1:1 to fields with same (lower-case) name in File
Name string
Base int
Size int
Lines []int
Infos []lineInfo
}
type serializedFileSet struct {
Base int
Files []serializedFile
}
// Read calls decode to deserialize a file set into s; s must not be nil.
func (s *FileSet) Read(decode func(interface{}) error) error {
var ss serializedFileSet
if err := decode(&ss); err != nil {
return err
}
s.mutex.Lock()
s.base = ss.Base
files := make([]*File, len(ss.Files))
for i := 0; i < len(ss.Files); i++ {
f := &ss.Files[i]
files[i] = &File{s, f.Name, f.Base, f.Size, f.Lines, f.Infos}
}
s.files = files
s.last = nil
s.mutex.Unlock()
return nil
}
// Write calls encode to serialize the file set s.
func (s *FileSet) Write(encode func(interface{}) error) error {
var ss serializedFileSet
s.mutex.Lock()
ss.Base = s.base
files := make([]serializedFile, len(s.files))
for i, f := range s.files {
files[i] = serializedFile{f.name, f.base, f.size, f.lines, f.infos}
}
ss.Files = files
s.mutex.Unlock()
return encode(ss)
}
================================================
FILE: vendor/github.com/go-git/gcfg/token/token.go
================================================
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package token defines constants representing the lexical tokens of the gcfg
// configuration syntax and basic operations on tokens (printing, predicates).
//
// Note that the API for the token package may change to accommodate new
// features or implementation changes in gcfg.
//
package token
import "strconv"
// Token is the set of lexical tokens of the gcfg configuration syntax.
type Token int
// The list of tokens.
const (
// Special tokens
ILLEGAL Token = iota
EOF
COMMENT
literal_beg
// Identifiers and basic type literals
// (these tokens stand for classes of literals)
IDENT // section-name, variable-name
STRING // "subsection-name", variable value
literal_end
operator_beg
// Operators and delimiters
ASSIGN // =
LBRACK // [
RBRACK // ]
EOL // \n
operator_end
)
var tokens = [...]string{
ILLEGAL: "ILLEGAL",
EOF: "EOF",
COMMENT: "COMMENT",
IDENT: "IDENT",
STRING: "STRING",
ASSIGN: "=",
LBRACK: "[",
RBRACK: "]",
EOL: "\n",
}
// String returns the string corresponding to the token tok.
// For operators and delimiters, the string is the actual token character
// sequence (e.g., for the token ASSIGN, the string is "="). For all other
// tokens the string corresponds to the token constant name (e.g. for the
// token IDENT, the string is "IDENT").
//
func (tok Token) String() string {
s := ""
if 0 <= tok && tok < Token(len(tokens)) {
s = tokens[tok]
}
if s == "" {
s = "token(" + strconv.Itoa(int(tok)) + ")"
}
return s
}
// Predicates
// IsLiteral returns true for tokens corresponding to identifiers
// and basic type literals; it returns false otherwise.
//
func (tok Token) IsLiteral() bool { return literal_beg < tok && tok < literal_end }
// IsOperator returns true for tokens corresponding to operators and
// delimiters; it returns false otherwise.
//
func (tok Token) IsOperator() bool { return operator_beg < tok && tok < operator_end }
================================================
FILE: vendor/github.com/go-git/gcfg/types/bool.go
================================================
package types
// BoolValues defines the name and value mappings for ParseBool.
var BoolValues = map[string]interface{}{
"true": true, "yes": true, "on": true, "1": true,
"false": false, "no": false, "off": false, "0": false,
}
var boolParser = func() *EnumParser {
ep := &EnumParser{}
ep.AddVals(BoolValues)
return ep
}()
// ParseBool parses bool values according to the definitions in BoolValues.
// Parsing is case-insensitive.
func ParseBool(s string) (bool, error) {
v, err := boolParser.Parse(s)
if err != nil {
return false, err
}
return v.(bool), nil
}
================================================
FILE: vendor/github.com/go-git/gcfg/types/doc.go
================================================
// Package types defines helpers for type conversions.
//
// The API for this package is not finalized yet.
package types
================================================
FILE: vendor/github.com/go-git/gcfg/types/enum.go
================================================
package types
import (
"fmt"
"reflect"
"strings"
)
// EnumParser parses "enum" values; i.e. a predefined set of strings to
// predefined values.
type EnumParser struct {
Type string // type name; if not set, use type of first value added
CaseMatch bool // if true, matching of strings is case-sensitive
// PrefixMatch bool
vals map[string]interface{}
}
// AddVals adds strings and values to an EnumParser.
func (ep *EnumParser) AddVals(vals map[string]interface{}) {
if ep.vals == nil {
ep.vals = make(map[string]interface{})
}
for k, v := range vals {
if ep.Type == "" {
ep.Type = reflect.TypeOf(v).Name()
}
if !ep.CaseMatch {
k = strings.ToLower(k)
}
ep.vals[k] = v
}
}
// Parse parses the string and returns the value or an error.
func (ep EnumParser) Parse(s string) (interface{}, error) {
if !ep.CaseMatch {
s = strings.ToLower(s)
}
v, ok := ep.vals[s]
if !ok {
return false, fmt.Errorf("failed to parse %s %#q", ep.Type, s)
}
return v, nil
}
================================================
FILE: vendor/github.com/go-git/gcfg/types/int.go
================================================
package types
import (
"fmt"
"strings"
)
// An IntMode is a mode for parsing integer values, representing a set of
// accepted bases.
type IntMode uint8
// IntMode values for ParseInt; can be combined using binary or.
const (
Dec IntMode = 1 << iota
Hex
Oct
)
// String returns a string representation of IntMode; e.g. `IntMode(Dec|Hex)`.
func (m IntMode) String() string {
var modes []string
if m&Dec != 0 {
modes = append(modes, "Dec")
}
if m&Hex != 0 {
modes = append(modes, "Hex")
}
if m&Oct != 0 {
modes = append(modes, "Oct")
}
return "IntMode(" + strings.Join(modes, "|") + ")"
}
var errIntAmbig = fmt.Errorf("ambiguous integer value; must include '0' prefix")
func prefix0(val string) bool {
return strings.HasPrefix(val, "0") || strings.HasPrefix(val, "-0")
}
func prefix0x(val string) bool {
return strings.HasPrefix(val, "0x") || strings.HasPrefix(val, "-0x")
}
// ParseInt parses val using mode into intptr, which must be a pointer to an
// integer kind type. Non-decimal value require prefix `0` or `0x` in the cases
// when mode permits ambiguity of base; otherwise the prefix can be omitted.
func ParseInt(intptr interface{}, val string, mode IntMode) error {
val = strings.TrimSpace(val)
verb := byte(0)
switch mode {
case Dec:
verb = 'd'
case Dec + Hex:
if prefix0x(val) {
verb = 'v'
} else {
verb = 'd'
}
case Dec + Oct:
if prefix0(val) && !prefix0x(val) {
verb = 'v'
} else {
verb = 'd'
}
case Dec + Hex + Oct:
verb = 'v'
case Hex:
if prefix0x(val) {
verb = 'v'
} else {
verb = 'x'
}
case Oct:
verb = 'o'
case Hex + Oct:
if prefix0(val) {
verb = 'v'
} else {
return errIntAmbig
}
}
if verb == 0 {
panic("unsupported mode")
}
return ScanFully(intptr, val, verb)
}
================================================
FILE: vendor/github.com/go-git/gcfg/types/scan.go
================================================
package types
import (
"fmt"
"io"
"reflect"
)
// ScanFully uses fmt.Sscanf with verb to fully scan val into ptr.
func ScanFully(ptr interface{}, val string, verb byte) error {
t := reflect.ValueOf(ptr).Elem().Type()
// attempt to read extra bytes to make sure the value is consumed
var b []byte
n, err := fmt.Sscanf(val, "%"+string(verb)+"%s", ptr, &b)
switch {
case n < 1 || n == 1 && err != io.EOF:
return fmt.Errorf("failed to parse %q as %v: %v", val, t, err)
case n > 1:
return fmt.Errorf("failed to parse %q as %v: extra characters %q", val, t, string(b))
}
// n == 1 && err == io.EOF
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/.gitignore
================================================
coverage.out
*~
coverage.txt
profile.out
.tmp/
.git-dist/
.vscode
================================================
FILE: vendor/github.com/go-git/go-git/v5/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
education, socio-economic status, nationality, personal appearance, race,
religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at conduct@sourced.tech. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
================================================
FILE: vendor/github.com/go-git/go-git/v5/COMPATIBILITY.md
================================================
# Supported Features
Here is a non-comprehensive table of git commands and features and their
compatibility status with go-git.
## Getting and creating repositories
| Feature | Sub-feature | Status | Notes | Examples |
| ------- | ------------------------------------------------------------------------------------------------------------------ | ------ | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `init` | | ✅ | | |
| `init` | `--bare` | ✅ | | |
| `init` | `--template` `--separate-git-dir` `--shared` | ❌ | | |
| `clone` | | ✅ | | - [PlainClone](_examples/clone/main.go) |
| `clone` | Authentication: - none - access token - username + password - ssh | ✅ | | - [clone ssh (private_key)](_examples/clone/auth/ssh/private_key/main.go) - [clone ssh (ssh_agent)](_examples/clone/auth/ssh/ssh_agent/main.go) - [clone access token](_examples/clone/auth/basic/access_token/main.go) - [clone user + password](_examples/clone/auth/basic/username_password/main.go) |
| `clone` | `--progress` `--single-branch` `--depth` `--origin` `--recurse-submodules` `--shared` | ✅ | | - [recurse submodules](_examples/clone/main.go) - [progress](_examples/progress/main.go) |
## Basic snapshotting
| Feature | Sub-feature | Status | Notes | Examples |
| -------- | ----------- | ------ | -------------------------------------------------------- | ------------------------------------ |
| `add` | | ✅ | Plain add is supported. Any other flags aren't supported | |
| `status` | | ✅ | | |
| `commit` | | ✅ | | - [commit](_examples/commit/main.go) |
| `reset` | | ✅ | | |
| `rm` | | ✅ | | |
| `mv` | | ✅ | | |
## Branching and merging
| Feature | Sub-feature | Status | Notes | Examples |
| ----------- | ----------- | ------------ | --------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `branch` | | ✅ | | - [branch](_examples/branch/main.go) |
| `checkout` | | ✅ | Basic usages of checkout are supported. | - [checkout](_examples/checkout/main.go) |
| `merge` | | ⚠️ (partial) | Fast-forward only | |
| `mergetool` | | ❌ | | |
| `stash` | | ❌ | | |
| `sparse-checkout` | | ✅ | | - [sparse-checkout](_examples/sparse-checkout/main.go) |
| `tag` | | ✅ | | - [tag](_examples/tag/main.go) - [tag create and push](_examples/tag-create-push/main.go) |
## Sharing and updating projects
| Feature | Sub-feature | Status | Notes | Examples |
| ----------- | ----------- | ------ | ----------------------------------------------------------------------- | ------------------------------------------ |
| `fetch` | | ✅ | | |
| `pull` | | ✅ | Only supports merges where the merge can be resolved as a fast-forward. | - [pull](_examples/pull/main.go) |
| `push` | | ✅ | | - [push](_examples/push/main.go) |
| `remote` | | ✅ | | - [remotes](_examples/remotes/main.go) |
| `submodule` | | ✅ | | - [submodule](_examples/submodule/main.go) |
| `submodule` | deinit | ❌ | | |
## Inspection and comparison
| Feature | Sub-feature | Status | Notes | Examples |
| ---------- | ----------- | --------- | ----- | ------------------------------ |
| `show` | | ✅ | | |
| `log` | | ✅ | | - [log](_examples/log/main.go) |
| `shortlog` | | (see log) | | |
| `describe` | | ❌ | | |
## Patching
| Feature | Sub-feature | Status | Notes | Examples |
| ------------- | ----------- | ------ | ---------------------------------------------------- | -------- |
| `apply` | | ❌ | | |
| `cherry-pick` | | ❌ | | |
| `diff` | | ✅ | Patch object with UnifiedDiff output representation. | |
| `rebase` | | ❌ | | |
| `revert` | | ❌ | | |
## Debugging
| Feature | Sub-feature | Status | Notes | Examples |
| -------- | ----------- | ------ | ----- | ---------------------------------- |
| `bisect` | | ❌ | | |
| `blame` | | ✅ | | - [blame](_examples/blame/main.go) |
| `grep` | | ✅ | | |
## Email
| Feature | Sub-feature | Status | Notes | Examples |
| -------------- | ----------- | ------ | ----- | -------- |
| `am` | | ❌ | | |
| `apply` | | ❌ | | |
| `format-patch` | | ❌ | | |
| `send-email` | | ❌ | | |
| `request-pull` | | ❌ | | |
## External systems
| Feature | Sub-feature | Status | Notes | Examples |
| ------------- | ----------- | ------ | ----- | -------- |
| `svn` | | ❌ | | |
| `fast-import` | | ❌ | | |
| `lfs` | | ❌ | | |
## Administration
| Feature | Sub-feature | Status | Notes | Examples |
| --------------- | ----------- | ------ | ----- | -------- |
| `clean` | | ✅ | | |
| `gc` | | ❌ | | |
| `fsck` | | ❌ | | |
| `reflog` | | ❌ | | |
| `filter-branch` | | ❌ | | |
| `instaweb` | | ❌ | | |
| `archive` | | ❌ | | |
| `bundle` | | ❌ | | |
| `prune` | | ❌ | | |
| `repack` | | ❌ | | |
## Server admin
| Feature | Sub-feature | Status | Notes | Examples |
| -------------------- | ----------- | ------ | ----- | ----------------------------------------- |
| `daemon` | | ❌ | | |
| `update-server-info` | | ✅ | | [cli](./cli/go-git/update_server_info.go) |
## Advanced
| Feature | Sub-feature | Status | Notes | Examples |
| ---------- | ----------- | ----------- | ----- | -------- |
| `notes` | | ❌ | | |
| `replace` | | ❌ | | |
| `worktree` | | ❌ | | |
| `annotate` | | (see blame) | | |
## GPG
| Feature | Sub-feature | Status | Notes | Examples |
| ------------------- | ----------- | ------ | ----- | -------- |
| `git-verify-commit` | | ✅ | | |
| `git-verify-tag` | | ✅ | | |
## Plumbing commands
| Feature | Sub-feature | Status | Notes | Examples |
| --------------- | ------------------------------------- | ------------ | --------------------------------------------------- | -------------------------------------------- |
| `cat-file` | | ✅ | | |
| `check-ignore` | | ❌ | | |
| `commit-tree` | | ❌ | | |
| `count-objects` | | ❌ | | |
| `diff-index` | | ❌ | | |
| `for-each-ref` | | ✅ | | |
| `hash-object` | | ✅ | | |
| `ls-files` | | ✅ | | |
| `ls-remote` | | ✅ | | - [ls-remote](_examples/ls-remote/main.go) |
| `merge-base` | `--independent` `--is-ancestor` | ⚠️ (partial) | Calculates the merge-base only between two commits. | - [merge-base](_examples/merge_base/main.go) |
| `merge-base` | `--fork-point` `--octopus` | ❌ | | |
| `read-tree` | | ❌ | | |
| `rev-list` | | ✅ | | |
| `rev-parse` | | ❌ | | |
| `show-ref` | | ✅ | | |
| `symbolic-ref` | | ✅ | | |
| `update-index` | | ❌ | | |
| `update-ref` | | ❌ | | |
| `verify-pack` | | ❌ | | |
| `write-tree` | | ❌ | | |
## Indexes and Git Protocols
| Feature | Version | Status | Notes |
| -------------------- | ------------------------------------------------------------------------------- | ------ | ----- |
| index | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ❌ | |
| index | [v2](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ✅ | |
| index | [v3](https://github.com/git/git/blob/master/Documentation/gitformat-index.txt) | ❌ | |
| pack-protocol | [v1](https://github.com/git/git/blob/master/Documentation/gitprotocol-pack.txt) | ✅ | |
| pack-protocol | [v2](https://github.com/git/git/blob/master/Documentation/gitprotocol-v2.txt) | ❌ | |
| multi-pack-index | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | |
| pack-\*.rev files | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | |
| pack-\*.mtimes files | [v1](https://github.com/git/git/blob/master/Documentation/gitformat-pack.txt) | ❌ | |
| cruft packs | | ❌ | |
## Capabilities
| Feature | Status | Notes |
| ------------------------------ | ------------ | ----- |
| `multi_ack` | ❌ | |
| `multi_ack_detailed` | ❌ | |
| `no-done` | ❌ | |
| `thin-pack` | ❌ | |
| `side-band` | ⚠️ (partial) | |
| `side-band-64k` | ⚠️ (partial) | |
| `ofs-delta` | ✅ | |
| `agent` | ✅ | |
| `object-format` | ❌ | |
| `symref` | ✅ | |
| `shallow` | ✅ | |
| `deepen-since` | ✅ | |
| `deepen-not` | ❌ | |
| `deepen-relative` | ❌ | |
| `no-progress` | ✅ | |
| `include-tag` | ✅ | |
| `report-status` | ✅ | |
| `report-status-v2` | ❌ | |
| `delete-refs` | ✅ | |
| `quiet` | ❌ | |
| `atomic` | ✅ | |
| `push-options` | ✅ | |
| `allow-tip-sha1-in-want` | ✅ | |
| `allow-reachable-sha1-in-want` | ❌ | |
| `push-cert=` | ❌ | |
| `filter` | ❌ | |
| `session-id=` | ❌ | |
## Transport Schemes
| Scheme | Status | Notes | Examples |
| -------------------- | ------------ | ---------------------------------------------------------------------- | ---------------------------------------------- |
| `http(s)://` (dumb) | ❌ | | |
| `http(s)://` (smart) | ✅ | | |
| `git://` | ✅ | | |
| `ssh://` | ✅ | | |
| `file://` | ⚠️ (partial) | Warning: this is not pure Golang. This shells out to the `git` binary. | |
| Custom | ✅ | All existing schemes can be replaced by custom implementations. | - [custom_http](_examples/custom_http/main.go) |
## SHA256
| Feature | Sub-feature | Status | Notes | Examples |
| -------- | ----------- | ------ | ---------------------------------- | ------------------------------------ |
| `init` | | ✅ | Requires building with tag sha256. | - [init](_examples/sha256/main.go) |
| `commit` | | ✅ | Requires building with tag sha256. | - [commit](_examples/sha256/main.go) |
| `pull` | | ❌ | | |
| `fetch` | | ❌ | | |
| `push` | | ❌ | | |
## Other features
| Feature | Sub-feature | Status | Notes | Examples |
| --------------- | --------------------------- | ------ | ---------------------------------------------- | -------- |
| `config` | `--local` | ✅ | Read and write per-repository (`.git/config`). | |
| `config` | `--global` `--system` | ✅ | Read-only. | |
| `gitignore` | | ✅ | | |
| `gitattributes` | | ✅ | | |
| `git-worktree` | | ❌ | Multiple worktrees are not supported. | |
================================================
FILE: vendor/github.com/go-git/go-git/v5/CONTRIBUTING.md
================================================
# Contributing Guidelines
source{d} go-git project is [Apache 2.0 licensed](LICENSE) and accepts
contributions via GitHub pull requests. This document outlines some of the
conventions on development workflow, commit message formatting, contact points,
and other resources to make it easier to get your contribution accepted.
## Support Channels
The official support channels, for both users and contributors, are:
- [StackOverflow go-git tag](https://stackoverflow.com/questions/tagged/go-git) for user questions.
- GitHub [Issues](https://github.com/src-d/go-git/issues)* for bug reports and feature requests.
*Before opening a new issue or submitting a new pull request, it's helpful to
search the project - it's likely that another user has already reported the
issue you're facing, or it's a known issue that we're already aware of.
## How to Contribute
Pull Requests (PRs) are the main and exclusive way to contribute to the official go-git project.
In order for a PR to be accepted it needs to pass a list of requirements:
- You should be able to run the same query using `git`. We don't accept features that are not implemented in the official git implementation.
- The expected behavior must match the [official git implementation](https://github.com/git/git).
- The actual behavior must be correctly explained with natural language and providing a minimum working example in Go that reproduces it.
- All PRs must be written in idiomatic Go, formatted according to [gofmt](https://golang.org/cmd/gofmt/), and without any warnings from [go lint](https://github.com/golang/lint) nor [go vet](https://golang.org/cmd/vet/).
- They should in general include tests, and those shall pass.
- If the PR is a bug fix, it has to include a suite of unit tests for the new functionality.
- If the PR is a new feature, it has to come with a suite of unit tests, that tests the new functionality.
- In any case, all the PRs have to pass the personal evaluation of at least one of the maintainers of go-git.
### Branches
The `master` branch is currently used for maintaining the `v5` major release only. The accepted changes would
be dependency bumps, bug fixes and small changes that aren't needed for `v6`. New development should target the
`v6-exp` branch, and if agreed with at least one go-git maintainer, it can be back ported to `v5` by creating
a new PR that targets `master`.
### Format of the commit message
Every commit message should describe what was changed, under which context and, if applicable, the GitHub issue it relates to:
```
plumbing: packp, Skip argument validations for unknown capabilities. Fixes #623
```
The format can be described more formally as follows:
```
: , . [Fixes #]
```
================================================
FILE: vendor/github.com/go-git/go-git/v5/EXTENDING.md
================================================
# Extending go-git
`go-git` was built in a highly extensible manner, which enables some of its functionalities to be changed or extended without the need of changing its codebase. Here are the key extensibility features:
## Dot Git Storers
Dot git storers are the components responsible for storing the Git internal files, including objects and references.
The built-in storer implementations include [memory](storage/memory) and [filesystem](storage/filesystem). The `memory` storer stores all the data in memory, and its use look like this:
```go
r, err := git.Init(memory.NewStorage(), nil)
```
The `filesystem` storer stores the data in the OS filesystem, and can be used as follows:
```go
r, err := git.Init(filesystem.NewStorage(osfs.New("/tmp/foo")), nil)
```
New implementations can be created by implementing the [storage.Storer interface](storage/storer.go#L16).
## Filesystem
Git repository worktrees are managed using a filesystem abstraction based on [go-billy](https://github.com/go-git/go-billy). The Git operations will take place against the specific filesystem implementation. Initialising a repository in Memory can be done as follows:
```go
fs := memfs.New()
r, err := git.Init(memory.NewStorage(), fs)
```
The same operation can be done against the OS filesystem:
```go
fs := osfs.New("/tmp/foo")
r, err := git.Init(memory.NewStorage(), fs)
```
New filesystems (e.g. cloud based storage) could be created by implementing `go-billy`'s [Filesystem interface](https://github.com/go-git/go-billy/blob/326c59f064021b821a55371d57794fbfb86d4cb3/fs.go#L52).
## Transport Schemes
Git supports various transport schemes, including `http`, `https`, `ssh`, `git`, `file`. `go-git` defines the [transport.Transport interface](plumbing/transport/common.go#L48) to represent them.
The built-in implementations can be replaced by calling `client.InstallProtocol`.
An example of changing the built-in `https` implementation to skip TLS could look like this:
```go
customClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
client.InstallProtocol("https", githttp.NewClient(customClient))
```
Some internal implementations enables code reuse amongst the different transport implementations. Some of these may be made public in the future (e.g. `plumbing/transport/internal/common`).
## Cache
Several different operations across `go-git` lean on caching of objects in order to achieve optimal performance. The caching functionality is defined by the [cache.Object interface](plumbing/cache/common.go#L17).
Two built-in implementations are `cache.ObjectLRU` and `cache.BufferLRU`. However, the caching functionality can be customized by implementing the interface `cache.Object` interface.
## Hash
`go-git` uses the `crypto.Hash` interface to represent hash functions. The built-in implementations are `github.com/pjbgf/sha1cd` for SHA1 and Go's `crypto/SHA256`.
The default hash functions can be changed by calling `hash.RegisterHash`.
```go
func init() {
hash.RegisterHash(crypto.SHA1, sha1.New)
}
```
New `SHA1` or `SHA256` hash functions that implement the `hash.RegisterHash` interface can be registered by calling `RegisterHash`.
================================================
FILE: vendor/github.com/go-git/go-git/v5/LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2018 Sourced Technologies, S.L.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: vendor/github.com/go-git/go-git/v5/Makefile
================================================
# General
WORKDIR = $(PWD)
# Go parameters
GOCMD = go
GOTEST = $(GOCMD) test
# Git config
GIT_VERSION ?=
GIT_DIST_PATH ?= $(PWD)/.git-dist
GIT_REPOSITORY = http://github.com/git/git.git
# Coverage
COVERAGE_REPORT = coverage.out
COVERAGE_MODE = count
build-git:
@if [ -f $(GIT_DIST_PATH)/git ]; then \
echo "nothing to do, using cache $(GIT_DIST_PATH)"; \
else \
git clone $(GIT_REPOSITORY) -b $(GIT_VERSION) --depth 1 --single-branch $(GIT_DIST_PATH); \
cd $(GIT_DIST_PATH); \
make configure; \
./configure; \
make all; \
fi
test:
@echo "running against `git version`"; \
$(GOTEST) -race ./...
$(GOTEST) -v _examples/common_test.go _examples/common.go --examples
TEMP_REPO := $(shell mktemp)
test-sha256:
$(GOCMD) run -tags sha256 _examples/sha256/main.go $(TEMP_REPO)
cd $(TEMP_REPO) && git fsck
rm -rf $(TEMP_REPO)
test-coverage:
@echo "running against `git version`"; \
echo "" > $(COVERAGE_REPORT); \
$(GOTEST) -coverprofile=$(COVERAGE_REPORT) -coverpkg=./... -covermode=$(COVERAGE_MODE) ./...
clean:
rm -rf $(GIT_DIST_PATH)
fuzz:
@go test -fuzz=FuzzParser $(PWD)/internal/revision
@go test -fuzz=FuzzDecoder $(PWD)/plumbing/format/config
@go test -fuzz=FuzzPatchDelta $(PWD)/plumbing/format/packfile
@go test -fuzz=FuzzParseSignedBytes $(PWD)/plumbing/object
@go test -fuzz=FuzzDecode $(PWD)/plumbing/object
@go test -fuzz=FuzzDecoder $(PWD)/plumbing/protocol/packp
@go test -fuzz=FuzzNewEndpoint $(PWD)/plumbing/transport
================================================
FILE: vendor/github.com/go-git/go-git/v5/README.md
================================================

[](https://pkg.go.dev/github.com/go-git/go-git/v5) [](https://github.com/go-git/go-git/actions) [](https://goreportcard.com/report/github.com/go-git/go-git)
*go-git* is a highly extensible git implementation library written in **pure Go**.
It can be used to manipulate git repositories at low level *(plumbing)* or high level *(porcelain)*, through an idiomatic Go API. It also supports several types of storage, such as in-memory filesystems, or custom implementations, thanks to the [`Storer`](https://pkg.go.dev/github.com/go-git/go-git/v5/plumbing/storer) interface.
It's being actively developed since 2015 and is being used extensively by [Keybase](https://keybase.io/blog/encrypted-git-for-everyone), [Gitea](https://gitea.io/en-us/) or [Pulumi](https://github.com/search?q=org%3Apulumi+go-git&type=Code), and by many other libraries and tools.
Project Status
--------------
After the legal issues with the [`src-d`](https://github.com/src-d) organization, the lack of update for four months and the requirement to make a hard fork, the project is **now back to normality**.
The project is currently actively maintained by individual contributors, including several of the original authors, but also backed by a new company, [gitsight](https://github.com/gitsight), where `go-git` is a critical component used at scale.
Comparison with git
-------------------
*go-git* aims to be fully compatible with [git](https://github.com/git/git), all the *porcelain* operations are implemented to work exactly as *git* does.
*git* is a humongous project with years of development by thousands of contributors, making it challenging for *go-git* to implement all the features. You can find a comparison of *go-git* vs *git* in the [compatibility documentation](COMPATIBILITY.md).
Installation
------------
The recommended way to install *go-git* is:
```go
import "github.com/go-git/go-git/v5" // with go modules enabled (GO111MODULE=on or outside GOPATH)
import "github.com/go-git/go-git" // with go modules disabled
```
Examples
--------
> Please note that the `CheckIfError` and `Info` functions used in the examples are from the [examples package](https://github.com/go-git/go-git/blob/master/_examples/common.go#L19) just to be used in the examples.
### Basic example
A basic example that mimics the standard `git clone` command
```go
// Clone the given repository to the given directory
Info("git clone https://github.com/go-git/go-git")
_, err := git.PlainClone("/tmp/foo", false, &git.CloneOptions{
URL: "https://github.com/go-git/go-git",
Progress: os.Stdout,
})
CheckIfError(err)
```
Outputs:
```
Counting objects: 4924, done.
Compressing objects: 100% (1333/1333), done.
Total 4924 (delta 530), reused 6 (delta 6), pack-reused 3533
```
### In-memory example
Cloning a repository into memory and printing the history of HEAD, just like `git log` does
```go
// Clones the given repository in memory, creating the remote, the local
// branches and fetching the objects, exactly as:
Info("git clone https://github.com/go-git/go-billy")
r, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
URL: "https://github.com/go-git/go-billy",
})
CheckIfError(err)
// Gets the HEAD history from HEAD, just like this command:
Info("git log")
// ... retrieves the branch pointed by HEAD
ref, err := r.Head()
CheckIfError(err)
// ... retrieves the commit history
cIter, err := r.Log(&git.LogOptions{From: ref.Hash()})
CheckIfError(err)
// ... just iterates over the commits, printing it
err = cIter.ForEach(func(c *object.Commit) error {
fmt.Println(c)
return nil
})
CheckIfError(err)
```
Outputs:
```
commit ded8054fd0c3994453e9c8aacaf48d118d42991e
Author: Santiago M. Mola
Date: Sat Nov 12 21:18:41 2016 +0100
index: ReadFrom/WriteTo returns IndexReadError/IndexWriteError. (#9)
commit df707095626f384ce2dc1a83b30f9a21d69b9dfc
Author: Santiago M. Mola
Date: Fri Nov 11 13:23:22 2016 +0100
readwriter: fix bug when writing index. (#10)
When using ReadWriter on an existing siva file, absolute offset for
index entries was not being calculated correctly.
...
```
You can find this [example](_examples/log/main.go) and many others in the [examples](_examples) folder.
Contribute
----------
[Contributions](https://github.com/go-git/go-git/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) are more than welcome, if you are interested please take a look to
our [Contributing Guidelines](CONTRIBUTING.md).
License
-------
Apache License Version 2.0, see [LICENSE](LICENSE)
================================================
FILE: vendor/github.com/go-git/go-git/v5/SECURITY.md
================================================
# go-git Security Policy
The purpose of this security policy is to outline `go-git`'s process
for reporting, handling and disclosing security sensitive information.
## Supported Versions
The project follows a version support policy where only the latest minor
release is actively supported. Therefore, only issues that impact the latest
minor release will be fixed. Users are encouraged to upgrade to the latest
minor/patch release to benefit from the most up-to-date features, bug fixes,
and security enhancements.
The supported versions policy applies to both the `go-git` library and its
associated repositories within the `go-git` org.
## Reporting Security Issues
Please report any security vulnerabilities or potential weaknesses in `go-git`
privately via go-git-security@googlegroups.com. Do not publicly disclose the
details of the vulnerability until a fix has been implemented and released.
During the process the project maintainers will investigate the report, so please
provide detailed information, including steps to reproduce, affected versions, and any mitigations if known.
The project maintainers will acknowledge the receipt of the report and work with
the reporter to validate and address the issue.
Please note that `go-git` does not have any bounty programs, and therefore do
not provide financial compensation for disclosures.
## Security Disclosure Process
The project maintainers will make every effort to promptly address security issues.
Once a security vulnerability is fixed, a security advisory will be published to notify users and provide appropriate mitigation measures.
All `go-git` advisories can be found at https://github.com/go-git/go-git/security/advisories.
================================================
FILE: vendor/github.com/go-git/go-git/v5/blame.go
================================================
package git
import (
"bytes"
"container/heap"
"errors"
"fmt"
"io"
"strconv"
"time"
"unicode/utf8"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/utils/diff"
"github.com/sergi/go-diff/diffmatchpatch"
)
// BlameResult represents the result of a Blame operation.
type BlameResult struct {
// Path is the path of the File that we're blaming.
Path string
// Rev (Revision) is the hash of the specified Commit used to generate this result.
Rev plumbing.Hash
// Lines contains every line with its authorship.
Lines []*Line
}
// Blame returns a BlameResult with the information about the last author of
// each line from file `path` at commit `c`.
func Blame(c *object.Commit, path string) (*BlameResult, error) {
// The file to blame is identified by the input arguments:
// commit and path. commit is a Commit object obtained from a Repository. Path
// represents a path to a specific file contained in the repository.
//
// Blaming a file is done by walking the tree in reverse order trying to find where each line was last modified.
//
// When a diff is found it cannot immediately assume it came from that commit, as it may have come from 1 of its
// parents, so it will first try to resolve those diffs from its parents, if it couldn't find the change in its
// parents then it will assign the change to itself.
//
// When encountering 2 parents that have made the same change to a file it will choose the parent that was merged
// into the current branch first (this is determined by the order of the parents inside the commit).
//
// This currently works on a line by line basis, if performance becomes an issue it could be changed to work with
// hunks rather than lines. Then when encountering diff hunks it would need to split them where necessary.
b := new(blame)
b.fRev = c
b.path = path
b.q = new(priorityQueue)
file, err := b.fRev.File(path)
if err != nil {
return nil, err
}
finalLines, err := file.Lines()
if err != nil {
return nil, err
}
finalLength := len(finalLines)
needsMap := make([]lineMap, finalLength)
for i := range needsMap {
needsMap[i] = lineMap{i, i, nil, -1}
}
contents, err := file.Contents()
if err != nil {
return nil, err
}
b.q.Push(&queueItem{
nil,
nil,
c,
path,
contents,
needsMap,
0,
false,
0,
})
items := make([]*queueItem, 0)
for {
items = items[:0]
for {
if b.q.Len() == 0 {
return nil, errors.New("invalid state: no items left on the blame queue")
}
item := b.q.Pop()
items = append(items, item)
next := b.q.Peek()
if next == nil || next.Hash != item.Commit.Hash {
break
}
}
finished, err := b.addBlames(items)
if err != nil {
return nil, err
}
if finished {
break
}
}
b.lineToCommit = make([]*object.Commit, finalLength)
for i := range needsMap {
b.lineToCommit[i] = needsMap[i].Commit
}
lines, err := newLines(finalLines, b.lineToCommit)
if err != nil {
return nil, err
}
return &BlameResult{
Path: path,
Rev: c.Hash,
Lines: lines,
}, nil
}
// Line values represent the contents and author of a line in BlamedResult values.
type Line struct {
// Author is the email address of the last author that modified the line.
Author string
// AuthorName is the name of the last author that modified the line.
AuthorName string
// Text is the original text of the line.
Text string
// Date is when the original text of the line was introduced
Date time.Time
// Hash is the commit hash that introduced the original line
Hash plumbing.Hash
}
func newLine(author, authorName, text string, date time.Time, hash plumbing.Hash) *Line {
return &Line{
Author: author,
AuthorName: authorName,
Text: text,
Hash: hash,
Date: date,
}
}
func newLines(contents []string, commits []*object.Commit) ([]*Line, error) {
result := make([]*Line, 0, len(contents))
for i := range contents {
result = append(result, newLine(
commits[i].Author.Email, commits[i].Author.Name, contents[i],
commits[i].Author.When, commits[i].Hash,
))
}
return result, nil
}
// this struct is internally used by the blame function to hold its
// inputs, outputs and state.
type blame struct {
// the path of the file to blame
path string
// the commit of the final revision of the file to blame
fRev *object.Commit
// resolved lines
lineToCommit []*object.Commit
// queue of commits that need resolving
q *priorityQueue
}
type lineMap struct {
Orig, Cur int
Commit *object.Commit
FromParentNo int
}
func (b *blame) addBlames(curItems []*queueItem) (bool, error) {
curItem := curItems[0]
// Simple optimisation to merge paths, there is potential to go a bit further here and check for any duplicates
// not only if they are all the same.
if len(curItems) == 1 {
curItems = nil
} else if curItem.IdenticalToChild {
allSame := true
lenCurItems := len(curItems)
lowestParentNo := curItem.ParentNo
for i := 1; i < lenCurItems; i++ {
if !curItems[i].IdenticalToChild || curItem.Child != curItems[i].Child {
allSame = false
break
}
lowestParentNo = min(lowestParentNo, curItems[i].ParentNo)
}
if allSame {
curItem.Child.numParentsNeedResolving = curItem.Child.numParentsNeedResolving - lenCurItems + 1
curItems = nil // free the memory
curItem.ParentNo = lowestParentNo
// Now check if we can remove the parent completely
for curItem.Child.IdenticalToChild && curItem.Child.MergedChildren == nil && curItem.Child.numParentsNeedResolving == 1 {
oldChild := curItem.Child
curItem.Child = oldChild.Child
curItem.ParentNo = oldChild.ParentNo
}
}
}
// if we have more than 1 item for this commit, create a single needsMap
if len(curItems) > 1 {
curItem.MergedChildren = make([]childToNeedsMap, len(curItems))
for i, c := range curItems {
curItem.MergedChildren[i] = childToNeedsMap{c.Child, c.NeedsMap, c.IdenticalToChild, c.ParentNo}
}
newNeedsMap := make([]lineMap, 0, len(curItem.NeedsMap))
newNeedsMap = append(newNeedsMap, curItems[0].NeedsMap...)
for i := 1; i < len(curItems); i++ {
cur := curItems[i].NeedsMap
n := 0 // position in newNeedsMap
c := 0 // position in current list
for c < len(cur) {
if n == len(newNeedsMap) {
newNeedsMap = append(newNeedsMap, cur[c:]...)
break
} else if newNeedsMap[n].Cur == cur[c].Cur {
n++
c++
} else if newNeedsMap[n].Cur < cur[c].Cur {
n++
} else {
newNeedsMap = append(newNeedsMap, cur[c])
newPos := len(newNeedsMap) - 1
for newPos > n {
newNeedsMap[newPos-1], newNeedsMap[newPos] = newNeedsMap[newPos], newNeedsMap[newPos-1]
newPos--
}
}
}
}
curItem.NeedsMap = newNeedsMap
curItem.IdenticalToChild = false
curItem.Child = nil
curItems = nil // free the memory
}
parents, err := parentsContainingPath(curItem.path, curItem.Commit)
if err != nil {
return false, err
}
anyPushed := false
for parnetNo, prev := range parents {
currentHash, err := blobHash(curItem.path, curItem.Commit)
if err != nil {
return false, err
}
prevHash, err := blobHash(prev.Path, prev.Commit)
if err != nil {
return false, err
}
if currentHash == prevHash {
if len(parents) == 1 && curItem.MergedChildren == nil && curItem.IdenticalToChild {
// commit that has 1 parent and 1 child and is the same as both, bypass it completely
b.q.Push(&queueItem{
Child: curItem.Child,
Commit: prev.Commit,
path: prev.Path,
Contents: curItem.Contents,
NeedsMap: curItem.NeedsMap, // reuse the NeedsMap as we are throwing away this item
IdenticalToChild: true,
ParentNo: curItem.ParentNo,
})
} else {
b.q.Push(&queueItem{
Child: curItem,
Commit: prev.Commit,
path: prev.Path,
Contents: curItem.Contents,
NeedsMap: append([]lineMap(nil), curItem.NeedsMap...), // create new slice and copy
IdenticalToChild: true,
ParentNo: parnetNo,
})
curItem.numParentsNeedResolving++
}
anyPushed = true
continue
}
// get the contents of the file
file, err := prev.Commit.File(prev.Path)
if err != nil {
return false, err
}
prevContents, err := file.Contents()
if err != nil {
return false, err
}
hunks := diff.Do(prevContents, curItem.Contents)
prevl := -1
curl := -1
need := 0
getFromParent := make([]lineMap, 0)
out:
for h := range hunks {
hLines := countLines(hunks[h].Text)
for hl := 0; hl < hLines; hl++ {
switch hunks[h].Type {
case diffmatchpatch.DiffEqual:
prevl++
curl++
if curl == curItem.NeedsMap[need].Cur {
// add to needs
getFromParent = append(getFromParent, lineMap{curl, prevl, nil, -1})
// move to next need
need++
if need >= len(curItem.NeedsMap) {
break out
}
}
case diffmatchpatch.DiffInsert:
curl++
if curl == curItem.NeedsMap[need].Cur {
// the line we want is added, it may have been added here (or by another parent), skip it for now
need++
if need >= len(curItem.NeedsMap) {
break out
}
}
case diffmatchpatch.DiffDelete:
prevl += hLines
continue out
default:
return false, errors.New("invalid state: invalid hunk Type")
}
}
}
if len(getFromParent) > 0 {
b.q.Push(&queueItem{
curItem,
nil,
prev.Commit,
prev.Path,
prevContents,
getFromParent,
0,
false,
parnetNo,
})
curItem.numParentsNeedResolving++
anyPushed = true
}
}
curItem.Contents = "" // no longer need, free the memory
if !anyPushed {
return finishNeeds(curItem)
}
return false, nil
}
func finishNeeds(curItem *queueItem) (bool, error) {
// any needs left in the needsMap must have come from this revision
for i := range curItem.NeedsMap {
if curItem.NeedsMap[i].Commit == nil {
curItem.NeedsMap[i].Commit = curItem.Commit
curItem.NeedsMap[i].FromParentNo = -1
}
}
if curItem.Child == nil && curItem.MergedChildren == nil {
return true, nil
}
if curItem.MergedChildren == nil {
return applyNeeds(curItem.Child, curItem.NeedsMap, curItem.IdenticalToChild, curItem.ParentNo)
}
for _, ctn := range curItem.MergedChildren {
m := 0 // position in merged needs map
p := 0 // position in parent needs map
for p < len(ctn.NeedsMap) {
if ctn.NeedsMap[p].Cur == curItem.NeedsMap[m].Cur {
ctn.NeedsMap[p].Commit = curItem.NeedsMap[m].Commit
m++
p++
} else if ctn.NeedsMap[p].Cur < curItem.NeedsMap[m].Cur {
p++
} else {
m++
}
}
finished, err := applyNeeds(ctn.Child, ctn.NeedsMap, ctn.IdenticalToChild, ctn.ParentNo)
if finished || err != nil {
return finished, err
}
}
return false, nil
}
func applyNeeds(child *queueItem, needsMap []lineMap, identicalToChild bool, parentNo int) (bool, error) {
if identicalToChild {
for i := range child.NeedsMap {
l := &child.NeedsMap[i]
if l.Cur != needsMap[i].Cur || l.Orig != needsMap[i].Orig {
return false, errors.New("needsMap isn't the same? Why not??")
}
if l.Commit == nil || parentNo < l.FromParentNo {
l.Commit = needsMap[i].Commit
l.FromParentNo = parentNo
}
}
} else {
i := 0
out:
for j := range child.NeedsMap {
l := &child.NeedsMap[j]
for needsMap[i].Orig < l.Cur {
i++
if i == len(needsMap) {
break out
}
}
if l.Cur == needsMap[i].Orig {
if l.Commit == nil || parentNo < l.FromParentNo {
l.Commit = needsMap[i].Commit
l.FromParentNo = parentNo
}
}
}
}
child.numParentsNeedResolving--
if child.numParentsNeedResolving == 0 {
finished, err := finishNeeds(child)
if finished || err != nil {
return finished, err
}
}
return false, nil
}
// String prints the results of a Blame using git-blame's style.
func (b BlameResult) String() string {
var buf bytes.Buffer
// max line number length
mlnl := len(strconv.Itoa(len(b.Lines)))
// max author length
mal := b.maxAuthorLength()
format := fmt.Sprintf("%%s (%%-%ds %%s %%%dd) %%s\n", mal, mlnl)
for ln := range b.Lines {
_, _ = fmt.Fprintf(&buf, format, b.Lines[ln].Hash.String()[:8],
b.Lines[ln].AuthorName, b.Lines[ln].Date.Format("2006-01-02 15:04:05 -0700"), ln+1, b.Lines[ln].Text)
}
return buf.String()
}
// utility function to calculate the number of runes needed
// to print the longest author name in the blame of a file.
func (b BlameResult) maxAuthorLength() int {
m := 0
for ln := range b.Lines {
m = max(m, utf8.RuneCountInString(b.Lines[ln].AuthorName))
}
return m
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
type childToNeedsMap struct {
Child *queueItem
NeedsMap []lineMap
IdenticalToChild bool
ParentNo int
}
type queueItem struct {
Child *queueItem
MergedChildren []childToNeedsMap
Commit *object.Commit
path string
Contents string
NeedsMap []lineMap
numParentsNeedResolving int
IdenticalToChild bool
ParentNo int
}
type priorityQueueImp []*queueItem
func (pq *priorityQueueImp) Len() int { return len(*pq) }
func (pq *priorityQueueImp) Less(i, j int) bool {
return !(*pq)[i].Commit.Less((*pq)[j].Commit)
}
func (pq *priorityQueueImp) Swap(i, j int) { (*pq)[i], (*pq)[j] = (*pq)[j], (*pq)[i] }
func (pq *priorityQueueImp) Push(x any) { *pq = append(*pq, x.(*queueItem)) }
func (pq *priorityQueueImp) Pop() any {
n := len(*pq)
ret := (*pq)[n-1]
(*pq)[n-1] = nil // ovoid memory leak
*pq = (*pq)[0 : n-1]
return ret
}
func (pq *priorityQueueImp) Peek() *object.Commit {
if len(*pq) == 0 {
return nil
}
return (*pq)[0].Commit
}
type priorityQueue priorityQueueImp
func (pq *priorityQueue) Init() { heap.Init((*priorityQueueImp)(pq)) }
func (pq *priorityQueue) Len() int { return (*priorityQueueImp)(pq).Len() }
func (pq *priorityQueue) Push(c *queueItem) {
heap.Push((*priorityQueueImp)(pq), c)
}
func (pq *priorityQueue) Pop() *queueItem {
return heap.Pop((*priorityQueueImp)(pq)).(*queueItem)
}
func (pq *priorityQueue) Peek() *object.Commit { return (*priorityQueueImp)(pq).Peek() }
type parentCommit struct {
Commit *object.Commit
Path string
}
func parentsContainingPath(path string, c *object.Commit) ([]parentCommit, error) {
// TODO: benchmark this method making git.object.Commit.parent public instead of using
// an iterator
var result []parentCommit
iter := c.Parents()
for {
parent, err := iter.Next()
if err == io.EOF {
return result, nil
}
if err != nil {
return nil, err
}
if _, err := parent.File(path); err == nil {
result = append(result, parentCommit{parent, path})
} else {
// look for renames
patch, err := parent.Patch(c)
if err != nil {
return nil, err
} else if patch != nil {
for _, fp := range patch.FilePatches() {
from, to := fp.Files()
if from != nil && to != nil && to.Path() == path {
result = append(result, parentCommit{parent, from.Path()})
break
}
}
}
}
}
}
func blobHash(path string, commit *object.Commit) (plumbing.Hash, error) {
file, err := commit.File(path)
if err != nil {
return plumbing.ZeroHash, err
}
return file.Hash, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/common.go
================================================
package git
import "strings"
// countLines returns the number of lines in a string à la git, this is
// The newline character is assumed to be '\n'. The empty string
// contains 0 lines. If the last line of the string doesn't end with a
// newline, it will still be considered a line.
func countLines(s string) int {
if s == "" {
return 0
}
nEOL := strings.Count(s, "\n")
if strings.HasSuffix(s, "\n") {
return nEOL
}
return nEOL + 1
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/config/branch.go
================================================
package config
import (
"errors"
"strings"
"github.com/go-git/go-git/v5/plumbing"
format "github.com/go-git/go-git/v5/plumbing/format/config"
)
var (
errBranchEmptyName = errors.New("branch config: empty name")
errBranchInvalidMerge = errors.New("branch config: invalid merge")
errBranchInvalidRebase = errors.New("branch config: rebase must be one of 'true' or 'interactive'")
)
// Branch contains information on the
// local branches and which remote to track
type Branch struct {
// Name of branch
Name string
// Remote name of remote to track
Remote string
// Merge is the local refspec for the branch
Merge plumbing.ReferenceName
// Rebase instead of merge when pulling. Valid values are
// "true" and "interactive". "false" is undocumented and
// typically represented by the non-existence of this field
Rebase string
// Description explains what the branch is for.
// Multi-line explanations may be used.
//
// Original git command to edit:
// git branch --edit-description
Description string
raw *format.Subsection
}
// Validate validates fields of branch
func (b *Branch) Validate() error {
if b.Name == "" {
return errBranchEmptyName
}
if b.Merge != "" && !b.Merge.IsBranch() {
return errBranchInvalidMerge
}
if b.Rebase != "" &&
b.Rebase != "true" &&
b.Rebase != "interactive" &&
b.Rebase != "false" {
return errBranchInvalidRebase
}
return plumbing.NewBranchReferenceName(b.Name).Validate()
}
func (b *Branch) marshal() *format.Subsection {
if b.raw == nil {
b.raw = &format.Subsection{}
}
b.raw.Name = b.Name
if b.Remote == "" {
b.raw.RemoveOption(remoteSection)
} else {
b.raw.SetOption(remoteSection, b.Remote)
}
if b.Merge == "" {
b.raw.RemoveOption(mergeKey)
} else {
b.raw.SetOption(mergeKey, string(b.Merge))
}
if b.Rebase == "" {
b.raw.RemoveOption(rebaseKey)
} else {
b.raw.SetOption(rebaseKey, b.Rebase)
}
if b.Description == "" {
b.raw.RemoveOption(descriptionKey)
} else {
desc := quoteDescription(b.Description)
b.raw.SetOption(descriptionKey, desc)
}
return b.raw
}
// hack to trigger conditional quoting in the
// plumbing/format/config/Encoder.encodeOptions
//
// Current Encoder implementation uses Go %q format if value contains a backslash character,
// which is not consistent with reference git implementation.
// git just replaces newline characters with \n, while Encoder prints them directly.
// Until value quoting fix, we should escape description value by replacing newline characters with \n.
func quoteDescription(desc string) string {
return strings.ReplaceAll(desc, "\n", `\n`)
}
func (b *Branch) unmarshal(s *format.Subsection) error {
b.raw = s
b.Name = b.raw.Name
b.Remote = b.raw.Options.Get(remoteSection)
b.Merge = plumbing.ReferenceName(b.raw.Options.Get(mergeKey))
b.Rebase = b.raw.Options.Get(rebaseKey)
b.Description = unquoteDescription(b.raw.Options.Get(descriptionKey))
return b.Validate()
}
// hack to enable conditional quoting in the
// plumbing/format/config/Encoder.encodeOptions
// goto quoteDescription for details.
func unquoteDescription(desc string) string {
return strings.ReplaceAll(desc, `\n`, "\n")
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/config/config.go
================================================
// Package config contains the abstraction of multiple config files
package config
import (
"bytes"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strconv"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
format "github.com/go-git/go-git/v5/plumbing/format/config"
)
const (
// DefaultFetchRefSpec is the default refspec used for fetch.
DefaultFetchRefSpec = "+refs/heads/*:refs/remotes/%s/*"
// DefaultPushRefSpec is the default refspec used for push.
DefaultPushRefSpec = "refs/heads/*:refs/heads/*"
)
// ConfigStorer generic storage of Config object
type ConfigStorer interface {
Config() (*Config, error)
SetConfig(*Config) error
}
var (
ErrInvalid = errors.New("config invalid key in remote or branch")
ErrRemoteConfigNotFound = errors.New("remote config not found")
ErrRemoteConfigEmptyURL = errors.New("remote config: empty URL")
ErrRemoteConfigEmptyName = errors.New("remote config: empty name")
)
// Scope defines the scope of a config file, such as local, global or system.
type Scope int
// Available ConfigScope's
const (
LocalScope Scope = iota
GlobalScope
SystemScope
)
// Config contains the repository configuration
// https://www.kernel.org/pub/software/scm/git/docs/git-config.html#FILES
type Config struct {
Core struct {
// IsBare if true this repository is assumed to be bare and has no
// working directory associated with it.
IsBare bool
// Worktree is the path to the root of the working tree.
Worktree string
// CommentChar is the character indicating the start of a
// comment for commands like commit and tag
CommentChar string
// RepositoryFormatVersion identifies the repository format and layout version.
RepositoryFormatVersion format.RepositoryFormatVersion
}
User struct {
// Name is the personal name of the author and the committer of a commit.
Name string
// Email is the email of the author and the committer of a commit.
Email string
}
Author struct {
// Name is the personal name of the author of a commit.
Name string
// Email is the email of the author of a commit.
Email string
}
Committer struct {
// Name is the personal name of the committer of a commit.
Name string
// Email is the email of the committer of a commit.
Email string
}
Pack struct {
// Window controls the size of the sliding window for delta
// compression. The default is 10. A value of 0 turns off
// delta compression entirely.
Window uint
}
Init struct {
// DefaultBranch Allows overriding the default branch name
// e.g. when initializing a new repository or when cloning
// an empty repository.
DefaultBranch string
}
Extensions struct {
// ObjectFormat specifies the hash algorithm to use. The
// acceptable values are sha1 and sha256. If not specified,
// sha1 is assumed. It is an error to specify this key unless
// core.repositoryFormatVersion is 1.
//
// This setting must not be changed after repository initialization
// (e.g. clone or init).
ObjectFormat format.ObjectFormat
}
// Remotes list of repository remotes, the key of the map is the name
// of the remote, should equal to RemoteConfig.Name.
Remotes map[string]*RemoteConfig
// Submodules list of repository submodules, the key of the map is the name
// of the submodule, should equal to Submodule.Name.
Submodules map[string]*Submodule
// Branches list of branches, the key is the branch name and should
// equal Branch.Name
Branches map[string]*Branch
// URLs list of url rewrite rules, if repo url starts with URL.InsteadOf value, it will be replaced with the
// key instead.
URLs map[string]*URL
// Raw contains the raw information of a config file. The main goal is
// preserve the parsed information from the original format, to avoid
// dropping unsupported fields.
Raw *format.Config
}
// NewConfig returns a new empty Config.
func NewConfig() *Config {
config := &Config{
Remotes: make(map[string]*RemoteConfig),
Submodules: make(map[string]*Submodule),
Branches: make(map[string]*Branch),
URLs: make(map[string]*URL),
Raw: format.New(),
}
config.Pack.Window = DefaultPackWindow
return config
}
// ReadConfig reads a config file from a io.Reader.
func ReadConfig(r io.Reader) (*Config, error) {
b, err := io.ReadAll(r)
if err != nil {
return nil, err
}
cfg := NewConfig()
if err = cfg.Unmarshal(b); err != nil {
return nil, err
}
return cfg, nil
}
// LoadConfig loads a config file from a given scope. The returned Config,
// contains exclusively information from the given scope. If it couldn't find a
// config file to the given scope, an empty one is returned.
func LoadConfig(scope Scope) (*Config, error) {
if scope == LocalScope {
return nil, fmt.Errorf("LocalScope should be read from the a ConfigStorer")
}
files, err := Paths(scope)
if err != nil {
return nil, err
}
for _, file := range files {
f, err := osfs.Default.Open(file)
if err != nil {
if os.IsNotExist(err) {
continue
}
return nil, err
}
defer f.Close()
return ReadConfig(f)
}
return NewConfig(), nil
}
// Paths returns the config file location for a given scope.
func Paths(scope Scope) ([]string, error) {
var files []string
switch scope {
case GlobalScope:
xdg := os.Getenv("XDG_CONFIG_HOME")
if xdg != "" {
files = append(files, filepath.Join(xdg, "git/config"))
}
home, err := os.UserHomeDir()
if err != nil {
return nil, err
}
files = append(files,
filepath.Join(home, ".gitconfig"),
filepath.Join(home, ".config/git/config"),
)
case SystemScope:
files = append(files, "/etc/gitconfig")
}
return files, nil
}
// Validate validates the fields and sets the default values.
func (c *Config) Validate() error {
for name, r := range c.Remotes {
if r.Name != name {
return ErrInvalid
}
if err := r.Validate(); err != nil {
return err
}
}
for name, b := range c.Branches {
if b.Name != name {
return ErrInvalid
}
if err := b.Validate(); err != nil {
return err
}
}
return nil
}
const (
remoteSection = "remote"
submoduleSection = "submodule"
branchSection = "branch"
coreSection = "core"
packSection = "pack"
userSection = "user"
authorSection = "author"
committerSection = "committer"
initSection = "init"
urlSection = "url"
extensionsSection = "extensions"
fetchKey = "fetch"
urlKey = "url"
pushurlKey = "pushurl"
bareKey = "bare"
worktreeKey = "worktree"
commentCharKey = "commentChar"
windowKey = "window"
mergeKey = "merge"
rebaseKey = "rebase"
nameKey = "name"
emailKey = "email"
descriptionKey = "description"
defaultBranchKey = "defaultBranch"
repositoryFormatVersionKey = "repositoryformatversion"
objectFormat = "objectformat"
mirrorKey = "mirror"
// DefaultPackWindow holds the number of previous objects used to
// generate deltas. The value 10 is the same used by git command.
DefaultPackWindow = uint(10)
)
// Unmarshal parses a git-config file and stores it.
func (c *Config) Unmarshal(b []byte) error {
r := bytes.NewBuffer(b)
d := format.NewDecoder(r)
c.Raw = format.New()
if err := d.Decode(c.Raw); err != nil {
return err
}
c.unmarshalCore()
c.unmarshalUser()
c.unmarshalInit()
if err := c.unmarshalPack(); err != nil {
return err
}
unmarshalSubmodules(c.Raw, c.Submodules)
if err := c.unmarshalBranches(); err != nil {
return err
}
if err := c.unmarshalURLs(); err != nil {
return err
}
return c.unmarshalRemotes()
}
func (c *Config) unmarshalCore() {
s := c.Raw.Section(coreSection)
if s.Options.Get(bareKey) == "true" {
c.Core.IsBare = true
}
c.Core.Worktree = s.Options.Get(worktreeKey)
c.Core.CommentChar = s.Options.Get(commentCharKey)
}
func (c *Config) unmarshalUser() {
s := c.Raw.Section(userSection)
c.User.Name = s.Options.Get(nameKey)
c.User.Email = s.Options.Get(emailKey)
s = c.Raw.Section(authorSection)
c.Author.Name = s.Options.Get(nameKey)
c.Author.Email = s.Options.Get(emailKey)
s = c.Raw.Section(committerSection)
c.Committer.Name = s.Options.Get(nameKey)
c.Committer.Email = s.Options.Get(emailKey)
}
func (c *Config) unmarshalPack() error {
s := c.Raw.Section(packSection)
window := s.Options.Get(windowKey)
if window == "" {
c.Pack.Window = DefaultPackWindow
} else {
winUint, err := strconv.ParseUint(window, 10, 32)
if err != nil {
return err
}
c.Pack.Window = uint(winUint)
}
return nil
}
func (c *Config) unmarshalRemotes() error {
s := c.Raw.Section(remoteSection)
for _, sub := range s.Subsections {
r := &RemoteConfig{}
if err := r.unmarshal(sub); err != nil {
return err
}
c.Remotes[r.Name] = r
}
// Apply insteadOf url rules
for _, r := range c.Remotes {
r.applyURLRules(c.URLs)
}
return nil
}
func (c *Config) unmarshalURLs() error {
s := c.Raw.Section(urlSection)
for _, sub := range s.Subsections {
r := &URL{}
if err := r.unmarshal(sub); err != nil {
return err
}
c.URLs[r.Name] = r
}
return nil
}
func unmarshalSubmodules(fc *format.Config, submodules map[string]*Submodule) {
s := fc.Section(submoduleSection)
for _, sub := range s.Subsections {
m := &Submodule{}
m.unmarshal(sub)
if m.Validate() == ErrModuleBadPath {
continue
}
submodules[m.Name] = m
}
}
func (c *Config) unmarshalBranches() error {
bs := c.Raw.Section(branchSection)
for _, sub := range bs.Subsections {
b := &Branch{}
if err := b.unmarshal(sub); err != nil {
return err
}
c.Branches[b.Name] = b
}
return nil
}
func (c *Config) unmarshalInit() {
s := c.Raw.Section(initSection)
c.Init.DefaultBranch = s.Options.Get(defaultBranchKey)
}
// Marshal returns Config encoded as a git-config file.
func (c *Config) Marshal() ([]byte, error) {
c.marshalCore()
c.marshalExtensions()
c.marshalUser()
c.marshalPack()
c.marshalRemotes()
c.marshalSubmodules()
c.marshalBranches()
c.marshalURLs()
c.marshalInit()
buf := bytes.NewBuffer(nil)
if err := format.NewEncoder(buf).Encode(c.Raw); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func (c *Config) marshalCore() {
s := c.Raw.Section(coreSection)
s.SetOption(bareKey, fmt.Sprintf("%t", c.Core.IsBare))
if string(c.Core.RepositoryFormatVersion) != "" {
s.SetOption(repositoryFormatVersionKey, string(c.Core.RepositoryFormatVersion))
}
if c.Core.Worktree != "" {
s.SetOption(worktreeKey, c.Core.Worktree)
}
}
func (c *Config) marshalExtensions() {
// Extensions are only supported on Version 1, therefore
// ignore them otherwise.
if c.Core.RepositoryFormatVersion == format.Version_1 {
s := c.Raw.Section(extensionsSection)
s.SetOption(objectFormat, string(c.Extensions.ObjectFormat))
}
}
func (c *Config) marshalUser() {
s := c.Raw.Section(userSection)
if c.User.Name != "" {
s.SetOption(nameKey, c.User.Name)
}
if c.User.Email != "" {
s.SetOption(emailKey, c.User.Email)
}
s = c.Raw.Section(authorSection)
if c.Author.Name != "" {
s.SetOption(nameKey, c.Author.Name)
}
if c.Author.Email != "" {
s.SetOption(emailKey, c.Author.Email)
}
s = c.Raw.Section(committerSection)
if c.Committer.Name != "" {
s.SetOption(nameKey, c.Committer.Name)
}
if c.Committer.Email != "" {
s.SetOption(emailKey, c.Committer.Email)
}
}
func (c *Config) marshalPack() {
s := c.Raw.Section(packSection)
if c.Pack.Window != DefaultPackWindow {
s.SetOption(windowKey, fmt.Sprintf("%d", c.Pack.Window))
}
}
func (c *Config) marshalRemotes() {
s := c.Raw.Section(remoteSection)
newSubsections := make(format.Subsections, 0, len(c.Remotes))
added := make(map[string]bool)
for _, subsection := range s.Subsections {
if remote, ok := c.Remotes[subsection.Name]; ok {
newSubsections = append(newSubsections, remote.marshal())
added[subsection.Name] = true
}
}
remoteNames := make([]string, 0, len(c.Remotes))
for name := range c.Remotes {
remoteNames = append(remoteNames, name)
}
sort.Strings(remoteNames)
for _, name := range remoteNames {
if !added[name] {
newSubsections = append(newSubsections, c.Remotes[name].marshal())
}
}
s.Subsections = newSubsections
}
func (c *Config) marshalSubmodules() {
s := c.Raw.Section(submoduleSection)
s.Subsections = make(format.Subsections, len(c.Submodules))
var i int
for _, r := range c.Submodules {
section := r.marshal()
// the submodule section at config is a subset of the .gitmodule file
// we should remove the non-valid options for the config file.
section.RemoveOption(pathKey)
s.Subsections[i] = section
i++
}
}
func (c *Config) marshalBranches() {
s := c.Raw.Section(branchSection)
newSubsections := make(format.Subsections, 0, len(c.Branches))
added := make(map[string]bool)
for _, subsection := range s.Subsections {
if branch, ok := c.Branches[subsection.Name]; ok {
newSubsections = append(newSubsections, branch.marshal())
added[subsection.Name] = true
}
}
branchNames := make([]string, 0, len(c.Branches))
for name := range c.Branches {
branchNames = append(branchNames, name)
}
sort.Strings(branchNames)
for _, name := range branchNames {
if !added[name] {
newSubsections = append(newSubsections, c.Branches[name].marshal())
}
}
s.Subsections = newSubsections
}
func (c *Config) marshalURLs() {
s := c.Raw.Section(urlSection)
s.Subsections = make(format.Subsections, len(c.URLs))
var i int
for _, r := range c.URLs {
section := r.marshal()
// the submodule section at config is a subset of the .gitmodule file
// we should remove the non-valid options for the config file.
s.Subsections[i] = section
i++
}
}
func (c *Config) marshalInit() {
s := c.Raw.Section(initSection)
if c.Init.DefaultBranch != "" {
s.SetOption(defaultBranchKey, c.Init.DefaultBranch)
}
}
// RemoteConfig contains the configuration for a given remote repository.
type RemoteConfig struct {
// Name of the remote
Name string
// URLs the URLs of a remote repository. It must be non-empty. Fetch will
// always use the first URL, while push will use all of them.
URLs []string
// Mirror indicates that the repository is a mirror of remote.
Mirror bool
// insteadOfRulesApplied have urls been modified
insteadOfRulesApplied bool
// originalURLs are the urls before applying insteadOf rules
originalURLs []string
// Fetch the default set of "refspec" for fetch operation
Fetch []RefSpec
// raw representation of the subsection, filled by marshal or unmarshal are
// called
raw *format.Subsection
}
// Validate validates the fields and sets the default values.
func (c *RemoteConfig) Validate() error {
if c.Name == "" {
return ErrRemoteConfigEmptyName
}
if len(c.URLs) == 0 {
return ErrRemoteConfigEmptyURL
}
for _, r := range c.Fetch {
if err := r.Validate(); err != nil {
return err
}
}
if len(c.Fetch) == 0 {
c.Fetch = []RefSpec{RefSpec(fmt.Sprintf(DefaultFetchRefSpec, c.Name))}
}
return plumbing.NewRemoteHEADReferenceName(c.Name).Validate()
}
func (c *RemoteConfig) unmarshal(s *format.Subsection) error {
c.raw = s
fetch := []RefSpec{}
for _, f := range c.raw.Options.GetAll(fetchKey) {
rs := RefSpec(f)
if err := rs.Validate(); err != nil {
return err
}
fetch = append(fetch, rs)
}
c.Name = c.raw.Name
c.URLs = append([]string(nil), c.raw.Options.GetAll(urlKey)...)
c.URLs = append(c.URLs, c.raw.Options.GetAll(pushurlKey)...)
c.Fetch = fetch
c.Mirror = c.raw.Options.Get(mirrorKey) == "true"
return nil
}
func (c *RemoteConfig) marshal() *format.Subsection {
if c.raw == nil {
c.raw = &format.Subsection{}
}
c.raw.Name = c.Name
if len(c.URLs) == 0 {
c.raw.RemoveOption(urlKey)
} else {
urls := c.URLs
if c.insteadOfRulesApplied {
urls = c.originalURLs
}
c.raw.SetOption(urlKey, urls...)
}
if len(c.Fetch) == 0 {
c.raw.RemoveOption(fetchKey)
} else {
var values []string
for _, rs := range c.Fetch {
values = append(values, rs.String())
}
c.raw.SetOption(fetchKey, values...)
}
if c.Mirror {
c.raw.SetOption(mirrorKey, strconv.FormatBool(c.Mirror))
}
return c.raw
}
func (c *RemoteConfig) IsFirstURLLocal() bool {
return url.IsLocalEndpoint(c.URLs[0])
}
func (c *RemoteConfig) applyURLRules(urlRules map[string]*URL) {
// save original urls
originalURLs := make([]string, len(c.URLs))
copy(originalURLs, c.URLs)
for i, url := range c.URLs {
if matchingURLRule := findLongestInsteadOfMatch(url, urlRules); matchingURLRule != nil {
c.URLs[i] = matchingURLRule.ApplyInsteadOf(c.URLs[i])
c.insteadOfRulesApplied = true
}
}
if c.insteadOfRulesApplied {
c.originalURLs = originalURLs
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/config/modules.go
================================================
package config
import (
"bytes"
"errors"
"regexp"
format "github.com/go-git/go-git/v5/plumbing/format/config"
)
var (
ErrModuleEmptyURL = errors.New("module config: empty URL")
ErrModuleEmptyPath = errors.New("module config: empty path")
ErrModuleBadPath = errors.New("submodule has an invalid path")
)
var (
// Matches module paths with dotdot ".." components.
dotdotPath = regexp.MustCompile(`(^|[/\\])\.\.([/\\]|$)`)
)
// Modules defines the submodules properties, represents a .gitmodules file
// https://www.kernel.org/pub/software/scm/git/docs/gitmodules.html
type Modules struct {
// Submodules is a map of submodules being the key the name of the submodule.
Submodules map[string]*Submodule
raw *format.Config
}
// NewModules returns a new empty Modules
func NewModules() *Modules {
return &Modules{
Submodules: make(map[string]*Submodule),
raw: format.New(),
}
}
const (
pathKey = "path"
branchKey = "branch"
)
// Unmarshal parses a git-config file and stores it.
func (m *Modules) Unmarshal(b []byte) error {
r := bytes.NewBuffer(b)
d := format.NewDecoder(r)
m.raw = format.New()
if err := d.Decode(m.raw); err != nil {
return err
}
unmarshalSubmodules(m.raw, m.Submodules)
return nil
}
// Marshal returns Modules encoded as a git-config file.
func (m *Modules) Marshal() ([]byte, error) {
s := m.raw.Section(submoduleSection)
s.Subsections = make(format.Subsections, len(m.Submodules))
var i int
for _, r := range m.Submodules {
s.Subsections[i] = r.marshal()
i++
}
buf := bytes.NewBuffer(nil)
if err := format.NewEncoder(buf).Encode(m.raw); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Submodule defines a submodule.
type Submodule struct {
// Name module name
Name string
// Path defines the path, relative to the top-level directory of the Git
// working tree.
Path string
// URL defines a URL from which the submodule repository can be cloned.
URL string
// Branch is a remote branch name for tracking updates in the upstream
// submodule. Optional value.
Branch string
// raw representation of the subsection, filled by marshal or unmarshal are
// called.
raw *format.Subsection
}
// Validate validates the fields and sets the default values.
func (m *Submodule) Validate() error {
if m.Path == "" {
return ErrModuleEmptyPath
}
if m.URL == "" {
return ErrModuleEmptyURL
}
if dotdotPath.MatchString(m.Path) {
return ErrModuleBadPath
}
return nil
}
func (m *Submodule) unmarshal(s *format.Subsection) {
m.raw = s
m.Name = m.raw.Name
m.Path = m.raw.Option(pathKey)
m.URL = m.raw.Option(urlKey)
m.Branch = m.raw.Option(branchKey)
}
func (m *Submodule) marshal() *format.Subsection {
if m.raw == nil {
m.raw = &format.Subsection{}
}
m.raw.Name = m.Name
if m.raw.Name == "" {
m.raw.Name = m.Path
}
m.raw.SetOption(pathKey, m.Path)
m.raw.SetOption(urlKey, m.URL)
if m.Branch != "" {
m.raw.SetOption(branchKey, m.Branch)
}
return m.raw
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/config/refspec.go
================================================
package config
import (
"errors"
"strings"
"github.com/go-git/go-git/v5/plumbing"
)
const (
refSpecWildcard = "*"
refSpecForce = "+"
refSpecSeparator = ":"
)
var (
ErrRefSpecMalformedSeparator = errors.New("malformed refspec, separators are wrong")
ErrRefSpecMalformedWildcard = errors.New("malformed refspec, mismatched number of wildcards")
)
// RefSpec is a mapping from local branches to remote references.
// The format of the refspec is an optional +, followed by :, where
// is the pattern for references on the remote side and is where
// those references will be written locally. The + tells Git to update the
// reference even if it isn’t a fast-forward.
// eg.: "+refs/heads/*:refs/remotes/origin/*"
//
// https://git-scm.com/book/en/v2/Git-Internals-The-Refspec
type RefSpec string
// Validate validates the RefSpec
func (s RefSpec) Validate() error {
spec := string(s)
if strings.Count(spec, refSpecSeparator) != 1 {
return ErrRefSpecMalformedSeparator
}
sep := strings.Index(spec, refSpecSeparator)
if sep == len(spec)-1 {
return ErrRefSpecMalformedSeparator
}
ws := strings.Count(spec[0:sep], refSpecWildcard)
wd := strings.Count(spec[sep+1:], refSpecWildcard)
if ws == wd && ws < 2 && wd < 2 {
return nil
}
return ErrRefSpecMalformedWildcard
}
// IsForceUpdate returns if update is allowed in non fast-forward merges.
func (s RefSpec) IsForceUpdate() bool {
return s[0] == refSpecForce[0]
}
// IsDelete returns true if the refspec indicates a delete (empty src).
func (s RefSpec) IsDelete() bool {
return s[0] == refSpecSeparator[0]
}
// IsExactSHA1 returns true if the source is a SHA1 hash.
func (s RefSpec) IsExactSHA1() bool {
return plumbing.IsHash(s.Src())
}
// Src returns the src side.
func (s RefSpec) Src() string {
spec := string(s)
var start int
if s.IsForceUpdate() {
start = 1
} else {
start = 0
}
end := strings.Index(spec, refSpecSeparator)
return spec[start:end]
}
// Match match the given plumbing.ReferenceName against the source.
func (s RefSpec) Match(n plumbing.ReferenceName) bool {
if !s.IsWildcard() {
return s.matchExact(n)
}
return s.matchGlob(n)
}
// IsWildcard returns true if the RefSpec contains a wildcard.
func (s RefSpec) IsWildcard() bool {
return strings.Contains(string(s), refSpecWildcard)
}
func (s RefSpec) matchExact(n plumbing.ReferenceName) bool {
return s.Src() == n.String()
}
func (s RefSpec) matchGlob(n plumbing.ReferenceName) bool {
src := s.Src()
name := n.String()
wildcard := strings.Index(src, refSpecWildcard)
var prefix, suffix string
prefix = src[0:wildcard]
if len(src) > wildcard+1 {
suffix = src[wildcard+1:]
}
return len(name) >= len(prefix)+len(suffix) &&
strings.HasPrefix(name, prefix) &&
strings.HasSuffix(name, suffix)
}
// Dst returns the destination for the given remote reference.
func (s RefSpec) Dst(n plumbing.ReferenceName) plumbing.ReferenceName {
spec := string(s)
start := strings.Index(spec, refSpecSeparator) + 1
dst := spec[start:]
src := s.Src()
if !s.IsWildcard() {
return plumbing.ReferenceName(dst)
}
name := n.String()
ws := strings.Index(src, refSpecWildcard)
wd := strings.Index(dst, refSpecWildcard)
match := name[ws : len(name)-(len(src)-(ws+1))]
return plumbing.ReferenceName(dst[0:wd] + match + dst[wd+1:])
}
func (s RefSpec) Reverse() RefSpec {
spec := string(s)
separator := strings.Index(spec, refSpecSeparator)
return RefSpec(spec[separator+1:] + refSpecSeparator + spec[:separator])
}
func (s RefSpec) String() string {
return string(s)
}
// MatchAny returns true if any of the RefSpec match with the given ReferenceName.
func MatchAny(l []RefSpec, n plumbing.ReferenceName) bool {
for _, r := range l {
if r.Match(n) {
return true
}
}
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/config/url.go
================================================
package config
import (
"errors"
"strings"
format "github.com/go-git/go-git/v5/plumbing/format/config"
)
var (
errURLEmptyInsteadOf = errors.New("url config: empty insteadOf")
)
// Url defines Url rewrite rules
type URL struct {
// Name new base url
Name string
// Any URL that starts with this value will be rewritten to start, instead, with .
// When more than one insteadOf strings match a given URL, the longest match is used.
InsteadOf string
// raw representation of the subsection, filled by marshal or unmarshal are
// called.
raw *format.Subsection
}
// Validate validates fields of branch
func (b *URL) Validate() error {
if b.InsteadOf == "" {
return errURLEmptyInsteadOf
}
return nil
}
const (
insteadOfKey = "insteadOf"
)
func (u *URL) unmarshal(s *format.Subsection) error {
u.raw = s
u.Name = s.Name
u.InsteadOf = u.raw.Option(insteadOfKey)
return nil
}
func (u *URL) marshal() *format.Subsection {
if u.raw == nil {
u.raw = &format.Subsection{}
}
u.raw.Name = u.Name
u.raw.SetOption(insteadOfKey, u.InsteadOf)
return u.raw
}
func findLongestInsteadOfMatch(remoteURL string, urls map[string]*URL) *URL {
var longestMatch *URL
for _, u := range urls {
if !strings.HasPrefix(remoteURL, u.InsteadOf) {
continue
}
// according to spec if there is more than one match, take the logest
if longestMatch == nil || len(longestMatch.InsteadOf) < len(u.InsteadOf) {
longestMatch = u
}
}
return longestMatch
}
func (u *URL) ApplyInsteadOf(url string) string {
if !strings.HasPrefix(url, u.InsteadOf) {
return url
}
return u.Name + url[len(u.InsteadOf):]
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/doc.go
================================================
// A highly extensible git implementation in pure Go.
//
// go-git aims to reach the completeness of libgit2 or jgit, nowadays covers the
// majority of the plumbing read operations and some of the main write
// operations, but lacks the main porcelain operations such as merges.
//
// It is highly extensible, we have been following the open/close principle in
// its design to facilitate extensions, mainly focusing the efforts on the
// persistence of the objects.
package git
================================================
FILE: vendor/github.com/go-git/go-git/v5/internal/path_util/path_util.go
================================================
package path_util
import (
"os"
"os/user"
"strings"
)
func ReplaceTildeWithHome(path string) (string, error) {
if strings.HasPrefix(path, "~") {
firstSlash := strings.Index(path, "/")
if firstSlash == 1 {
home, err := os.UserHomeDir()
if err != nil {
return path, err
}
return strings.Replace(path, "~", home, 1), nil
} else if firstSlash > 1 {
username := path[1:firstSlash]
userAccount, err := user.Lookup(username)
if err != nil {
return path, err
}
return strings.Replace(path, path[:firstSlash], userAccount.HomeDir, 1), nil
}
}
return path, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/internal/revision/parser.go
================================================
// Package revision extracts git revision from string
// More information about revision : https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html
package revision
import (
"bytes"
"fmt"
"io"
"regexp"
"strconv"
"time"
)
// ErrInvalidRevision is emitted if string doesn't match valid revision
type ErrInvalidRevision struct {
s string
}
func (e *ErrInvalidRevision) Error() string {
return "Revision invalid : " + e.s
}
// Revisioner represents a revision component.
// A revision is made of multiple revision components
// obtained after parsing a revision string,
// for instance revision "master~" will be converted in
// two revision components Ref and TildePath
type Revisioner interface {
}
// Ref represents a reference name : HEAD, master,
type Ref string
// TildePath represents ~, ~{n}
type TildePath struct {
Depth int
}
// CaretPath represents ^, ^{n}
type CaretPath struct {
Depth int
}
// CaretReg represents ^{/foo bar}
type CaretReg struct {
Regexp *regexp.Regexp
Negate bool
}
// CaretType represents ^{commit}
type CaretType struct {
ObjectType string
}
// AtReflog represents @{n}
type AtReflog struct {
Depth int
}
// AtCheckout represents @{-n}
type AtCheckout struct {
Depth int
}
// AtUpstream represents @{upstream}, @{u}
type AtUpstream struct {
BranchName string
}
// AtPush represents @{push}
type AtPush struct {
BranchName string
}
// AtDate represents @{"2006-01-02T15:04:05Z"}
type AtDate struct {
Date time.Time
}
// ColonReg represents :/foo bar
type ColonReg struct {
Regexp *regexp.Regexp
Negate bool
}
// ColonPath represents :./ :
type ColonPath struct {
Path string
}
// ColonStagePath represents ::/
type ColonStagePath struct {
Path string
Stage int
}
// Parser represents a parser
// use to tokenize and transform to revisioner chunks
// a given string
type Parser struct {
s *scanner
currentParsedChar struct {
tok token
lit string
}
unreadLastChar bool
}
// NewParserFromString returns a new instance of parser from a string.
func NewParserFromString(s string) *Parser {
return NewParser(bytes.NewBufferString(s))
}
// NewParser returns a new instance of parser.
func NewParser(r io.Reader) *Parser {
return &Parser{s: newScanner(r)}
}
// scan returns the next token from the underlying scanner
// or the last scanned token if an unscan was requested
func (p *Parser) scan() (token, string, error) {
if p.unreadLastChar {
p.unreadLastChar = false
return p.currentParsedChar.tok, p.currentParsedChar.lit, nil
}
tok, lit, err := p.s.scan()
p.currentParsedChar.tok, p.currentParsedChar.lit = tok, lit
return tok, lit, err
}
// unscan pushes the previously read token back onto the buffer.
func (p *Parser) unscan() { p.unreadLastChar = true }
// Parse explode a revision string into revisioner chunks
func (p *Parser) Parse() ([]Revisioner, error) {
var rev Revisioner
var revs []Revisioner
var tok token
var err error
for {
tok, _, err = p.scan()
if err != nil {
return nil, err
}
switch tok {
case at:
rev, err = p.parseAt()
case tilde:
rev, err = p.parseTilde()
case caret:
rev, err = p.parseCaret()
case colon:
rev, err = p.parseColon()
case eof:
err = p.validateFullRevision(&revs)
if err != nil {
return []Revisioner{}, err
}
return revs, nil
default:
p.unscan()
rev, err = p.parseRef()
}
if err != nil {
return []Revisioner{}, err
}
revs = append(revs, rev)
}
}
// validateFullRevision ensures all revisioner chunks make a valid revision
func (p *Parser) validateFullRevision(chunks *[]Revisioner) error {
var hasReference bool
for i, chunk := range *chunks {
switch chunk.(type) {
case Ref:
if i == 0 {
hasReference = true
} else {
return &ErrInvalidRevision{`reference must be defined once at the beginning`}
}
case AtDate:
if len(*chunks) == 1 || hasReference && len(*chunks) == 2 {
return nil
}
return &ErrInvalidRevision{`"@" statement is not valid, could be : @{}, @{}`}
case AtReflog:
if len(*chunks) == 1 || hasReference && len(*chunks) == 2 {
return nil
}
return &ErrInvalidRevision{`"@" statement is not valid, could be : @{}, @{}`}
case AtCheckout:
if len(*chunks) == 1 {
return nil
}
return &ErrInvalidRevision{`"@" statement is not valid, could be : @{-}`}
case AtUpstream:
if len(*chunks) == 1 || hasReference && len(*chunks) == 2 {
return nil
}
return &ErrInvalidRevision{`"@" statement is not valid, could be : @{upstream}, @{upstream}, @{u}, @{u}`}
case AtPush:
if len(*chunks) == 1 || hasReference && len(*chunks) == 2 {
return nil
}
return &ErrInvalidRevision{`"@" statement is not valid, could be : @{push}, @{push}`}
case TildePath, CaretPath, CaretReg:
if !hasReference {
return &ErrInvalidRevision{`"~" or "^" statement must have a reference defined at the beginning`}
}
case ColonReg:
if len(*chunks) == 1 {
return nil
}
return &ErrInvalidRevision{`":" statement is not valid, could be : :/`}
case ColonPath:
if i == len(*chunks)-1 && hasReference || len(*chunks) == 1 {
return nil
}
return &ErrInvalidRevision{`":" statement is not valid, could be : :`}
case ColonStagePath:
if len(*chunks) == 1 {
return nil
}
return &ErrInvalidRevision{`":" statement is not valid, could be : ::`}
}
}
return nil
}
// parseAt extract @ statements
func (p *Parser) parseAt() (Revisioner, error) {
var tok, nextTok token
var lit, nextLit string
var err error
tok, _, err = p.scan()
if err != nil {
return nil, err
}
if tok != obrace {
p.unscan()
return Ref("HEAD"), nil
}
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
nextTok, nextLit, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == word && (lit == "u" || lit == "upstream") && nextTok == cbrace:
return AtUpstream{}, nil
case tok == word && lit == "push" && nextTok == cbrace:
return AtPush{}, nil
case tok == number && nextTok == cbrace:
n, _ := strconv.Atoi(lit)
return AtReflog{n}, nil
case tok == minus && nextTok == number:
n, _ := strconv.Atoi(nextLit)
t, _, err := p.scan()
if err != nil {
return nil, err
}
if t != cbrace {
return nil, &ErrInvalidRevision{s: `missing "}" in @{-n} structure`}
}
return AtCheckout{n}, nil
default:
p.unscan()
date := lit
for {
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == cbrace:
t, err := time.Parse("2006-01-02T15:04:05Z", date)
if err != nil {
return nil, &ErrInvalidRevision{fmt.Sprintf(`wrong date "%s" must fit ISO-8601 format : 2006-01-02T15:04:05Z`, date)}
}
return AtDate{t}, nil
case tok == eof:
return nil, &ErrInvalidRevision{s: `missing "}" in @{} structure`}
default:
date += lit
}
}
}
}
// parseTilde extract ~ statements
func (p *Parser) parseTilde() (Revisioner, error) {
var tok token
var lit string
var err error
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == number:
n, _ := strconv.Atoi(lit)
return TildePath{n}, nil
default:
p.unscan()
return TildePath{1}, nil
}
}
// parseCaret extract ^ statements
func (p *Parser) parseCaret() (Revisioner, error) {
var tok token
var lit string
var err error
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == obrace:
r, err := p.parseCaretBraces()
if err != nil {
return nil, err
}
return r, nil
case tok == number:
n, _ := strconv.Atoi(lit)
if n > 2 {
return nil, &ErrInvalidRevision{fmt.Sprintf(`"%s" found must be 0, 1 or 2 after "^"`, lit)}
}
return CaretPath{n}, nil
default:
p.unscan()
return CaretPath{1}, nil
}
}
// parseCaretBraces extract ^{} statements
func (p *Parser) parseCaretBraces() (Revisioner, error) {
var tok, nextTok token
var lit, _ string
start := true
var re string
var negate bool
var err error
for {
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
nextTok, _, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == word && nextTok == cbrace && (lit == "commit" || lit == "tree" || lit == "blob" || lit == "tag" || lit == "object"):
return CaretType{lit}, nil
case re == "" && tok == cbrace:
return CaretType{"tag"}, nil
case re == "" && tok == emark && nextTok == emark:
re += lit
case re == "" && tok == emark && nextTok == minus:
negate = true
case re == "" && tok == emark:
return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`}
case re == "" && tok == slash:
p.unscan()
case tok != slash && start:
return nil, &ErrInvalidRevision{fmt.Sprintf(`"%s" is not a valid revision suffix brace component`, lit)}
case tok == eof:
return nil, &ErrInvalidRevision{s: `missing "}" in ^{} structure`}
case tok != cbrace:
p.unscan()
re += lit
case tok == cbrace:
p.unscan()
reg, err := regexp.Compile(re)
if err != nil {
return CaretReg{}, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component, %s`, err.Error())}
}
return CaretReg{reg, negate}, nil
}
start = false
}
}
// parseColon extract : statements
func (p *Parser) parseColon() (Revisioner, error) {
var tok token
var err error
tok, _, err = p.scan()
if err != nil {
return nil, err
}
switch tok {
case slash:
return p.parseColonSlash()
default:
p.unscan()
return p.parseColonDefault()
}
}
// parseColonSlash extract :/ statements
func (p *Parser) parseColonSlash() (Revisioner, error) {
var tok, nextTok token
var lit string
var re string
var negate bool
var err error
for {
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
nextTok, _, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == emark && nextTok == emark:
re += lit
case re == "" && tok == emark && nextTok == minus:
negate = true
case re == "" && tok == emark:
return nil, &ErrInvalidRevision{s: `revision suffix brace component sequences starting with "/!" others than those defined are reserved`}
case tok == eof:
p.unscan()
reg, err := regexp.Compile(re)
if err != nil {
return ColonReg{}, &ErrInvalidRevision{fmt.Sprintf(`revision suffix brace component, %s`, err.Error())}
}
return ColonReg{reg, negate}, nil
default:
p.unscan()
re += lit
}
}
}
// parseColonDefault extract : statements
func (p *Parser) parseColonDefault() (Revisioner, error) {
var tok token
var lit string
var path string
var stage int
var err error
var n = -1
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
nextTok, _, err := p.scan()
if err != nil {
return nil, err
}
if tok == number && nextTok == colon {
n, _ = strconv.Atoi(lit)
}
switch n {
case 0, 1, 2, 3:
stage = n
default:
path += lit
p.unscan()
}
for {
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
switch {
case tok == eof && n == -1:
return ColonPath{path}, nil
case tok == eof:
return ColonStagePath{path, stage}, nil
default:
path += lit
}
}
}
// parseRef extract reference name
func (p *Parser) parseRef() (Revisioner, error) {
var tok, prevTok token
var lit, buf string
var endOfRef bool
var err error
for {
tok, lit, err = p.scan()
if err != nil {
return nil, err
}
switch tok {
case eof, at, colon, tilde, caret:
endOfRef = true
}
err := p.checkRefFormat(tok, lit, prevTok, buf, endOfRef)
if err != nil {
return "", err
}
if endOfRef {
p.unscan()
return Ref(buf), nil
}
buf += lit
prevTok = tok
}
}
// checkRefFormat ensure reference name follow rules defined here :
// https://git-scm.com/docs/git-check-ref-format
func (p *Parser) checkRefFormat(token token, literal string, previousToken token, buffer string, endOfRef bool) error {
switch token {
case aslash, space, control, qmark, asterisk, obracket:
return &ErrInvalidRevision{fmt.Sprintf(`must not contains "%s"`, literal)}
}
switch {
case (token == dot || token == slash) && buffer == "":
return &ErrInvalidRevision{fmt.Sprintf(`must not start with "%s"`, literal)}
case previousToken == slash && endOfRef:
return &ErrInvalidRevision{`must not end with "/"`}
case previousToken == dot && endOfRef:
return &ErrInvalidRevision{`must not end with "."`}
case token == dot && previousToken == slash:
return &ErrInvalidRevision{`must not contains "/."`}
case previousToken == dot && token == dot:
return &ErrInvalidRevision{`must not contains ".."`}
case previousToken == slash && token == slash:
return &ErrInvalidRevision{`must not contains consecutively "/"`}
case (token == slash || endOfRef) && len(buffer) > 4 && buffer[len(buffer)-5:] == ".lock":
return &ErrInvalidRevision{"cannot end with .lock"}
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/internal/revision/scanner.go
================================================
package revision
import (
"bufio"
"io"
"unicode"
)
// runeCategoryValidator takes a rune as input and
// validates it belongs to a rune category
type runeCategoryValidator func(r rune) bool
// tokenizeExpression aggregates a series of runes matching check predicate into a single
// string and provides given tokenType as token type
func tokenizeExpression(ch rune, tokenType token, check runeCategoryValidator, r *bufio.Reader) (token, string, error) {
var data []rune
data = append(data, ch)
for {
c, _, err := r.ReadRune()
if c == zeroRune {
break
}
if err != nil {
return tokenError, "", err
}
if check(c) {
data = append(data, c)
} else {
err := r.UnreadRune()
if err != nil {
return tokenError, "", err
}
return tokenType, string(data), nil
}
}
return tokenType, string(data), nil
}
// maxRevisionLength holds the maximum length that will be parsed for a
// revision. Git itself doesn't enforce a max length, but rather leans on
// the OS to enforce it via its ARG_MAX.
const maxRevisionLength = 128 * 1024 // 128kb
var zeroRune = rune(0)
// scanner represents a lexical scanner.
type scanner struct {
r *bufio.Reader
}
// newScanner returns a new instance of scanner.
func newScanner(r io.Reader) *scanner {
return &scanner{r: bufio.NewReader(io.LimitReader(r, maxRevisionLength))}
}
// Scan extracts tokens and their strings counterpart
// from the reader
func (s *scanner) scan() (token, string, error) {
ch, _, err := s.r.ReadRune()
if err != nil && err != io.EOF {
return tokenError, "", err
}
switch ch {
case zeroRune:
return eof, "", nil
case ':':
return colon, string(ch), nil
case '~':
return tilde, string(ch), nil
case '^':
return caret, string(ch), nil
case '.':
return dot, string(ch), nil
case '/':
return slash, string(ch), nil
case '{':
return obrace, string(ch), nil
case '}':
return cbrace, string(ch), nil
case '-':
return minus, string(ch), nil
case '@':
return at, string(ch), nil
case '\\':
return aslash, string(ch), nil
case '?':
return qmark, string(ch), nil
case '*':
return asterisk, string(ch), nil
case '[':
return obracket, string(ch), nil
case '!':
return emark, string(ch), nil
}
if unicode.IsSpace(ch) {
return space, string(ch), nil
}
if unicode.IsControl(ch) {
return control, string(ch), nil
}
if unicode.IsLetter(ch) {
return tokenizeExpression(ch, word, unicode.IsLetter, s.r)
}
if unicode.IsNumber(ch) {
return tokenizeExpression(ch, number, unicode.IsNumber, s.r)
}
return tokenError, string(ch), nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/internal/revision/token.go
================================================
package revision
// token represents a entity extracted from string parsing
type token int
const (
eof token = iota
aslash
asterisk
at
caret
cbrace
colon
control
dot
emark
minus
number
obrace
obracket
qmark
slash
space
tilde
tokenError
word
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/internal/url/url.go
================================================
package url
import (
"regexp"
)
var (
isSchemeRegExp = regexp.MustCompile(`^[^:]+://`)
// Ref: https://github.com/git/git/blob/master/Documentation/urls.txt#L37
scpLikeUrlRegExp = regexp.MustCompile(`^(?:(?P[^@]+)@)?(?P[^:\s]+):(?:(?P[0-9]{1,5}):)?(?P[^\\].*)$`)
)
// MatchesScheme returns true if the given string matches a URL-like
// format scheme.
func MatchesScheme(url string) bool {
return isSchemeRegExp.MatchString(url)
}
// MatchesScpLike returns true if the given string matches an SCP-like
// format scheme.
func MatchesScpLike(url string) bool {
return scpLikeUrlRegExp.MatchString(url)
}
// FindScpLikeComponents returns the user, host, port and path of the
// given SCP-like URL.
func FindScpLikeComponents(url string) (user, host, port, path string) {
m := scpLikeUrlRegExp.FindStringSubmatch(url)
return m[1], m[2], m[3], m[4]
}
// IsLocalEndpoint returns true if the given URL string specifies a
// local file endpoint. For example, on a Linux machine,
// `/home/user/src/go-git` would match as a local endpoint, but
// `https://github.com/src-d/go-git` would not.
func IsLocalEndpoint(url string) bool {
return !MatchesScheme(url) && !MatchesScpLike(url)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/object_walker.go
================================================
package git
import (
"fmt"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage"
)
type objectWalker struct {
Storer storage.Storer
// seen is the set of objects seen in the repo.
// seen map can become huge if walking over large
// repos. Thus using struct{} as the value type.
seen map[plumbing.Hash]struct{}
}
func newObjectWalker(s storage.Storer) *objectWalker {
return &objectWalker{s, map[plumbing.Hash]struct{}{}}
}
// walkAllRefs walks all (hash) references from the repo.
func (p *objectWalker) walkAllRefs() error {
// Walk over all the references in the repo.
it, err := p.Storer.IterReferences()
if err != nil {
return err
}
defer it.Close()
err = it.ForEach(func(ref *plumbing.Reference) error {
// Exit this iteration early for non-hash references.
if ref.Type() != plumbing.HashReference {
return nil
}
return p.walkObjectTree(ref.Hash())
})
return err
}
func (p *objectWalker) isSeen(hash plumbing.Hash) bool {
_, seen := p.seen[hash]
return seen
}
func (p *objectWalker) add(hash plumbing.Hash) {
p.seen[hash] = struct{}{}
}
// walkObjectTree walks over all objects and remembers references
// to them in the objectWalker. This is used instead of the revlist
// walks because memory usage is tight with huge repos.
func (p *objectWalker) walkObjectTree(hash plumbing.Hash) error {
// Check if we have already seen, and mark this object
if p.isSeen(hash) {
return nil
}
p.add(hash)
// Fetch the object.
obj, err := object.GetObject(p.Storer, hash)
if err != nil {
return fmt.Errorf("getting object %s failed: %v", hash, err)
}
// Walk all children depending on object type.
switch obj := obj.(type) {
case *object.Commit:
err = p.walkObjectTree(obj.TreeHash)
if err != nil {
return err
}
for _, h := range obj.ParentHashes {
err = p.walkObjectTree(h)
if err != nil {
return err
}
}
case *object.Tree:
for i := range obj.Entries {
// Shortcut for blob objects:
// 'or' the lower bits of a mode and check that it
// it matches a filemode.Executable. The type information
// is in the higher bits, but this is the cleanest way
// to handle plain files with different modes.
// Other non-tree objects are somewhat rare, so they
// are not special-cased.
if obj.Entries[i].Mode|0755 == filemode.Executable {
p.add(obj.Entries[i].Hash)
continue
}
// Normal walk for sub-trees (and symlinks etc).
err = p.walkObjectTree(obj.Entries[i].Hash)
if err != nil {
return err
}
}
case *object.Tag:
return p.walkObjectTree(obj.Target)
default:
// Error out on unhandled object types.
return fmt.Errorf("unknown object %X %s %T", obj.ID(), obj.Type(), obj)
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/options.go
================================================
package git
import (
"errors"
"fmt"
"regexp"
"strings"
"time"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
formatcfg "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
"github.com/go-git/go-git/v5/plumbing/transport"
)
// SubmoduleRescursivity defines how depth will affect any submodule recursive
// operation.
type SubmoduleRescursivity uint
const (
// DefaultRemoteName name of the default Remote, just like git command.
DefaultRemoteName = "origin"
// NoRecurseSubmodules disables the recursion for a submodule operation.
NoRecurseSubmodules SubmoduleRescursivity = 0
// DefaultSubmoduleRecursionDepth allow recursion in a submodule operation.
DefaultSubmoduleRecursionDepth SubmoduleRescursivity = 10
)
var (
ErrMissingURL = errors.New("URL field is required")
)
// CloneOptions describes how a clone should be performed.
type CloneOptions struct {
// The (possibly remote) repository URL to clone from.
URL string
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// Name of the remote to be added, by default `origin`.
RemoteName string
// Remote branch to clone.
ReferenceName plumbing.ReferenceName
// Fetch only ReferenceName if true.
SingleBranch bool
// Mirror clones the repository as a mirror.
//
// Compared to a bare clone, mirror not only maps local branches of the
// source to local branches of the target, it maps all refs (including
// remote-tracking branches, notes etc.) and sets up a refspec configuration
// such that all these refs are overwritten by a git remote update in the
// target repository.
Mirror bool
// No checkout of HEAD after clone if true.
NoCheckout bool
// Limit fetching to the specified number of commits.
Depth int
// RecurseSubmodules after the clone is created, initialize all submodules
// within, using their default settings. This option is ignored if the
// cloned repository does not have a worktree.
RecurseSubmodules SubmoduleRescursivity
// ShallowSubmodules limit cloning submodules to the 1 level of depth.
// It matches the git command --shallow-submodules.
ShallowSubmodules bool
// Progress is where the human readable information sent by the server is
// stored, if nil nothing is stored and the capability (if supported)
// no-progress, is sent to the server to avoid send this information.
Progress sideband.Progress
// Tags describe how the tags will be fetched from the remote repository,
// by default is AllTags.
Tags TagMode
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CABundle specify additional ca bundle with system cert pool
CABundle []byte
// ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions
// When the repository to clone is on the local machine, instead of
// using hard links, automatically setup .git/objects/info/alternates
// to share the objects with the source repository.
// The resulting repository starts out without any object of its own.
// NOTE: this is a possibly dangerous operation; do not use it unless
// you understand what it does.
//
// [Reference]: https://git-scm.com/docs/git-clone#Documentation/git-clone.txt---shared
Shared bool
}
// MergeOptions describes how a merge should be performed.
type MergeOptions struct {
// Strategy defines the merge strategy to be used.
Strategy MergeStrategy
}
// MergeStrategy represents the different types of merge strategies.
type MergeStrategy int8
const (
// FastForwardMerge represents a Git merge strategy where the current
// branch can be simply updated to point to the HEAD of the branch being
// merged. This is only possible if the history of the branch being merged
// is a linear descendant of the current branch, with no conflicting commits.
//
// This is the default option.
FastForwardMerge MergeStrategy = iota
)
// Validate validates the fields and sets the default values.
func (o *CloneOptions) Validate() error {
if o.URL == "" {
return ErrMissingURL
}
if o.RemoteName == "" {
o.RemoteName = DefaultRemoteName
}
if o.ReferenceName == "" {
o.ReferenceName = plumbing.HEAD
}
if o.Tags == InvalidTagMode {
o.Tags = AllTags
}
return nil
}
// PullOptions describes how a pull should be performed.
type PullOptions struct {
// Name of the remote to be pulled. If empty, uses the default.
RemoteName string
// RemoteURL overrides the remote repo address with a custom URL
RemoteURL string
// Remote branch to clone. If empty, uses HEAD.
ReferenceName plumbing.ReferenceName
// Fetch only ReferenceName if true.
SingleBranch bool
// Limit fetching to the specified number of commits.
Depth int
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// RecurseSubmodules controls if new commits of all populated submodules
// should be fetched too.
RecurseSubmodules SubmoduleRescursivity
// Progress is where the human readable information sent by the server is
// stored, if nil nothing is stored and the capability (if supported)
// no-progress, is sent to the server to avoid send this information.
Progress sideband.Progress
// Force allows the pull to update a local branch even when the remote
// branch does not descend from it.
Force bool
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CABundle specify additional ca bundle with system cert pool
CABundle []byte
// ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions
}
// Validate validates the fields and sets the default values.
func (o *PullOptions) Validate() error {
if o.RemoteName == "" {
o.RemoteName = DefaultRemoteName
}
if o.ReferenceName == "" {
o.ReferenceName = plumbing.HEAD
}
return nil
}
type TagMode int
const (
InvalidTagMode TagMode = iota
// TagFollowing any tag that points into the histories being fetched is also
// fetched. TagFollowing requires a server with `include-tag` capability
// in order to fetch the annotated tags objects.
TagFollowing
// AllTags fetch all tags from the remote (i.e., fetch remote tags
// refs/tags/* into local tags with the same name)
AllTags
// NoTags fetch no tags from the remote at all
NoTags
)
// FetchOptions describes how a fetch should be performed
type FetchOptions struct {
// Name of the remote to fetch from. Defaults to origin.
RemoteName string
// RemoteURL overrides the remote repo address with a custom URL
RemoteURL string
RefSpecs []config.RefSpec
// Depth limit fetching to the specified number of commits from the tip of
// each remote branch history.
Depth int
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// Progress is where the human readable information sent by the server is
// stored, if nil nothing is stored and the capability (if supported)
// no-progress, is sent to the server to avoid send this information.
Progress sideband.Progress
// Tags describe how the tags will be fetched from the remote repository,
// by default is TagFollowing.
Tags TagMode
// Force allows the fetch to update a local branch even when the remote
// branch does not descend from it.
Force bool
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CABundle specify additional ca bundle with system cert pool
CABundle []byte
// ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions
// Prune specify that local refs that match given RefSpecs and that do
// not exist remotely will be removed.
Prune bool
}
// Validate validates the fields and sets the default values.
func (o *FetchOptions) Validate() error {
if o.RemoteName == "" {
o.RemoteName = DefaultRemoteName
}
if o.Tags == InvalidTagMode {
o.Tags = TagFollowing
}
for _, r := range o.RefSpecs {
if err := r.Validate(); err != nil {
return err
}
}
return nil
}
// PushOptions describes how a push should be performed.
type PushOptions struct {
// RemoteName is the name of the remote to be pushed to.
RemoteName string
// RemoteURL overrides the remote repo address with a custom URL
RemoteURL string
// RefSpecs specify what destination ref to update with what source object.
//
// The format of a parameter is an optional plus +, followed by
// the source object , followed by a colon :, followed by the destination ref .
// The is often the name of the branch you would want to push, but it can be a SHA-1.
// The tells which ref on the remote side is updated with this push.
//
// A refspec with empty src can be used to delete a reference.
RefSpecs []config.RefSpec
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// Progress is where the human readable information sent by the server is
// stored, if nil nothing is stored.
Progress sideband.Progress
// Prune specify that remote refs that match given RefSpecs and that do
// not exist locally will be removed.
Prune bool
// Force allows the push to update a remote branch even when the local
// branch does not descend from it.
Force bool
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CABundle specify additional ca bundle with system cert pool
CABundle []byte
// RequireRemoteRefs only allows a remote ref to be updated if its current
// value is the one specified here.
RequireRemoteRefs []config.RefSpec
// FollowTags will send any annotated tags with a commit target reachable from
// the refs already being pushed
FollowTags bool
// ForceWithLease allows a force push as long as the remote ref adheres to a "lease"
ForceWithLease *ForceWithLease
// PushOptions sets options to be transferred to the server during push.
Options map[string]string
// Atomic sets option to be an atomic push
Atomic bool
// ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions
}
// ForceWithLease sets fields on the lease
// If neither RefName nor Hash are set, ForceWithLease protects
// all refs in the refspec by ensuring the ref of the remote in the local repsitory
// matches the one in the ref advertisement.
type ForceWithLease struct {
// RefName, when set will protect the ref by ensuring it matches the
// hash in the ref advertisement.
RefName plumbing.ReferenceName
// Hash is the expected object id of RefName. The push will be rejected unless this
// matches the corresponding object id of RefName in the refs advertisement.
Hash plumbing.Hash
}
// Validate validates the fields and sets the default values.
func (o *PushOptions) Validate() error {
if o.RemoteName == "" {
o.RemoteName = DefaultRemoteName
}
if len(o.RefSpecs) == 0 {
o.RefSpecs = []config.RefSpec{
config.RefSpec(config.DefaultPushRefSpec),
}
}
for _, r := range o.RefSpecs {
if err := r.Validate(); err != nil {
return err
}
}
return nil
}
// SubmoduleUpdateOptions describes how a submodule update should be performed.
type SubmoduleUpdateOptions struct {
// Init, if true initializes the submodules recorded in the index.
Init bool
// NoFetch tell to the update command to not fetch new objects from the
// remote site.
NoFetch bool
// RecurseSubmodules the update is performed not only in the submodules of
// the current repository but also in any nested submodules inside those
// submodules (and so on). Until the SubmoduleRescursivity is reached.
RecurseSubmodules SubmoduleRescursivity
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// Depth limit fetching to the specified number of commits from the tip of
// each remote branch history.
Depth int
}
var (
ErrBranchHashExclusive = errors.New("Branch and Hash are mutually exclusive")
ErrCreateRequiresBranch = errors.New("Branch is mandatory when Create is used")
)
// CheckoutOptions describes how a checkout operation should be performed.
type CheckoutOptions struct {
// Hash is the hash of a commit or tag to be checked out. If used, HEAD
// will be in detached mode. If Create is not used, Branch and Hash are
// mutually exclusive.
Hash plumbing.Hash
// Branch to be checked out, if Branch and Hash are empty is set to `master`.
Branch plumbing.ReferenceName
// Create a new branch named Branch and start it at Hash.
Create bool
// Force, if true when switching branches, proceed even if the index or the
// working tree differs from HEAD. This is used to throw away local changes
Force bool
// Keep, if true when switching branches, local changes (the index or the
// working tree changes) will be kept so that they can be committed to the
// target branch. Force and Keep are mutually exclusive, should not be both
// set to true.
Keep bool
// SparseCheckoutDirectories
SparseCheckoutDirectories []string
}
// Validate validates the fields and sets the default values.
func (o *CheckoutOptions) Validate() error {
if !o.Create && !o.Hash.IsZero() && o.Branch != "" {
return ErrBranchHashExclusive
}
if o.Create && o.Branch == "" {
return ErrCreateRequiresBranch
}
if o.Branch == "" {
o.Branch = plumbing.Master
}
return nil
}
// ResetMode defines the mode of a reset operation.
type ResetMode int8
const (
// MixedReset resets the index but not the working tree (i.e., the changed
// files are preserved but not marked for commit) and reports what has not
// been updated. This is the default action.
MixedReset ResetMode = iota
// HardReset resets the index and working tree. Any changes to tracked files
// in the working tree are discarded.
HardReset
// MergeReset resets the index and updates the files in the working tree
// that are different between Commit and HEAD, but keeps those which are
// different between the index and working tree (i.e. which have changes
// which have not been added).
//
// If a file that is different between Commit and the index has unstaged
// changes, reset is aborted.
MergeReset
// SoftReset does not touch the index file or the working tree at all (but
// resets the head to , just like all modes do). This leaves all
// your changed files "Changes to be committed", as git status would put it.
SoftReset
)
// ResetOptions describes how a reset operation should be performed.
type ResetOptions struct {
// Commit, if commit is present set the current branch head (HEAD) to it.
Commit plumbing.Hash
// Mode, form resets the current branch head to Commit and possibly updates
// the index (resetting it to the tree of Commit) and the working tree
// depending on Mode. If empty MixedReset is used.
Mode ResetMode
// Files, if not empty will constrain the reseting the index to only files
// specified in this list.
Files []string
}
// Validate validates the fields and sets the default values.
func (o *ResetOptions) Validate(r *Repository) error {
if o.Commit == plumbing.ZeroHash {
ref, err := r.Head()
if err != nil {
return err
}
o.Commit = ref.Hash()
} else {
_, err := r.CommitObject(o.Commit)
if err != nil {
return fmt.Errorf("invalid reset option: %w", err)
}
}
return nil
}
type LogOrder int8
const (
LogOrderDefault LogOrder = iota
LogOrderDFS
LogOrderDFSPost
LogOrderBSF
LogOrderCommitterTime
)
// LogOptions describes how a log action should be performed.
type LogOptions struct {
// When the From option is set the log will only contain commits
// reachable from it. If this option is not set, HEAD will be used as
// the default From.
From plumbing.Hash
// The default traversal algorithm is Depth-first search
// set Order=LogOrderCommitterTime for ordering by committer time (more compatible with `git log`)
// set Order=LogOrderBSF for Breadth-first search
Order LogOrder
// Show only those commits in which the specified file was inserted/updated.
// It is equivalent to running `git log -- `.
// this field is kept for compatibility, it can be replaced with PathFilter
FileName *string
// Filter commits based on the path of files that are updated
// takes file path as argument and should return true if the file is desired
// It can be used to implement `git log -- `
// either is a file path, or directory path, or a regexp of file/directory path
PathFilter func(string) bool
// Pretend as if all the refs in refs/, along with HEAD, are listed on the command line as .
// It is equivalent to running `git log --all`.
// If set on true, the From option will be ignored.
All bool
// Show commits more recent than a specific date.
// It is equivalent to running `git log --since ` or `git log --after `.
Since *time.Time
// Show commits older than a specific date.
// It is equivalent to running `git log --until ` or `git log --before `.
Until *time.Time
}
var (
ErrMissingAuthor = errors.New("author field is required")
)
// AddOptions describes how an `add` operation should be performed
type AddOptions struct {
// All equivalent to `git add -A`, update the index not only where the
// working tree has a file matching `Path` but also where the index already
// has an entry. This adds, modifies, and removes index entries to match the
// working tree. If no `Path` nor `Glob` is given when `All` option is
// used, all files in the entire working tree are updated.
All bool
// Path is the exact filepath to the file or directory to be added.
Path string
// Glob adds all paths, matching pattern, to the index. If pattern matches a
// directory path, all directory contents are added to the index recursively.
Glob string
// SkipStatus adds the path with no status check. This option is relevant only
// when the `Path` option is specified and does not apply when the `All` option is used.
// Notice that when passing an ignored path it will be added anyway.
// When true it can speed up adding files to the worktree in very large repositories.
SkipStatus bool
}
// Validate validates the fields and sets the default values.
func (o *AddOptions) Validate(r *Repository) error {
if o.Path != "" && o.Glob != "" {
return fmt.Errorf("fields Path and Glob are mutual exclusive")
}
return nil
}
// CommitOptions describes how a commit operation should be performed.
type CommitOptions struct {
// All automatically stage files that have been modified and deleted, but
// new files you have not told Git about are not affected.
All bool
// AllowEmptyCommits enable empty commits to be created. An empty commit
// is when no changes to the tree were made, but a new commit message is
// provided. The default behavior is false, which results in ErrEmptyCommit.
AllowEmptyCommits bool
// Author is the author's signature of the commit. If Author is empty the
// Name and Email is read from the config, and time.Now it's used as When.
Author *object.Signature
// Committer is the committer's signature of the commit. If Committer is
// nil the Author signature is used.
Committer *object.Signature
// Parents are the parents commits for the new commit, by default when
// len(Parents) is zero, the hash of HEAD reference is used.
Parents []plumbing.Hash
// SignKey denotes a key to sign the commit with. A nil value here means the
// commit will not be signed. The private key must be present and already
// decrypted.
SignKey *openpgp.Entity
// Signer denotes a cryptographic signer to sign the commit with.
// A nil value here means the commit will not be signed.
// Takes precedence over SignKey.
Signer Signer
// Amend will create a new commit object and replace the commit that HEAD currently
// points to. Cannot be used with All nor Parents.
Amend bool
}
// Validate validates the fields and sets the default values.
func (o *CommitOptions) Validate(r *Repository) error {
if o.All && o.Amend {
return errors.New("all and amend cannot be used together")
}
if o.Amend && len(o.Parents) > 0 {
return errors.New("parents cannot be used with amend")
}
if o.Author == nil {
if err := o.loadConfigAuthorAndCommitter(r); err != nil {
return err
}
}
if o.Committer == nil {
o.Committer = o.Author
}
if len(o.Parents) == 0 {
head, err := r.Head()
if err != nil && err != plumbing.ErrReferenceNotFound {
return err
}
if head != nil {
o.Parents = []plumbing.Hash{head.Hash()}
}
}
return nil
}
func (o *CommitOptions) loadConfigAuthorAndCommitter(r *Repository) error {
cfg, err := r.ConfigScoped(config.SystemScope)
if err != nil {
return err
}
if o.Author == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
o.Author = &object.Signature{
Name: cfg.Author.Name,
Email: cfg.Author.Email,
When: time.Now(),
}
}
if o.Committer == nil && cfg.Committer.Email != "" && cfg.Committer.Name != "" {
o.Committer = &object.Signature{
Name: cfg.Committer.Name,
Email: cfg.Committer.Email,
When: time.Now(),
}
}
if o.Author == nil && cfg.User.Email != "" && cfg.User.Name != "" {
o.Author = &object.Signature{
Name: cfg.User.Name,
Email: cfg.User.Email,
When: time.Now(),
}
}
if o.Author == nil {
return ErrMissingAuthor
}
return nil
}
var (
ErrMissingName = errors.New("name field is required")
ErrMissingTagger = errors.New("tagger field is required")
ErrMissingMessage = errors.New("message field is required")
)
// CreateTagOptions describes how a tag object should be created.
type CreateTagOptions struct {
// Tagger defines the signature of the tag creator. If Tagger is empty the
// Name and Email is read from the config, and time.Now it's used as When.
Tagger *object.Signature
// Message defines the annotation of the tag. It is canonicalized during
// validation into the format expected by git - no leading whitespace and
// ending in a newline.
Message string
// SignKey denotes a key to sign the tag with. A nil value here means the tag
// will not be signed. The private key must be present and already decrypted.
SignKey *openpgp.Entity
}
// Validate validates the fields and sets the default values.
func (o *CreateTagOptions) Validate(r *Repository, hash plumbing.Hash) error {
if o.Tagger == nil {
if err := o.loadConfigTagger(r); err != nil {
return err
}
}
if o.Message == "" {
return ErrMissingMessage
}
// Canonicalize the message into the expected message format.
o.Message = strings.TrimSpace(o.Message) + "\n"
return nil
}
func (o *CreateTagOptions) loadConfigTagger(r *Repository) error {
cfg, err := r.ConfigScoped(config.SystemScope)
if err != nil {
return err
}
if o.Tagger == nil && cfg.Author.Email != "" && cfg.Author.Name != "" {
o.Tagger = &object.Signature{
Name: cfg.Author.Name,
Email: cfg.Author.Email,
When: time.Now(),
}
}
if o.Tagger == nil && cfg.User.Email != "" && cfg.User.Name != "" {
o.Tagger = &object.Signature{
Name: cfg.User.Name,
Email: cfg.User.Email,
When: time.Now(),
}
}
if o.Tagger == nil {
return ErrMissingTagger
}
return nil
}
// ListOptions describes how a remote list should be performed.
type ListOptions struct {
// Auth credentials, if required, to use with the remote repository.
Auth transport.AuthMethod
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CABundle specify additional ca bundle with system cert pool
CABundle []byte
// PeelingOption defines how peeled objects are handled during a
// remote list.
PeelingOption PeelingOption
// ProxyOptions provides info required for connecting to a proxy.
ProxyOptions transport.ProxyOptions
// Timeout specifies the timeout in seconds for list operations
Timeout int
}
// PeelingOption represents the different ways to handle peeled references.
//
// Peeled references represent the underlying object of an annotated
// (or signed) tag. Refer to upstream documentation for more info:
// https://github.com/git/git/blob/master/Documentation/technical/reftable.txt
type PeelingOption uint8
const (
// IgnorePeeled ignores all peeled reference names. This is the default behavior.
IgnorePeeled PeelingOption = 0
// OnlyPeeled returns only peeled reference names.
OnlyPeeled PeelingOption = 1
// AppendPeeled appends peeled reference names to the reference list.
AppendPeeled PeelingOption = 2
)
// CleanOptions describes how a clean should be performed.
type CleanOptions struct {
Dir bool
}
// GrepOptions describes how a grep should be performed.
type GrepOptions struct {
// Patterns are compiled Regexp objects to be matched.
Patterns []*regexp.Regexp
// InvertMatch selects non-matching lines.
InvertMatch bool
// CommitHash is the hash of the commit from which worktree should be derived.
CommitHash plumbing.Hash
// ReferenceName is the branch or tag name from which worktree should be derived.
ReferenceName plumbing.ReferenceName
// PathSpecs are compiled Regexp objects of pathspec to use in the matching.
PathSpecs []*regexp.Regexp
}
var (
ErrHashOrReference = errors.New("ambiguous options, only one of CommitHash or ReferenceName can be passed")
)
// Validate validates the fields and sets the default values.
//
// TODO: deprecate in favor of Validate(r *Repository) in v6.
func (o *GrepOptions) Validate(w *Worktree) error {
return o.validate(w.r)
}
func (o *GrepOptions) validate(r *Repository) error {
if !o.CommitHash.IsZero() && o.ReferenceName != "" {
return ErrHashOrReference
}
// If none of CommitHash and ReferenceName are provided, set commit hash of
// the repository's head.
if o.CommitHash.IsZero() && o.ReferenceName == "" {
ref, err := r.Head()
if err != nil {
return err
}
o.CommitHash = ref.Hash()
}
return nil
}
// PlainOpenOptions describes how opening a plain repository should be
// performed.
type PlainOpenOptions struct {
// DetectDotGit defines whether parent directories should be
// walked until a .git directory or file is found.
DetectDotGit bool
// Enable .git/commondir support (see https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt).
// NOTE: This option will only work with the filesystem storage.
EnableDotGitCommonDir bool
}
// Validate validates the fields and sets the default values.
func (o *PlainOpenOptions) Validate() error { return nil }
type PlainInitOptions struct {
InitOptions
// Determines if the repository will have a worktree (non-bare) or not (bare).
Bare bool
ObjectFormat formatcfg.ObjectFormat
}
// Validate validates the fields and sets the default values.
func (o *PlainInitOptions) Validate() error { return nil }
var (
ErrNoRestorePaths = errors.New("you must specify path(s) to restore")
)
// RestoreOptions describes how a restore should be performed.
type RestoreOptions struct {
// Marks to restore the content in the index
Staged bool
// Marks to restore the content of the working tree
Worktree bool
// List of file paths that will be restored
Files []string
}
// Validate validates the fields and sets the default values.
func (o *RestoreOptions) Validate() error {
if len(o.Files) == 0 {
return ErrNoRestorePaths
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/oss-fuzz.sh
================================================
#!/bin/bash -eu
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################
go mod download
go get github.com/AdamKorcz/go-118-fuzz-build/testing
if [ "$SANITIZER" != "coverage" ]; then
sed -i '/func (s \*DecoderSuite) TestDecode(/,/^}/ s/^/\/\//' plumbing/format/config/decoder_test.go
sed -n '35,$p' plumbing/format/packfile/common_test.go >> plumbing/format/packfile/delta_test.go
sed -n '20,53p' plumbing/object/object_test.go >> plumbing/object/tree_test.go
sed -i 's|func Test|// func Test|' plumbing/transport/common_test.go
fi
compile_native_go_fuzzer $(pwd)/internal/revision FuzzParser fuzz_parser
compile_native_go_fuzzer $(pwd)/plumbing/format/config FuzzDecoder fuzz_decoder_config
compile_native_go_fuzzer $(pwd)/plumbing/format/packfile FuzzPatchDelta fuzz_patch_delta
compile_native_go_fuzzer $(pwd)/plumbing/object FuzzParseSignedBytes fuzz_parse_signed_bytes
compile_native_go_fuzzer $(pwd)/plumbing/object FuzzDecode fuzz_decode
compile_native_go_fuzzer $(pwd)/plumbing/protocol/packp FuzzDecoder fuzz_decoder_packp
compile_native_go_fuzzer $(pwd)/plumbing/transport FuzzNewEndpoint fuzz_new_endpoint
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/cache/buffer_lru.go
================================================
package cache
import (
"container/list"
"sync"
)
// BufferLRU implements an object cache with an LRU eviction policy and a
// maximum size (measured in object size).
type BufferLRU struct {
MaxSize FileSize
actualSize FileSize
ll *list.List
cache map[int64]*list.Element
mut sync.Mutex
}
// NewBufferLRU creates a new BufferLRU with the given maximum size. The maximum
// size will never be exceeded.
func NewBufferLRU(maxSize FileSize) *BufferLRU {
return &BufferLRU{MaxSize: maxSize}
}
// NewBufferLRUDefault creates a new BufferLRU with the default cache size.
func NewBufferLRUDefault() *BufferLRU {
return &BufferLRU{MaxSize: DefaultMaxSize}
}
type buffer struct {
Key int64
Slice []byte
}
// Put puts a buffer into the cache. If the buffer is already in the cache, it
// will be marked as used. Otherwise, it will be inserted. A buffers might
// be evicted to make room for the new one.
func (c *BufferLRU) Put(key int64, slice []byte) {
c.mut.Lock()
defer c.mut.Unlock()
if c.cache == nil {
c.actualSize = 0
c.cache = make(map[int64]*list.Element, 1000)
c.ll = list.New()
}
bufSize := FileSize(len(slice))
if ee, ok := c.cache[key]; ok {
oldBuf := ee.Value.(buffer)
// in this case bufSize is a delta: new size - old size
bufSize -= FileSize(len(oldBuf.Slice))
c.ll.MoveToFront(ee)
ee.Value = buffer{key, slice}
} else {
if bufSize > c.MaxSize {
return
}
ee := c.ll.PushFront(buffer{key, slice})
c.cache[key] = ee
}
c.actualSize += bufSize
for c.actualSize > c.MaxSize {
last := c.ll.Back()
lastObj := last.Value.(buffer)
lastSize := FileSize(len(lastObj.Slice))
c.ll.Remove(last)
delete(c.cache, lastObj.Key)
c.actualSize -= lastSize
}
}
// Get returns a buffer by its key. It marks the buffer as used. If the buffer
// is not in the cache, (nil, false) will be returned.
func (c *BufferLRU) Get(key int64) ([]byte, bool) {
c.mut.Lock()
defer c.mut.Unlock()
ee, ok := c.cache[key]
if !ok {
return nil, false
}
c.ll.MoveToFront(ee)
return ee.Value.(buffer).Slice, true
}
// Clear the content of this buffer cache.
func (c *BufferLRU) Clear() {
c.mut.Lock()
defer c.mut.Unlock()
c.ll = nil
c.cache = nil
c.actualSize = 0
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/cache/common.go
================================================
package cache
import "github.com/go-git/go-git/v5/plumbing"
const (
Byte FileSize = 1 << (iota * 10)
KiByte
MiByte
GiByte
)
type FileSize int64
const DefaultMaxSize FileSize = 96 * MiByte
// Object is an interface to a object cache.
type Object interface {
// Put puts the given object into the cache. Whether this object will
// actually be put into the cache or not is implementation specific.
Put(o plumbing.EncodedObject)
// Get gets an object from the cache given its hash. The second return value
// is true if the object was returned, and false otherwise.
Get(k plumbing.Hash) (plumbing.EncodedObject, bool)
// Clear clears every object from the cache.
Clear()
}
// Buffer is an interface to a buffer cache.
type Buffer interface {
// Put puts a buffer into the cache. If the buffer is already in the cache,
// it will be marked as used. Otherwise, it will be inserted. Buffer might
// be evicted to make room for the new one.
Put(key int64, slice []byte)
// Get returns a buffer by its key. It marks the buffer as used. If the
// buffer is not in the cache, (nil, false) will be returned.
Get(key int64) ([]byte, bool)
// Clear clears every object from the cache.
Clear()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/cache/object_lru.go
================================================
package cache
import (
"container/list"
"sync"
"github.com/go-git/go-git/v5/plumbing"
)
// ObjectLRU implements an object cache with an LRU eviction policy and a
// maximum size (measured in object size).
type ObjectLRU struct {
MaxSize FileSize
actualSize FileSize
ll *list.List
cache map[interface{}]*list.Element
mut sync.Mutex
}
// NewObjectLRU creates a new ObjectLRU with the given maximum size. The maximum
// size will never be exceeded.
func NewObjectLRU(maxSize FileSize) *ObjectLRU {
return &ObjectLRU{MaxSize: maxSize}
}
// NewObjectLRUDefault creates a new ObjectLRU with the default cache size.
func NewObjectLRUDefault() *ObjectLRU {
return &ObjectLRU{MaxSize: DefaultMaxSize}
}
// Put puts an object into the cache. If the object is already in the cache, it
// will be marked as used. Otherwise, it will be inserted. A single object might
// be evicted to make room for the new object.
func (c *ObjectLRU) Put(obj plumbing.EncodedObject) {
c.mut.Lock()
defer c.mut.Unlock()
if c.cache == nil {
c.actualSize = 0
c.cache = make(map[interface{}]*list.Element, 1000)
c.ll = list.New()
}
objSize := FileSize(obj.Size())
key := obj.Hash()
if ee, ok := c.cache[key]; ok {
oldObj := ee.Value.(plumbing.EncodedObject)
// in this case objSize is a delta: new size - old size
objSize -= FileSize(oldObj.Size())
c.ll.MoveToFront(ee)
ee.Value = obj
} else {
if objSize > c.MaxSize {
return
}
ee := c.ll.PushFront(obj)
c.cache[key] = ee
}
c.actualSize += objSize
for c.actualSize > c.MaxSize {
last := c.ll.Back()
if last == nil {
c.actualSize = 0
break
}
lastObj := last.Value.(plumbing.EncodedObject)
lastSize := FileSize(lastObj.Size())
c.ll.Remove(last)
delete(c.cache, lastObj.Hash())
c.actualSize -= lastSize
}
}
// Get returns an object by its hash. It marks the object as used. If the object
// is not in the cache, (nil, false) will be returned.
func (c *ObjectLRU) Get(k plumbing.Hash) (plumbing.EncodedObject, bool) {
c.mut.Lock()
defer c.mut.Unlock()
ee, ok := c.cache[k]
if !ok {
return nil, false
}
c.ll.MoveToFront(ee)
return ee.Value.(plumbing.EncodedObject), true
}
// Clear the content of this object cache.
func (c *ObjectLRU) Clear() {
c.mut.Lock()
defer c.mut.Unlock()
c.ll = nil
c.cache = nil
c.actualSize = 0
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/color/color.go
================================================
package color
// TODO read colors from a github.com/go-git/go-git/plumbing/format/config.Config struct
// TODO implement color parsing, see https://github.com/git/git/blob/v2.26.2/color.c
// Colors. See https://github.com/git/git/blob/v2.26.2/color.h#L24-L53.
const (
Normal = ""
Reset = "\033[m"
Bold = "\033[1m"
Red = "\033[31m"
Green = "\033[32m"
Yellow = "\033[33m"
Blue = "\033[34m"
Magenta = "\033[35m"
Cyan = "\033[36m"
BoldRed = "\033[1;31m"
BoldGreen = "\033[1;32m"
BoldYellow = "\033[1;33m"
BoldBlue = "\033[1;34m"
BoldMagenta = "\033[1;35m"
BoldCyan = "\033[1;36m"
FaintRed = "\033[2;31m"
FaintGreen = "\033[2;32m"
FaintYellow = "\033[2;33m"
FaintBlue = "\033[2;34m"
FaintMagenta = "\033[2;35m"
FaintCyan = "\033[2;36m"
BgRed = "\033[41m"
BgGreen = "\033[42m"
BgYellow = "\033[43m"
BgBlue = "\033[44m"
BgMagenta = "\033[45m"
BgCyan = "\033[46m"
Faint = "\033[2m"
FaintItalic = "\033[2;3m"
Reverse = "\033[7m"
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/error.go
================================================
package plumbing
import "fmt"
type PermanentError struct {
Err error
}
func NewPermanentError(err error) *PermanentError {
if err == nil {
return nil
}
return &PermanentError{Err: err}
}
func (e *PermanentError) Error() string {
return fmt.Sprintf("permanent client error: %s", e.Err.Error())
}
type UnexpectedError struct {
Err error
}
func NewUnexpectedError(err error) *UnexpectedError {
if err == nil {
return nil
}
return &UnexpectedError{Err: err}
}
func (e *UnexpectedError) Error() string {
return fmt.Sprintf("unexpected client error: %s", e.Err.Error())
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/filemode/filemode.go
================================================
package filemode
import (
"encoding/binary"
"fmt"
"os"
"strconv"
)
// A FileMode represents the kind of tree entries used by git. It
// resembles regular file systems modes, although FileModes are
// considerably simpler (there are not so many), and there are some,
// like Submodule that has no file system equivalent.
type FileMode uint32
const (
// Empty is used as the FileMode of tree elements when comparing
// trees in the following situations:
//
// - the mode of tree elements before their creation. - the mode of
// tree elements after their deletion. - the mode of unmerged
// elements when checking the index.
//
// Empty has no file system equivalent. As Empty is the zero value
// of FileMode, it is also returned by New and
// NewFromOsNewFromOSFileMode along with an error, when they fail.
Empty FileMode = 0
// Dir represent a Directory.
Dir FileMode = 0040000
// Regular represent non-executable files. Please note this is not
// the same as golang regular files, which include executable files.
Regular FileMode = 0100644
// Deprecated represent non-executable files with the group writable
// bit set. This mode was supported by the first versions of git,
// but it has been deprecated nowadays. This library uses them
// internally, so you can read old packfiles, but will treat them as
// Regulars when interfacing with the outside world. This is the
// standard git behaviour.
Deprecated FileMode = 0100664
// Executable represents executable files.
Executable FileMode = 0100755
// Symlink represents symbolic links to files.
Symlink FileMode = 0120000
// Submodule represents git submodules. This mode has no file system
// equivalent.
Submodule FileMode = 0160000
)
// New takes the octal string representation of a FileMode and returns
// the FileMode and a nil error. If the string can not be parsed to a
// 32 bit unsigned octal number, it returns Empty and the parsing error.
//
// Example: "40000" means Dir, "100644" means Regular.
//
// Please note this function does not check if the returned FileMode
// is valid in git or if it is malformed. For instance, "1" will
// return the malformed FileMode(1) and a nil error.
func New(s string) (FileMode, error) {
n, err := strconv.ParseUint(s, 8, 32)
if err != nil {
return Empty, err
}
return FileMode(n), nil
}
// NewFromOSFileMode returns the FileMode used by git to represent
// the provided file system modes and a nil error on success. If the
// file system mode cannot be mapped to any valid git mode (as with
// sockets or named pipes), it will return Empty and an error.
//
// Note that some git modes cannot be generated from os.FileModes, like
// Deprecated and Submodule; while Empty will be returned, along with an
// error, only when the method fails.
func NewFromOSFileMode(m os.FileMode) (FileMode, error) {
if m.IsRegular() {
if isSetTemporary(m) {
return Empty, fmt.Errorf("no equivalent git mode for %s", m)
}
if isSetCharDevice(m) {
return Empty, fmt.Errorf("no equivalent git mode for %s", m)
}
if isSetUserExecutable(m) {
return Executable, nil
}
return Regular, nil
}
if m.IsDir() {
return Dir, nil
}
if isSetSymLink(m) {
return Symlink, nil
}
return Empty, fmt.Errorf("no equivalent git mode for %s", m)
}
func isSetCharDevice(m os.FileMode) bool {
return m&os.ModeCharDevice != 0
}
func isSetTemporary(m os.FileMode) bool {
return m&os.ModeTemporary != 0
}
func isSetUserExecutable(m os.FileMode) bool {
return m&0100 != 0
}
func isSetSymLink(m os.FileMode) bool {
return m&os.ModeSymlink != 0
}
// Bytes return a slice of 4 bytes with the mode in little endian
// encoding.
func (m FileMode) Bytes() []byte {
ret := make([]byte, 4)
binary.LittleEndian.PutUint32(ret, uint32(m))
return ret
}
// IsMalformed returns if the FileMode should not appear in a git packfile,
// this is: Empty and any other mode not mentioned as a constant in this
// package.
func (m FileMode) IsMalformed() bool {
return m != Dir &&
m != Regular &&
m != Deprecated &&
m != Executable &&
m != Symlink &&
m != Submodule
}
// String returns the FileMode as a string in the standard git format,
// this is, an octal number padded with ceros to 7 digits. Malformed
// modes are printed in that same format, for easier debugging.
//
// Example: Regular is "0100644", Empty is "0000000".
func (m FileMode) String() string {
return fmt.Sprintf("%07o", uint32(m))
}
// IsRegular returns if the FileMode represents that of a regular file,
// this is, either Regular or Deprecated. Please note that Executable
// are not regular even though in the UNIX tradition, they usually are:
// See the IsFile method.
func (m FileMode) IsRegular() bool {
return m == Regular ||
m == Deprecated
}
// IsFile returns if the FileMode represents that of a file, this is,
// Regular, Deprecated, Executable or Link.
func (m FileMode) IsFile() bool {
return m == Regular ||
m == Deprecated ||
m == Executable ||
m == Symlink
}
// ToOSFileMode returns the os.FileMode to be used when creating file
// system elements with the given git mode and a nil error on success.
//
// When the provided mode cannot be mapped to a valid file system mode
// (e.g. Submodule) it returns os.FileMode(0) and an error.
//
// The returned file mode does not take into account the umask.
func (m FileMode) ToOSFileMode() (os.FileMode, error) {
switch m {
case Dir:
return os.ModePerm | os.ModeDir, nil
case Submodule:
return os.ModePerm | os.ModeDir, nil
case Regular:
return os.FileMode(0644), nil
// Deprecated is no longer allowed: treated as a Regular instead
case Deprecated:
return os.FileMode(0644), nil
case Executable:
return os.FileMode(0755), nil
case Symlink:
return os.ModePerm | os.ModeSymlink, nil
}
return os.FileMode(0), fmt.Errorf("malformed mode (%s)", m)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/common.go
================================================
package config
// New creates a new config instance.
func New() *Config {
return &Config{}
}
// Config contains all the sections, comments and includes from a config file.
type Config struct {
Comment *Comment
Sections Sections
Includes Includes
}
// Includes is a list of Includes in a config file.
type Includes []*Include
// Include is a reference to an included config file.
type Include struct {
Path string
Config *Config
}
// Comment string without the prefix '#' or ';'.
type Comment string
const (
// NoSubsection token is passed to Config.Section and Config.SetSection to
// represent the absence of a section.
NoSubsection = ""
)
// Section returns a existing section with the given name or creates a new one.
func (c *Config) Section(name string) *Section {
for i := len(c.Sections) - 1; i >= 0; i-- {
s := c.Sections[i]
if s.IsName(name) {
return s
}
}
s := &Section{Name: name}
c.Sections = append(c.Sections, s)
return s
}
// HasSection checks if the Config has a section with the specified name.
func (c *Config) HasSection(name string) bool {
for _, s := range c.Sections {
if s.IsName(name) {
return true
}
}
return false
}
// RemoveSection removes a section from a config file.
func (c *Config) RemoveSection(name string) *Config {
result := Sections{}
for _, s := range c.Sections {
if !s.IsName(name) {
result = append(result, s)
}
}
c.Sections = result
return c
}
// RemoveSubsection remove a subsection from a config file.
func (c *Config) RemoveSubsection(section string, subsection string) *Config {
for _, s := range c.Sections {
if s.IsName(section) {
result := Subsections{}
for _, ss := range s.Subsections {
if !ss.IsName(subsection) {
result = append(result, ss)
}
}
s.Subsections = result
}
}
return c
}
// AddOption adds an option to a given section and subsection. Use the
// NoSubsection constant for the subsection argument if no subsection is wanted.
func (c *Config) AddOption(section string, subsection string, key string, value string) *Config {
if subsection == "" {
c.Section(section).AddOption(key, value)
} else {
c.Section(section).Subsection(subsection).AddOption(key, value)
}
return c
}
// SetOption sets an option to a given section and subsection. Use the
// NoSubsection constant for the subsection argument if no subsection is wanted.
func (c *Config) SetOption(section string, subsection string, key string, value string) *Config {
if subsection == "" {
c.Section(section).SetOption(key, value)
} else {
c.Section(section).Subsection(subsection).SetOption(key, value)
}
return c
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/decoder.go
================================================
package config
import (
"io"
"github.com/go-git/gcfg"
)
// A Decoder reads and decodes config files from an input stream.
type Decoder struct {
io.Reader
}
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{r}
}
// Decode reads the whole config from its input and stores it in the
// value pointed to by config.
func (d *Decoder) Decode(config *Config) error {
cb := func(s string, ss string, k string, v string, bv bool) error {
if ss == "" && k == "" {
config.Section(s)
return nil
}
if ss != "" && k == "" {
config.Section(s).Subsection(ss)
return nil
}
config.AddOption(s, ss, k, v)
return nil
}
return gcfg.ReadWithCallback(d, cb)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/doc.go
================================================
// Package config implements encoding and decoding of git config files.
//
// Configuration File
// ------------------
//
// The Git configuration file contains a number of variables that affect
// the Git commands' behavior. The `.git/config` file in each repository
// is used to store the configuration for that repository, and
// `$HOME/.gitconfig` is used to store a per-user configuration as
// fallback values for the `.git/config` file. The file `/etc/gitconfig`
// can be used to store a system-wide default configuration.
//
// The configuration variables are used by both the Git plumbing
// and the porcelains. The variables are divided into sections, wherein
// the fully qualified variable name of the variable itself is the last
// dot-separated segment and the section name is everything before the last
// dot. The variable names are case-insensitive, allow only alphanumeric
// characters and `-`, and must start with an alphabetic character. Some
// variables may appear multiple times; we say then that the variable is
// multivalued.
//
// Syntax
// ~~~~~~
//
// The syntax is fairly flexible and permissive; whitespaces are mostly
// ignored. The '#' and ';' characters begin comments to the end of line,
// blank lines are ignored.
//
// The file consists of sections and variables. A section begins with
// the name of the section in square brackets and continues until the next
// section begins. Section names are case-insensitive. Only alphanumeric
// characters, `-` and `.` are allowed in section names. Each variable
// must belong to some section, which means that there must be a section
// header before the first setting of a variable.
//
// Sections can be further divided into subsections. To begin a subsection
// put its name in double quotes, separated by space from the section name,
// in the section header, like in the example below:
//
// --------
// [section "subsection"]
//
// --------
//
// Subsection names are case sensitive and can contain any characters except
// newline (doublequote `"` and backslash can be included by escaping them
// as `\"` and `\\`, respectively). Section headers cannot span multiple
// lines. Variables may belong directly to a section or to a given subsection.
// You can have `[section]` if you have `[section "subsection"]`, but you
// don't need to.
//
// There is also a deprecated `[section.subsection]` syntax. With this
// syntax, the subsection name is converted to lower-case and is also
// compared case sensitively. These subsection names follow the same
// restrictions as section names.
//
// All the other lines (and the remainder of the line after the section
// header) are recognized as setting variables, in the form
// 'name = value' (or just 'name', which is a short-hand to say that
// the variable is the boolean "true").
// The variable names are case-insensitive, allow only alphanumeric characters
// and `-`, and must start with an alphabetic character.
//
// A line that defines a value can be continued to the next line by
// ending it with a `\`; the backquote and the end-of-line are
// stripped. Leading whitespaces after 'name =', the remainder of the
// line after the first comment character '#' or ';', and trailing
// whitespaces of the line are discarded unless they are enclosed in
// double quotes. Internal whitespaces within the value are retained
// verbatim.
//
// Inside double quotes, double quote `"` and backslash `\` characters
// must be escaped: use `\"` for `"` and `\\` for `\`.
//
// The following escape sequences (beside `\"` and `\\`) are recognized:
// `\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
// and `\b` for backspace (BS). Other char escape sequences (including octal
// escape sequences) are invalid.
//
// Includes
// ~~~~~~~~
//
// You can include one config file from another by setting the special
// `include.path` variable to the name of the file to be included. The
// variable takes a pathname as its value, and is subject to tilde
// expansion.
//
// The included file is expanded immediately, as if its contents had been
// found at the location of the include directive. If the value of the
// `include.path` variable is a relative path, the path is considered to be
// relative to the configuration file in which the include directive was
// found. See below for examples.
//
//
// Example
// ~~~~~~~
//
// # Core variables
// [core]
// ; Don't trust file modes
// filemode = false
//
// # Our diff algorithm
// [diff]
// external = /usr/local/bin/diff-wrapper
// renames = true
//
// [branch "devel"]
// remote = origin
// merge = refs/heads/devel
//
// # Proxy settings
// [core]
// gitProxy="ssh" for "kernel.org"
// gitProxy=default-proxy ; for the rest
//
// [include]
// path = /path/to/foo.inc ; include by absolute path
// path = foo ; expand "foo" relative to the current file
// path = ~/foo ; expand "foo" in your `$HOME` directory
//
package config
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/encoder.go
================================================
package config
import (
"fmt"
"io"
"strings"
)
// An Encoder writes config files to an output stream.
type Encoder struct {
w io.Writer
}
var (
subsectionReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`)
valueReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`, "\n", `\n`, "\t", `\t`, "\b", `\b`)
)
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w}
}
// Encode writes the config in git config format to the stream of the encoder.
func (e *Encoder) Encode(cfg *Config) error {
for _, s := range cfg.Sections {
if err := e.encodeSection(s); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeSection(s *Section) error {
if len(s.Options) > 0 {
if err := e.printf("[%s]\n", s.Name); err != nil {
return err
}
if err := e.encodeOptions(s.Options); err != nil {
return err
}
}
for _, ss := range s.Subsections {
if err := e.encodeSubsection(s.Name, ss); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error {
if err := e.printf("[%s \"%s\"]\n", sectionName, subsectionReplacer.Replace(s.Name)); err != nil {
return err
}
return e.encodeOptions(s.Options)
}
func (e *Encoder) encodeOptions(opts Options) error {
for _, o := range opts {
var value string
if strings.ContainsAny(o.Value, "#;\"\t\n\\") || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") {
value = `"`+valueReplacer.Replace(o.Value)+`"`
} else {
value = o.Value
}
if err := e.printf("\t%s = %s\n", o.Key, value); err != nil {
return err
}
}
return nil
}
func (e *Encoder) printf(msg string, args ...interface{}) error {
_, err := fmt.Fprintf(e.w, msg, args...)
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/format.go
================================================
package config
// RepositoryFormatVersion represents the repository format version,
// as per defined at:
//
// https://git-scm.com/docs/repository-version
type RepositoryFormatVersion string
const (
// Version_0 is the format defined by the initial version of git,
// including but not limited to the format of the repository
// directory, the repository configuration file, and the object
// and ref storage.
//
// Specifying the complete behavior of git is beyond the scope
// of this document.
Version_0 = "0"
// Version_1 is identical to version 0, with the following exceptions:
//
// 1. When reading the core.repositoryformatversion variable, a git
// implementation which supports version 1 MUST also read any
// configuration keys found in the extensions section of the
// configuration file.
//
// 2. If a version-1 repository specifies any extensions.* keys that
// the running git has not implemented, the operation MUST NOT proceed.
// Similarly, if the value of any known key is not understood by the
// implementation, the operation MUST NOT proceed.
//
// Note that if no extensions are specified in the config file, then
// core.repositoryformatversion SHOULD be set to 0 (setting it to 1 provides
// no benefit, and makes the repository incompatible with older
// implementations of git).
Version_1 = "1"
// DefaultRepositoryFormatVersion holds the default repository format version.
DefaultRepositoryFormatVersion = Version_0
)
// ObjectFormat defines the object format.
type ObjectFormat string
const (
// SHA1 represents the object format used for SHA1.
SHA1 ObjectFormat = "sha1"
// SHA256 represents the object format used for SHA256.
SHA256 ObjectFormat = "sha256"
// DefaultObjectFormat holds the default object format.
DefaultObjectFormat = SHA1
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/option.go
================================================
package config
import (
"fmt"
"strings"
)
// Option defines a key/value entity in a config file.
type Option struct {
// Key preserving original caseness.
// Use IsKey instead to compare key regardless of caseness.
Key string
// Original value as string, could be not normalized.
Value string
}
type Options []*Option
// IsKey returns true if the given key matches
// this option's key in a case-insensitive comparison.
func (o *Option) IsKey(key string) bool {
return strings.EqualFold(o.Key, key)
}
func (opts Options) GoString() string {
var strs []string
for _, opt := range opts {
strs = append(strs, fmt.Sprintf("%#v", opt))
}
return strings.Join(strs, ", ")
}
// Get gets the value for the given key if set,
// otherwise it returns the empty string.
//
// Note that there is no difference
//
// This matches git behaviour since git v1.8.1-rc1,
// if there are multiple definitions of a key, the
// last one wins.
//
// See: http://article.gmane.org/gmane.linux.kernel/1407184
//
// In order to get all possible values for the same key,
// use GetAll.
func (opts Options) Get(key string) string {
for i := len(opts) - 1; i >= 0; i-- {
o := opts[i]
if o.IsKey(key) {
return o.Value
}
}
return ""
}
// Has checks if an Option exist with the given key.
func (opts Options) Has(key string) bool {
for _, o := range opts {
if o.IsKey(key) {
return true
}
}
return false
}
// GetAll returns all possible values for the same key.
func (opts Options) GetAll(key string) []string {
result := []string{}
for _, o := range opts {
if o.IsKey(key) {
result = append(result, o.Value)
}
}
return result
}
func (opts Options) withoutOption(key string) Options {
result := Options{}
for _, o := range opts {
if !o.IsKey(key) {
result = append(result, o)
}
}
return result
}
func (opts Options) withAddedOption(key string, value string) Options {
return append(opts, &Option{key, value})
}
func (opts Options) withSettedOption(key string, values ...string) Options {
var result Options
var added []string
for _, o := range opts {
if !o.IsKey(key) {
result = append(result, o)
continue
}
if contains(values, o.Value) {
added = append(added, o.Value)
result = append(result, o)
continue
}
}
for _, value := range values {
if contains(added, value) {
continue
}
result = result.withAddedOption(key, value)
}
return result
}
func contains(haystack []string, needle string) bool {
for _, s := range haystack {
if s == needle {
return true
}
}
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/config/section.go
================================================
package config
import (
"fmt"
"strings"
)
// Section is the representation of a section inside git configuration files.
// Each Section contains Options that are used by both the Git plumbing
// and the porcelains.
// Sections can be further divided into subsections. To begin a subsection
// put its name in double quotes, separated by space from the section name,
// in the section header, like in the example below:
//
// [section "subsection"]
//
// All the other lines (and the remainder of the line after the section header)
// are recognized as option variables, in the form "name = value" (or just name,
// which is a short-hand to say that the variable is the boolean "true").
// The variable names are case-insensitive, allow only alphanumeric characters
// and -, and must start with an alphabetic character:
//
// [section "subsection1"]
// option1 = value1
// option2
// [section "subsection2"]
// option3 = value2
//
type Section struct {
Name string
Options Options
Subsections Subsections
}
type Subsection struct {
Name string
Options Options
}
type Sections []*Section
func (s Sections) GoString() string {
var strs []string
for _, ss := range s {
strs = append(strs, fmt.Sprintf("%#v", ss))
}
return strings.Join(strs, ", ")
}
type Subsections []*Subsection
func (s Subsections) GoString() string {
var strs []string
for _, ss := range s {
strs = append(strs, fmt.Sprintf("%#v", ss))
}
return strings.Join(strs, ", ")
}
// IsName checks if the name provided is equals to the Section name, case insensitive.
func (s *Section) IsName(name string) bool {
return strings.EqualFold(s.Name, name)
}
// Subsection returns a Subsection from the specified Section. If the
// Subsection does not exists, new one is created and added to Section.
func (s *Section) Subsection(name string) *Subsection {
for i := len(s.Subsections) - 1; i >= 0; i-- {
ss := s.Subsections[i]
if ss.IsName(name) {
return ss
}
}
ss := &Subsection{Name: name}
s.Subsections = append(s.Subsections, ss)
return ss
}
// HasSubsection checks if the Section has a Subsection with the specified name.
func (s *Section) HasSubsection(name string) bool {
for _, ss := range s.Subsections {
if ss.IsName(name) {
return true
}
}
return false
}
// RemoveSubsection removes a subsection from a Section.
func (s *Section) RemoveSubsection(name string) *Section {
result := Subsections{}
for _, s := range s.Subsections {
if !s.IsName(name) {
result = append(result, s)
}
}
s.Subsections = result
return s
}
// Option returns the value for the specified key. Empty string is returned if
// key does not exists.
func (s *Section) Option(key string) string {
return s.Options.Get(key)
}
// OptionAll returns all possible values for an option with the specified key.
// If the option does not exists, an empty slice will be returned.
func (s *Section) OptionAll(key string) []string {
return s.Options.GetAll(key)
}
// HasOption checks if the Section has an Option with the given key.
func (s *Section) HasOption(key string) bool {
return s.Options.Has(key)
}
// AddOption adds a new Option to the Section. The updated Section is returned.
func (s *Section) AddOption(key string, value string) *Section {
s.Options = s.Options.withAddedOption(key, value)
return s
}
// SetOption adds a new Option to the Section. If the option already exists, is replaced.
// The updated Section is returned.
func (s *Section) SetOption(key string, value string) *Section {
s.Options = s.Options.withSettedOption(key, value)
return s
}
// Remove an option with the specified key. The updated Section is returned.
func (s *Section) RemoveOption(key string) *Section {
s.Options = s.Options.withoutOption(key)
return s
}
// IsName checks if the name of the subsection is exactly the specified name.
func (s *Subsection) IsName(name string) bool {
return s.Name == name
}
// Option returns an option with the specified key. If the option does not exists,
// empty spring will be returned.
func (s *Subsection) Option(key string) string {
return s.Options.Get(key)
}
// OptionAll returns all possible values for an option with the specified key.
// If the option does not exists, an empty slice will be returned.
func (s *Subsection) OptionAll(key string) []string {
return s.Options.GetAll(key)
}
// HasOption checks if the Subsection has an Option with the given key.
func (s *Subsection) HasOption(key string) bool {
return s.Options.Has(key)
}
// AddOption adds a new Option to the Subsection. The updated Subsection is returned.
func (s *Subsection) AddOption(key string, value string) *Subsection {
s.Options = s.Options.withAddedOption(key, value)
return s
}
// SetOption adds a new Option to the Subsection. If the option already exists, is replaced.
// The updated Subsection is returned.
func (s *Subsection) SetOption(key string, value ...string) *Subsection {
s.Options = s.Options.withSettedOption(key, value...)
return s
}
// RemoveOption removes the option with the specified key. The updated Subsection is returned.
func (s *Subsection) RemoveOption(key string) *Subsection {
s.Options = s.Options.withoutOption(key)
return s
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/diff/colorconfig.go
================================================
package diff
import "github.com/go-git/go-git/v5/plumbing/color"
// A ColorKey is a key into a ColorConfig map and also equal to the key in the
// diff.color subsection of the config. See
// https://github.com/git/git/blob/v2.26.2/diff.c#L83-L106.
type ColorKey string
// ColorKeys.
const (
Context ColorKey = "context"
Meta ColorKey = "meta"
Frag ColorKey = "frag"
Old ColorKey = "old"
New ColorKey = "new"
Commit ColorKey = "commit"
Whitespace ColorKey = "whitespace"
Func ColorKey = "func"
OldMoved ColorKey = "oldMoved"
OldMovedAlternative ColorKey = "oldMovedAlternative"
OldMovedDimmed ColorKey = "oldMovedDimmed"
OldMovedAlternativeDimmed ColorKey = "oldMovedAlternativeDimmed"
NewMoved ColorKey = "newMoved"
NewMovedAlternative ColorKey = "newMovedAlternative"
NewMovedDimmed ColorKey = "newMovedDimmed"
NewMovedAlternativeDimmed ColorKey = "newMovedAlternativeDimmed"
ContextDimmed ColorKey = "contextDimmed"
OldDimmed ColorKey = "oldDimmed"
NewDimmed ColorKey = "newDimmed"
ContextBold ColorKey = "contextBold"
OldBold ColorKey = "oldBold"
NewBold ColorKey = "newBold"
)
// A ColorConfig is a color configuration. A nil or empty ColorConfig
// corresponds to no color.
type ColorConfig map[ColorKey]string
// A ColorConfigOption sets an option on a ColorConfig.
type ColorConfigOption func(ColorConfig)
// WithColor sets the color for key.
func WithColor(key ColorKey, color string) ColorConfigOption {
return func(cc ColorConfig) {
cc[key] = color
}
}
// defaultColorConfig is the default color configuration. See
// https://github.com/git/git/blob/v2.26.2/diff.c#L57-L81.
var defaultColorConfig = ColorConfig{
Context: color.Normal,
Meta: color.Bold,
Frag: color.Cyan,
Old: color.Red,
New: color.Green,
Commit: color.Yellow,
Whitespace: color.BgRed,
Func: color.Normal,
OldMoved: color.BoldMagenta,
OldMovedAlternative: color.BoldBlue,
OldMovedDimmed: color.Faint,
OldMovedAlternativeDimmed: color.FaintItalic,
NewMoved: color.BoldCyan,
NewMovedAlternative: color.BoldYellow,
NewMovedDimmed: color.Faint,
NewMovedAlternativeDimmed: color.FaintItalic,
ContextDimmed: color.Faint,
OldDimmed: color.FaintRed,
NewDimmed: color.FaintGreen,
ContextBold: color.Bold,
OldBold: color.BoldRed,
NewBold: color.BoldGreen,
}
// NewColorConfig returns a new ColorConfig.
func NewColorConfig(options ...ColorConfigOption) ColorConfig {
cc := make(ColorConfig)
for key, value := range defaultColorConfig {
cc[key] = value
}
for _, option := range options {
option(cc)
}
return cc
}
// Reset returns the ANSI escape sequence to reset the color with key set from
// cc. If no color was set then no reset is needed so it returns the empty
// string.
func (cc ColorConfig) Reset(key ColorKey) string {
if cc[key] == "" {
return ""
}
return color.Reset
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/diff/patch.go
================================================
package diff
import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
)
// Operation defines the operation of a diff item.
type Operation int
const (
// Equal item represents an equals diff.
Equal Operation = iota
// Add item represents an insert diff.
Add
// Delete item represents a delete diff.
Delete
)
// Patch represents a collection of steps to transform several files.
type Patch interface {
// FilePatches returns a slice of patches per file.
FilePatches() []FilePatch
// Message returns an optional message that can be at the top of the
// Patch representation.
Message() string
}
// FilePatch represents the necessary steps to transform one file into another.
type FilePatch interface {
// IsBinary returns true if this patch is representing a binary file.
IsBinary() bool
// Files returns the from and to Files, with all the necessary metadata
// about them. If the patch creates a new file, "from" will be nil.
// If the patch deletes a file, "to" will be nil.
Files() (from, to File)
// Chunks returns a slice of ordered changes to transform "from" File into
// "to" File. If the file is a binary one, Chunks will be empty.
Chunks() []Chunk
}
// File contains all the file metadata necessary to print some patch formats.
type File interface {
// Hash returns the File Hash.
Hash() plumbing.Hash
// Mode returns the FileMode.
Mode() filemode.FileMode
// Path returns the complete Path to the file, including the filename.
Path() string
}
// Chunk represents a portion of a file transformation into another.
type Chunk interface {
// Content contains the portion of the file.
Content() string
// Type contains the Operation to do with this Chunk.
Type() Operation
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/diff/unified_encoder.go
================================================
package diff
import (
"fmt"
"io"
"regexp"
"strconv"
"strings"
"github.com/go-git/go-git/v5/plumbing"
)
// DefaultContextLines is the default number of context lines.
const DefaultContextLines = 3
var (
splitLinesRegexp = regexp.MustCompile(`[^\n]*(\n|$)`)
operationChar = map[Operation]byte{
Add: '+',
Delete: '-',
Equal: ' ',
}
operationColorKey = map[Operation]ColorKey{
Add: New,
Delete: Old,
Equal: Context,
}
)
// UnifiedEncoder encodes an unified diff into the provided Writer. It does not
// support similarity index for renames or sorting hash representations.
type UnifiedEncoder struct {
io.Writer
// contextLines is the count of unchanged lines that will appear surrounding
// a change.
contextLines int
// srcPrefix and dstPrefix are prepended to file paths when encoding a diff.
srcPrefix string
dstPrefix string
// colorConfig is the color configuration. The default is no color.
color ColorConfig
}
// NewUnifiedEncoder returns a new UnifiedEncoder that writes to w.
func NewUnifiedEncoder(w io.Writer, contextLines int) *UnifiedEncoder {
return &UnifiedEncoder{
Writer: w,
srcPrefix: "a/",
dstPrefix: "b/",
contextLines: contextLines,
}
}
// SetColor sets e's color configuration and returns e.
func (e *UnifiedEncoder) SetColor(colorConfig ColorConfig) *UnifiedEncoder {
e.color = colorConfig
return e
}
// SetSrcPrefix sets e's srcPrefix and returns e.
func (e *UnifiedEncoder) SetSrcPrefix(prefix string) *UnifiedEncoder {
e.srcPrefix = prefix
return e
}
// SetDstPrefix sets e's dstPrefix and returns e.
func (e *UnifiedEncoder) SetDstPrefix(prefix string) *UnifiedEncoder {
e.dstPrefix = prefix
return e
}
// Encode encodes patch.
func (e *UnifiedEncoder) Encode(patch Patch) error {
sb := &strings.Builder{}
if message := patch.Message(); message != "" {
sb.WriteString(message)
if !strings.HasSuffix(message, "\n") {
sb.WriteByte('\n')
}
}
for _, filePatch := range patch.FilePatches() {
e.writeFilePatchHeader(sb, filePatch)
g := newHunksGenerator(filePatch.Chunks(), e.contextLines)
for _, hunk := range g.Generate() {
hunk.writeTo(sb, e.color)
}
}
_, err := e.Write([]byte(sb.String()))
return err
}
func (e *UnifiedEncoder) writeFilePatchHeader(sb *strings.Builder, filePatch FilePatch) {
from, to := filePatch.Files()
if from == nil && to == nil {
return
}
isBinary := filePatch.IsBinary()
var lines []string
switch {
case from != nil && to != nil:
hashEquals := from.Hash() == to.Hash()
lines = append(lines,
fmt.Sprintf("diff --git %s%s %s%s",
e.srcPrefix, from.Path(), e.dstPrefix, to.Path()),
)
if from.Mode() != to.Mode() {
lines = append(lines,
fmt.Sprintf("old mode %o", from.Mode()),
fmt.Sprintf("new mode %o", to.Mode()),
)
}
if from.Path() != to.Path() {
lines = append(lines,
fmt.Sprintf("rename from %s", from.Path()),
fmt.Sprintf("rename to %s", to.Path()),
)
}
if from.Mode() != to.Mode() && !hashEquals {
lines = append(lines,
fmt.Sprintf("index %s..%s", from.Hash(), to.Hash()),
)
} else if !hashEquals {
lines = append(lines,
fmt.Sprintf("index %s..%s %o", from.Hash(), to.Hash(), from.Mode()),
)
}
if !hashEquals {
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), e.dstPrefix+to.Path(), isBinary)
}
case from == nil:
lines = append(lines,
fmt.Sprintf("diff --git %s %s", e.srcPrefix+to.Path(), e.dstPrefix+to.Path()),
fmt.Sprintf("new file mode %o", to.Mode()),
fmt.Sprintf("index %s..%s", plumbing.ZeroHash, to.Hash()),
)
lines = e.appendPathLines(lines, "/dev/null", e.dstPrefix+to.Path(), isBinary)
case to == nil:
lines = append(lines,
fmt.Sprintf("diff --git %s %s", e.srcPrefix+from.Path(), e.dstPrefix+from.Path()),
fmt.Sprintf("deleted file mode %o", from.Mode()),
fmt.Sprintf("index %s..%s", from.Hash(), plumbing.ZeroHash),
)
lines = e.appendPathLines(lines, e.srcPrefix+from.Path(), "/dev/null", isBinary)
}
sb.WriteString(e.color[Meta])
sb.WriteString(lines[0])
for _, line := range lines[1:] {
sb.WriteByte('\n')
sb.WriteString(line)
}
sb.WriteString(e.color.Reset(Meta))
sb.WriteByte('\n')
}
func (e *UnifiedEncoder) appendPathLines(lines []string, fromPath, toPath string, isBinary bool) []string {
if isBinary {
return append(lines,
fmt.Sprintf("Binary files %s and %s differ", fromPath, toPath),
)
}
return append(lines,
fmt.Sprintf("--- %s", fromPath),
fmt.Sprintf("+++ %s", toPath),
)
}
type hunksGenerator struct {
fromLine, toLine int
ctxLines int
chunks []Chunk
current *hunk
hunks []*hunk
beforeContext, afterContext []string
}
func newHunksGenerator(chunks []Chunk, ctxLines int) *hunksGenerator {
return &hunksGenerator{
chunks: chunks,
ctxLines: ctxLines,
}
}
func (g *hunksGenerator) Generate() []*hunk {
for i, chunk := range g.chunks {
lines := splitLines(chunk.Content())
nLines := len(lines)
switch chunk.Type() {
case Equal:
g.fromLine += nLines
g.toLine += nLines
g.processEqualsLines(lines, i)
case Delete:
if nLines != 0 {
g.fromLine++
}
g.processHunk(i, chunk.Type())
g.fromLine += nLines - 1
g.current.AddOp(chunk.Type(), lines...)
case Add:
if nLines != 0 {
g.toLine++
}
g.processHunk(i, chunk.Type())
g.toLine += nLines - 1
g.current.AddOp(chunk.Type(), lines...)
}
if i == len(g.chunks)-1 && g.current != nil {
g.hunks = append(g.hunks, g.current)
}
}
return g.hunks
}
func (g *hunksGenerator) processHunk(i int, op Operation) {
if g.current != nil {
return
}
var ctxPrefix string
linesBefore := len(g.beforeContext)
if linesBefore > g.ctxLines {
ctxPrefix = g.beforeContext[linesBefore-g.ctxLines-1]
g.beforeContext = g.beforeContext[linesBefore-g.ctxLines:]
linesBefore = g.ctxLines
}
g.current = &hunk{ctxPrefix: strings.TrimSuffix(ctxPrefix, "\n")}
g.current.AddOp(Equal, g.beforeContext...)
switch op {
case Delete:
g.current.fromLine, g.current.toLine =
g.addLineNumbers(g.fromLine, g.toLine, linesBefore, i, Add)
case Add:
g.current.toLine, g.current.fromLine =
g.addLineNumbers(g.toLine, g.fromLine, linesBefore, i, Delete)
}
g.beforeContext = nil
}
// addLineNumbers obtains the line numbers in a new chunk.
func (g *hunksGenerator) addLineNumbers(la, lb int, linesBefore int, i int, op Operation) (cla, clb int) {
cla = la - linesBefore
// we need to search for a reference for the next diff
switch {
case linesBefore != 0 && g.ctxLines != 0:
if lb > g.ctxLines {
clb = lb - g.ctxLines + 1
} else {
clb = 1
}
case g.ctxLines == 0:
clb = lb
case i != len(g.chunks)-1:
next := g.chunks[i+1]
if next.Type() == op || next.Type() == Equal {
// this diff will be into this chunk
clb = lb + 1
}
}
return
}
func (g *hunksGenerator) processEqualsLines(ls []string, i int) {
if g.current == nil {
g.beforeContext = append(g.beforeContext, ls...)
return
}
g.afterContext = append(g.afterContext, ls...)
if len(g.afterContext) <= g.ctxLines*2 && i != len(g.chunks)-1 {
g.current.AddOp(Equal, g.afterContext...)
g.afterContext = nil
} else {
ctxLines := g.ctxLines
if ctxLines > len(g.afterContext) {
ctxLines = len(g.afterContext)
}
g.current.AddOp(Equal, g.afterContext[:ctxLines]...)
g.hunks = append(g.hunks, g.current)
g.current = nil
g.beforeContext = g.afterContext[ctxLines:]
g.afterContext = nil
}
}
func splitLines(s string) []string {
out := splitLinesRegexp.FindAllString(s, -1)
if out[len(out)-1] == "" {
out = out[:len(out)-1]
}
return out
}
type hunk struct {
fromLine int
toLine int
fromCount int
toCount int
ctxPrefix string
ops []*op
}
func (h *hunk) writeTo(sb *strings.Builder, color ColorConfig) {
sb.WriteString(color[Frag])
sb.WriteString("@@ -")
if h.fromCount == 1 {
sb.WriteString(strconv.Itoa(h.fromLine))
} else {
sb.WriteString(strconv.Itoa(h.fromLine))
sb.WriteByte(',')
sb.WriteString(strconv.Itoa(h.fromCount))
}
sb.WriteString(" +")
if h.toCount == 1 {
sb.WriteString(strconv.Itoa(h.toLine))
} else {
sb.WriteString(strconv.Itoa(h.toLine))
sb.WriteByte(',')
sb.WriteString(strconv.Itoa(h.toCount))
}
sb.WriteString(" @@")
sb.WriteString(color.Reset(Frag))
if h.ctxPrefix != "" {
sb.WriteByte(' ')
sb.WriteString(color[Func])
sb.WriteString(h.ctxPrefix)
sb.WriteString(color.Reset(Func))
}
sb.WriteByte('\n')
for _, op := range h.ops {
op.writeTo(sb, color)
}
}
func (h *hunk) AddOp(t Operation, ss ...string) {
n := len(ss)
switch t {
case Add:
h.toCount += n
case Delete:
h.fromCount += n
case Equal:
h.toCount += n
h.fromCount += n
}
for _, s := range ss {
h.ops = append(h.ops, &op{s, t})
}
}
type op struct {
text string
t Operation
}
func (o *op) writeTo(sb *strings.Builder, color ColorConfig) {
colorKey := operationColorKey[o.t]
sb.WriteString(color[colorKey])
sb.WriteByte(operationChar[o.t])
if strings.HasSuffix(o.text, "\n") {
sb.WriteString(strings.TrimSuffix(o.text, "\n"))
} else {
sb.WriteString(o.text + "\n\\ No newline at end of file")
}
sb.WriteString(color.Reset(colorKey))
sb.WriteByte('\n')
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/dir.go
================================================
package gitignore
import (
"bufio"
"bytes"
"io"
"os"
"strings"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/internal/path_util"
"github.com/go-git/go-git/v5/plumbing/format/config"
gioutil "github.com/go-git/go-git/v5/utils/ioutil"
)
const (
commentPrefix = "#"
coreSection = "core"
excludesfile = "excludesfile"
gitDir = ".git"
gitignoreFile = ".gitignore"
gitconfigFile = ".gitconfig"
systemFile = "/etc/gitconfig"
infoExcludeFile = gitDir + "/info/exclude"
)
// readIgnoreFile reads a specific git ignore file.
func readIgnoreFile(fs billy.Filesystem, path []string, ignoreFile string) (ps []Pattern, err error) {
ignoreFile, _ = path_util.ReplaceTildeWithHome(ignoreFile)
f, err := fs.Open(fs.Join(append(path, ignoreFile)...))
if err == nil {
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
s := scanner.Text()
if !strings.HasPrefix(s, commentPrefix) && len(strings.TrimSpace(s)) > 0 {
ps = append(ps, ParsePattern(s, path))
}
}
} else if !os.IsNotExist(err) {
return nil, err
}
return
}
// ReadPatterns reads the .git/info/exclude and then the gitignore patterns
// recursively traversing through the directory structure. The result is in
// the ascending order of priority (last higher).
func ReadPatterns(fs billy.Filesystem, path []string) (ps []Pattern, err error) {
ps, _ = readIgnoreFile(fs, path, infoExcludeFile)
subps, _ := readIgnoreFile(fs, path, gitignoreFile)
ps = append(ps, subps...)
var fis []os.FileInfo
fis, err = fs.ReadDir(fs.Join(path...))
if err != nil {
return
}
for _, fi := range fis {
if fi.IsDir() && fi.Name() != gitDir {
if NewMatcher(ps).Match(append(path, fi.Name()), true) {
continue
}
var subps []Pattern
subps, err = ReadPatterns(fs, append(path, fi.Name()))
if err != nil {
return
}
if len(subps) > 0 {
ps = append(ps, subps...)
}
}
}
return
}
func loadPatterns(fs billy.Filesystem, path string) (ps []Pattern, err error) {
f, err := fs.Open(path)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer gioutil.CheckClose(f, &err)
b, err := io.ReadAll(f)
if err != nil {
return
}
d := config.NewDecoder(bytes.NewBuffer(b))
raw := config.New()
if err = d.Decode(raw); err != nil {
return
}
s := raw.Section(coreSection)
efo := s.Options.Get(excludesfile)
if efo == "" {
return nil, nil
}
ps, err = readIgnoreFile(fs, nil, efo)
if os.IsNotExist(err) {
return nil, nil
}
return
}
// LoadGlobalPatterns loads gitignore patterns from the gitignore file
// declared in a user's ~/.gitconfig file. If the ~/.gitconfig file does not
// exist the function will return nil. If the core.excludesfile property
// is not declared, the function will return nil. If the file pointed to by
// the core.excludesfile property does not exist, the function will return nil.
//
// The function assumes fs is rooted at the root filesystem.
func LoadGlobalPatterns(fs billy.Filesystem) (ps []Pattern, err error) {
home, err := os.UserHomeDir()
if err != nil {
return
}
return loadPatterns(fs, fs.Join(home, gitconfigFile))
}
// LoadSystemPatterns loads gitignore patterns from the gitignore file
// declared in a system's /etc/gitconfig file. If the /etc/gitconfig file does
// not exist the function will return nil. If the core.excludesfile property
// is not declared, the function will return nil. If the file pointed to by
// the core.excludesfile property does not exist, the function will return nil.
//
// The function assumes fs is rooted at the root filesystem.
func LoadSystemPatterns(fs billy.Filesystem) (ps []Pattern, err error) {
return loadPatterns(fs, systemFile)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/doc.go
================================================
// Package gitignore implements matching file system paths to gitignore patterns that
// can be automatically read from a git repository tree in the order of definition
// priorities. It support all pattern formats as specified in the original gitignore
// documentation, copied below:
//
// Pattern format
// ==============
//
// - A blank line matches no files, so it can serve as a separator for readability.
//
// - A line starting with # serves as a comment. Put a backslash ("\") in front of
// the first hash for patterns that begin with a hash.
//
// - Trailing spaces are ignored unless they are quoted with backslash ("\").
//
// - An optional prefix "!" which negates the pattern; any matching file excluded
// by a previous pattern will become included again. It is not possible to
// re-include a file if a parent directory of that file is excluded.
// Git doesn’t list excluded directories for performance reasons, so
// any patterns on contained files have no effect, no matter where they are
// defined. Put a backslash ("\") in front of the first "!" for patterns
// that begin with a literal "!", for example, "\!important!.txt".
//
// - If the pattern ends with a slash, it is removed for the purpose of the
// following description, but it would only find a match with a directory.
// In other words, foo/ will match a directory foo and paths underneath it,
// but will not match a regular file or a symbolic link foo (this is consistent
// with the way how pathspec works in general in Git).
//
// - If the pattern does not contain a slash /, Git treats it as a shell glob
// pattern and checks for a match against the pathname relative to the location
// of the .gitignore file (relative to the toplevel of the work tree if not
// from a .gitignore file).
//
// - Otherwise, Git treats the pattern as a shell glob suitable for consumption
// by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will
// not match a / in the pathname. For example, "Documentation/*.html" matches
// "Documentation/git.html" but not "Documentation/ppc/ppc.html" or
// "tools/perf/Documentation/perf.html".
//
// - A leading slash matches the beginning of the pathname. For example,
// "/*.c" matches "cat-file.c" but not "mozilla-sha1/sha1.c".
//
// Two consecutive asterisks ("**") in patterns matched against full pathname
// may have special meaning:
//
// - A leading "**" followed by a slash means match in all directories.
// For example, "**/foo" matches file or directory "foo" anywhere, the same as
// pattern "foo". "**/foo/bar" matches file or directory "bar"
// anywhere that is directly under directory "foo".
//
// - A trailing "/**" matches everything inside. For example, "abc/**" matches
// all files inside directory "abc", relative to the location of the
// .gitignore file, with infinite depth.
//
// - A slash followed by two consecutive asterisks then a slash matches
// zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b",
// "a/x/y/b" and so on.
//
// - Other consecutive asterisks are considered invalid.
//
// Copyright and license
// =====================
//
// Copyright (c) Oleg Sklyar, Silvertern and source{d}
//
// The package code was donated to source{d} to include, modify and develop
// further as a part of the `go-git` project, release it on the license of
// the whole project or delete it from the project.
package gitignore
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/matcher.go
================================================
package gitignore
// Matcher defines a global multi-pattern matcher for gitignore patterns
type Matcher interface {
// Match matches patterns in the order of priorities. As soon as an inclusion or
// exclusion is found, not further matching is performed.
Match(path []string, isDir bool) bool
}
// NewMatcher constructs a new global matcher. Patterns must be given in the order of
// increasing priority. That is most generic settings files first, then the content of
// the repo .gitignore, then content of .gitignore down the path or the repo and then
// the content command line arguments.
func NewMatcher(ps []Pattern) Matcher {
return &matcher{ps}
}
type matcher struct {
patterns []Pattern
}
func (m *matcher) Match(path []string, isDir bool) bool {
n := len(m.patterns)
for i := n - 1; i >= 0; i-- {
if match := m.patterns[i].Match(path, isDir); match > NoMatch {
return match == Exclude
}
}
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/gitignore/pattern.go
================================================
package gitignore
import (
"path/filepath"
"strings"
)
// MatchResult defines outcomes of a match, no match, exclusion or inclusion.
type MatchResult int
const (
// NoMatch defines the no match outcome of a match check
NoMatch MatchResult = iota
// Exclude defines an exclusion of a file as a result of a match check
Exclude
// Include defines an explicit inclusion of a file as a result of a match check
Include
)
const (
inclusionPrefix = "!"
zeroToManyDirs = "**"
patternDirSep = "/"
)
// Pattern defines a single gitignore pattern.
type Pattern interface {
// Match matches the given path to the pattern.
Match(path []string, isDir bool) MatchResult
}
type pattern struct {
domain []string
pattern []string
inclusion bool
dirOnly bool
isGlob bool
}
// ParsePattern parses a gitignore pattern string into the Pattern structure.
func ParsePattern(p string, domain []string) Pattern {
// storing domain, copy it to ensure it isn't changed externally
domain = append([]string(nil), domain...)
res := pattern{domain: domain}
if strings.HasPrefix(p, inclusionPrefix) {
res.inclusion = true
p = p[1:]
}
if !strings.HasSuffix(p, "\\ ") {
p = strings.TrimRight(p, " ")
}
if strings.HasSuffix(p, patternDirSep) {
res.dirOnly = true
p = p[:len(p)-1]
}
if strings.Contains(p, patternDirSep) {
res.isGlob = true
}
res.pattern = strings.Split(p, patternDirSep)
return &res
}
func (p *pattern) Match(path []string, isDir bool) MatchResult {
if len(path) <= len(p.domain) {
return NoMatch
}
for i, e := range p.domain {
if path[i] != e {
return NoMatch
}
}
path = path[len(p.domain):]
if p.isGlob && !p.globMatch(path, isDir) {
return NoMatch
} else if !p.isGlob && !p.simpleNameMatch(path, isDir) {
return NoMatch
}
if p.inclusion {
return Include
} else {
return Exclude
}
}
func (p *pattern) simpleNameMatch(path []string, isDir bool) bool {
for i, name := range path {
if match, err := filepath.Match(p.pattern[0], name); err != nil {
return false
} else if !match {
continue
}
if p.dirOnly && !isDir && i == len(path)-1 {
return false
}
return true
}
return false
}
func (p *pattern) globMatch(path []string, isDir bool) bool {
matched := false
canTraverse := false
for i, pattern := range p.pattern {
if pattern == "" {
canTraverse = false
continue
}
if pattern == zeroToManyDirs {
if i == len(p.pattern)-1 {
break
}
canTraverse = true
continue
}
if strings.Contains(pattern, zeroToManyDirs) {
return false
}
if len(path) == 0 {
return false
}
if canTraverse {
canTraverse = false
for len(path) > 0 {
e := path[0]
path = path[1:]
if match, err := filepath.Match(pattern, e); err != nil {
return false
} else if match {
matched = true
break
} else if len(path) == 0 {
// if nothing left then fail
matched = false
}
}
} else {
if match, err := filepath.Match(pattern, path[0]); err != nil || !match {
return false
}
matched = true
path = path[1:]
}
}
if matched && p.dirOnly && !isDir && len(path) == 0 {
matched = false
}
return matched
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/decoder.go
================================================
package idxfile
import (
"bufio"
"bytes"
"errors"
"io"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/utils/binary"
)
var (
// ErrUnsupportedVersion is returned by Decode when the idx file version
// is not supported.
ErrUnsupportedVersion = errors.New("unsupported version")
// ErrMalformedIdxFile is returned by Decode when the idx file is corrupted.
ErrMalformedIdxFile = errors.New("malformed IDX file")
)
const (
fanout = 256
objectIDLength = hash.Size
)
// Decoder reads and decodes idx files from an input stream.
type Decoder struct {
*bufio.Reader
}
// NewDecoder builds a new idx stream decoder, that reads from r.
func NewDecoder(r io.Reader) *Decoder {
return &Decoder{bufio.NewReader(r)}
}
// Decode reads from the stream and decode the content into the MemoryIndex struct.
func (d *Decoder) Decode(idx *MemoryIndex) error {
if err := validateHeader(d); err != nil {
return err
}
flow := []func(*MemoryIndex, io.Reader) error{
readVersion,
readFanout,
readObjectNames,
readCRC32,
readOffsets,
readChecksums,
}
for _, f := range flow {
if err := f(idx, d); err != nil {
return err
}
}
return nil
}
func validateHeader(r io.Reader) error {
var h = make([]byte, 4)
if _, err := io.ReadFull(r, h); err != nil {
return err
}
if !bytes.Equal(h, idxHeader) {
return ErrMalformedIdxFile
}
return nil
}
func readVersion(idx *MemoryIndex, r io.Reader) error {
v, err := binary.ReadUint32(r)
if err != nil {
return err
}
if v > VersionSupported {
return ErrUnsupportedVersion
}
idx.Version = v
return nil
}
func readFanout(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
n, err := binary.ReadUint32(r)
if err != nil {
return err
}
idx.Fanout[k] = n
idx.FanoutMapping[k] = noMapping
}
return nil
}
func readObjectNames(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
var buckets uint32
if k == 0 {
buckets = idx.Fanout[k]
} else {
buckets = idx.Fanout[k] - idx.Fanout[k-1]
}
if buckets == 0 {
continue
}
idx.FanoutMapping[k] = len(idx.Names)
nameLen := int(buckets * objectIDLength)
bin := make([]byte, nameLen)
if _, err := io.ReadFull(r, bin); err != nil {
return err
}
idx.Names = append(idx.Names, bin)
idx.Offset32 = append(idx.Offset32, make([]byte, buckets*4))
idx.CRC32 = append(idx.CRC32, make([]byte, buckets*4))
}
return nil
}
func readCRC32(idx *MemoryIndex, r io.Reader) error {
for k := 0; k < fanout; k++ {
if pos := idx.FanoutMapping[k]; pos != noMapping {
if _, err := io.ReadFull(r, idx.CRC32[pos]); err != nil {
return err
}
}
}
return nil
}
func readOffsets(idx *MemoryIndex, r io.Reader) error {
var o64cnt int
for k := 0; k < fanout; k++ {
if pos := idx.FanoutMapping[k]; pos != noMapping {
if _, err := io.ReadFull(r, idx.Offset32[pos]); err != nil {
return err
}
for p := 0; p < len(idx.Offset32[pos]); p += 4 {
if idx.Offset32[pos][p]&(byte(1)<<7) > 0 {
o64cnt++
}
}
}
}
if o64cnt > 0 {
idx.Offset64 = make([]byte, o64cnt*8)
if _, err := io.ReadFull(r, idx.Offset64); err != nil {
return err
}
}
return nil
}
func readChecksums(idx *MemoryIndex, r io.Reader) error {
if _, err := io.ReadFull(r, idx.PackfileChecksum[:]); err != nil {
return err
}
if _, err := io.ReadFull(r, idx.IdxChecksum[:]); err != nil {
return err
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/doc.go
================================================
// Package idxfile implements encoding and decoding of packfile idx files.
//
// == Original (version 1) pack-*.idx files have the following format:
//
// - The header consists of 256 4-byte network byte order
// integers. N-th entry of this table records the number of
// objects in the corresponding pack, the first byte of whose
// object name is less than or equal to N. This is called the
// 'first-level fan-out' table.
//
// - The header is followed by sorted 24-byte entries, one entry
// per object in the pack. Each entry is:
//
// 4-byte network byte order integer, recording where the
// object is stored in the packfile as the offset from the
// beginning.
//
// 20-byte object name.
//
// - The file is concluded with a trailer:
//
// A copy of the 20-byte SHA1 checksum at the end of
// corresponding packfile.
//
// 20-byte SHA1-checksum of all of the above.
//
// Pack Idx file:
//
// -- +--------------------------------+
// fanout | fanout[0] = 2 (for example) |-.
// table +--------------------------------+ |
// | fanout[1] | |
// +--------------------------------+ |
// | fanout[2] | |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
// | fanout[255] = total objects |---.
// -- +--------------------------------+ | |
// main | offset | | |
// index | object name 00XXXXXXXXXXXXXXXX | | |
// tab +--------------------------------+ | |
// | offset | | |
// | object name 00XXXXXXXXXXXXXXXX | | |
// +--------------------------------+<+ |
// .-| offset | |
// | | object name 01XXXXXXXXXXXXXXXX | |
// | +--------------------------------+ |
// | | offset | |
// | | object name 01XXXXXXXXXXXXXXXX | |
// | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
// | | offset | |
// | | object name FFXXXXXXXXXXXXXXXX | |
// --| +--------------------------------+<--+
// trailer | | packfile checksum |
// | +--------------------------------+
// | | idxfile checksum |
// | +--------------------------------+
// .---------.
// |
// Pack file entry: <+
//
// packed object header:
// 1-byte size extension bit (MSB)
// type (next 3 bit)
// size0 (lower 4-bit)
// n-byte sizeN (as long as MSB is set, each 7-bit)
// size0..sizeN form 4+7+7+..+7 bit integer, size0
// is the least significant part, and sizeN is the
// most significant part.
// packed object data:
// If it is not DELTA, then deflated bytes (the size above
// is the size before compression).
// If it is REF_DELTA, then
// 20-byte base object name SHA1 (the size above is the
// size of the delta data that follows).
// delta data, deflated.
// If it is OFS_DELTA, then
// n-byte offset (see below) interpreted as a negative
// offset from the type-byte of the header of the
// ofs-delta entry (the size above is the size of
// the delta data that follows).
// delta data, deflated.
//
// offset encoding:
// n bytes with MSB set in all but the last one.
// The offset is then the number constructed by
// concatenating the lower 7 bit of each byte, and
// for n >= 2 adding 2^7 + 2^14 + ... + 2^(7*(n-1))
// to the result.
//
// == Version 2 pack-*.idx files support packs larger than 4 GiB, and
// have some other reorganizations. They have the format:
//
// - A 4-byte magic number '\377tOc' which is an unreasonable
// fanout[0] value.
//
// - A 4-byte version number (= 2)
//
// - A 256-entry fan-out table just like v1.
//
// - A table of sorted 20-byte SHA1 object names. These are
// packed together without offset values to reduce the cache
// footprint of the binary search for a specific object name.
//
// - A table of 4-byte CRC32 values of the packed object data.
// This is new in v2 so compressed data can be copied directly
// from pack to pack during repacking without undetected
// data corruption.
//
// - A table of 4-byte offset values (in network byte order).
// These are usually 31-bit pack file offsets, but large
// offsets are encoded as an index into the next table with
// the msbit set.
//
// - A table of 8-byte offset entries (empty for pack files less
// than 2 GiB). Pack files are organized with heavily used
// objects toward the front, so most object references should
// not need to refer to this table.
//
// - The same trailer as a v1 pack file:
//
// A copy of the 20-byte SHA1 checksum at the end of
// corresponding packfile.
//
// 20-byte SHA1-checksum of all of the above.
//
// Source:
// https://www.kernel.org/pub/software/scm/git/docs/v1.7.5/technical/pack-format.txt
package idxfile
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/encoder.go
================================================
package idxfile
import (
"io"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/utils/binary"
)
// Encoder writes MemoryIndex structs to an output stream.
type Encoder struct {
io.Writer
hash hash.Hash
}
// NewEncoder returns a new stream encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
h := hash.New(hash.CryptoType)
mw := io.MultiWriter(w, h)
return &Encoder{mw, h}
}
// Encode encodes an MemoryIndex to the encoder writer.
func (e *Encoder) Encode(idx *MemoryIndex) (int, error) {
flow := []func(*MemoryIndex) (int, error){
e.encodeHeader,
e.encodeFanout,
e.encodeHashes,
e.encodeCRC32,
e.encodeOffsets,
e.encodeChecksums,
}
sz := 0
for _, f := range flow {
i, err := f(idx)
sz += i
if err != nil {
return sz, err
}
}
return sz, nil
}
func (e *Encoder) encodeHeader(idx *MemoryIndex) (int, error) {
c, err := e.Write(idxHeader)
if err != nil {
return c, err
}
return c + 4, binary.WriteUint32(e, idx.Version)
}
func (e *Encoder) encodeFanout(idx *MemoryIndex) (int, error) {
for _, c := range idx.Fanout {
if err := binary.WriteUint32(e, c); err != nil {
return 0, err
}
}
return fanout * 4, nil
}
func (e *Encoder) encodeHashes(idx *MemoryIndex) (int, error) {
var size int
for k := 0; k < fanout; k++ {
pos := idx.FanoutMapping[k]
if pos == noMapping {
continue
}
n, err := e.Write(idx.Names[pos])
if err != nil {
return size, err
}
size += n
}
return size, nil
}
func (e *Encoder) encodeCRC32(idx *MemoryIndex) (int, error) {
var size int
for k := 0; k < fanout; k++ {
pos := idx.FanoutMapping[k]
if pos == noMapping {
continue
}
n, err := e.Write(idx.CRC32[pos])
if err != nil {
return size, err
}
size += n
}
return size, nil
}
func (e *Encoder) encodeOffsets(idx *MemoryIndex) (int, error) {
var size int
for k := 0; k < fanout; k++ {
pos := idx.FanoutMapping[k]
if pos == noMapping {
continue
}
n, err := e.Write(idx.Offset32[pos])
if err != nil {
return size, err
}
size += n
}
if len(idx.Offset64) > 0 {
n, err := e.Write(idx.Offset64)
if err != nil {
return size, err
}
size += n
}
return size, nil
}
func (e *Encoder) encodeChecksums(idx *MemoryIndex) (int, error) {
if _, err := e.Write(idx.PackfileChecksum[:]); err != nil {
return 0, err
}
copy(idx.IdxChecksum[:], e.hash.Sum(nil)[:hash.Size])
if _, err := e.Write(idx.IdxChecksum[:]); err != nil {
return 0, err
}
return hash.HexSize, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/idxfile.go
================================================
package idxfile
import (
"bytes"
"io"
"sort"
encbin "encoding/binary"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/hash"
)
const (
// VersionSupported is the only idx version supported.
VersionSupported = 2
noMapping = -1
)
var (
idxHeader = []byte{255, 't', 'O', 'c'}
)
// Index represents an index of a packfile.
type Index interface {
// Contains checks whether the given hash is in the index.
Contains(h plumbing.Hash) (bool, error)
// FindOffset finds the offset in the packfile for the object with
// the given hash.
FindOffset(h plumbing.Hash) (int64, error)
// FindCRC32 finds the CRC32 of the object with the given hash.
FindCRC32(h plumbing.Hash) (uint32, error)
// FindHash finds the hash for the object with the given offset.
FindHash(o int64) (plumbing.Hash, error)
// Count returns the number of entries in the index.
Count() (int64, error)
// Entries returns an iterator to retrieve all index entries.
Entries() (EntryIter, error)
// EntriesByOffset returns an iterator to retrieve all index entries ordered
// by offset.
EntriesByOffset() (EntryIter, error)
}
// MemoryIndex is the in memory representation of an idx file.
type MemoryIndex struct {
Version uint32
Fanout [256]uint32
// FanoutMapping maps the position in the fanout table to the position
// in the Names, Offset32 and CRC32 slices. This improves the memory
// usage by not needing an array with unnecessary empty slots.
FanoutMapping [256]int
Names [][]byte
Offset32 [][]byte
CRC32 [][]byte
Offset64 []byte
PackfileChecksum [hash.Size]byte
IdxChecksum [hash.Size]byte
offsetHash map[int64]plumbing.Hash
offsetHashIsFull bool
}
var _ Index = (*MemoryIndex)(nil)
// NewMemoryIndex returns an instance of a new MemoryIndex.
func NewMemoryIndex() *MemoryIndex {
return &MemoryIndex{}
}
func (idx *MemoryIndex) findHashIndex(h plumbing.Hash) (int, bool) {
k := idx.FanoutMapping[h[0]]
if k == noMapping {
return 0, false
}
if len(idx.Names) <= k {
return 0, false
}
data := idx.Names[k]
high := uint64(len(idx.Offset32[k])) >> 2
if high == 0 {
return 0, false
}
low := uint64(0)
for {
mid := (low + high) >> 1
offset := mid * objectIDLength
cmp := bytes.Compare(h[:], data[offset:offset+objectIDLength])
if cmp < 0 {
high = mid
} else if cmp == 0 {
return int(mid), true
} else {
low = mid + 1
}
if low >= high {
break
}
}
return 0, false
}
// Contains implements the Index interface.
func (idx *MemoryIndex) Contains(h plumbing.Hash) (bool, error) {
_, ok := idx.findHashIndex(h)
return ok, nil
}
// FindOffset implements the Index interface.
func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) {
if len(idx.FanoutMapping) <= int(h[0]) {
return 0, plumbing.ErrObjectNotFound
}
k := idx.FanoutMapping[h[0]]
i, ok := idx.findHashIndex(h)
if !ok {
return 0, plumbing.ErrObjectNotFound
}
offset := idx.getOffset(k, i)
if !idx.offsetHashIsFull {
// Save the offset for reverse lookup
if idx.offsetHash == nil {
idx.offsetHash = make(map[int64]plumbing.Hash)
}
idx.offsetHash[int64(offset)] = h
}
return int64(offset), nil
}
const isO64Mask = uint64(1) << 31
func (idx *MemoryIndex) getOffset(firstLevel, secondLevel int) uint64 {
offset := secondLevel << 2
ofs := encbin.BigEndian.Uint32(idx.Offset32[firstLevel][offset : offset+4])
if (uint64(ofs) & isO64Mask) != 0 {
offset := 8 * (uint64(ofs) & ^isO64Mask)
n := encbin.BigEndian.Uint64(idx.Offset64[offset : offset+8])
return n
}
return uint64(ofs)
}
// FindCRC32 implements the Index interface.
func (idx *MemoryIndex) FindCRC32(h plumbing.Hash) (uint32, error) {
k := idx.FanoutMapping[h[0]]
i, ok := idx.findHashIndex(h)
if !ok {
return 0, plumbing.ErrObjectNotFound
}
return idx.getCRC32(k, i), nil
}
func (idx *MemoryIndex) getCRC32(firstLevel, secondLevel int) uint32 {
offset := secondLevel << 2
return encbin.BigEndian.Uint32(idx.CRC32[firstLevel][offset : offset+4])
}
// FindHash implements the Index interface.
func (idx *MemoryIndex) FindHash(o int64) (plumbing.Hash, error) {
var hash plumbing.Hash
var ok bool
if idx.offsetHash != nil {
if hash, ok = idx.offsetHash[o]; ok {
return hash, nil
}
}
// Lazily generate the reverse offset/hash map if required.
if !idx.offsetHashIsFull || idx.offsetHash == nil {
if err := idx.genOffsetHash(); err != nil {
return plumbing.ZeroHash, err
}
hash, ok = idx.offsetHash[o]
}
if !ok {
return plumbing.ZeroHash, plumbing.ErrObjectNotFound
}
return hash, nil
}
// genOffsetHash generates the offset/hash mapping for reverse search.
func (idx *MemoryIndex) genOffsetHash() error {
count, err := idx.Count()
if err != nil {
return err
}
idx.offsetHash = make(map[int64]plumbing.Hash, count)
idx.offsetHashIsFull = true
var hash plumbing.Hash
i := uint32(0)
for firstLevel, fanoutValue := range idx.Fanout {
mappedFirstLevel := idx.FanoutMapping[firstLevel]
for secondLevel := uint32(0); i < fanoutValue; i++ {
copy(hash[:], idx.Names[mappedFirstLevel][secondLevel*objectIDLength:])
offset := int64(idx.getOffset(mappedFirstLevel, int(secondLevel)))
idx.offsetHash[offset] = hash
secondLevel++
}
}
return nil
}
// Count implements the Index interface.
func (idx *MemoryIndex) Count() (int64, error) {
return int64(idx.Fanout[fanout-1]), nil
}
// Entries implements the Index interface.
func (idx *MemoryIndex) Entries() (EntryIter, error) {
return &idxfileEntryIter{idx, 0, 0, 0}, nil
}
// EntriesByOffset implements the Index interface.
func (idx *MemoryIndex) EntriesByOffset() (EntryIter, error) {
count, err := idx.Count()
if err != nil {
return nil, err
}
iter := &idxfileEntryOffsetIter{
entries: make(entriesByOffset, count),
}
entries, err := idx.Entries()
if err != nil {
return nil, err
}
for pos := 0; int64(pos) < count; pos++ {
entry, err := entries.Next()
if err != nil {
return nil, err
}
iter.entries[pos] = entry
}
sort.Sort(iter.entries)
return iter, nil
}
// EntryIter is an iterator that will return the entries in a packfile index.
type EntryIter interface {
// Next returns the next entry in the packfile index.
Next() (*Entry, error)
// Close closes the iterator.
Close() error
}
type idxfileEntryIter struct {
idx *MemoryIndex
total int
firstLevel, secondLevel int
}
func (i *idxfileEntryIter) Next() (*Entry, error) {
for {
if i.firstLevel >= fanout {
return nil, io.EOF
}
if i.total >= int(i.idx.Fanout[i.firstLevel]) {
i.firstLevel++
i.secondLevel = 0
continue
}
mappedFirstLevel := i.idx.FanoutMapping[i.firstLevel]
entry := new(Entry)
copy(entry.Hash[:], i.idx.Names[mappedFirstLevel][i.secondLevel*objectIDLength:])
entry.Offset = i.idx.getOffset(mappedFirstLevel, i.secondLevel)
entry.CRC32 = i.idx.getCRC32(mappedFirstLevel, i.secondLevel)
i.secondLevel++
i.total++
return entry, nil
}
}
func (i *idxfileEntryIter) Close() error {
i.firstLevel = fanout
return nil
}
// Entry is the in memory representation of an object entry in the idx file.
type Entry struct {
Hash plumbing.Hash
CRC32 uint32
Offset uint64
}
type idxfileEntryOffsetIter struct {
entries entriesByOffset
pos int
}
func (i *idxfileEntryOffsetIter) Next() (*Entry, error) {
if i.pos >= len(i.entries) {
return nil, io.EOF
}
entry := i.entries[i.pos]
i.pos++
return entry, nil
}
func (i *idxfileEntryOffsetIter) Close() error {
i.pos = len(i.entries) + 1
return nil
}
type entriesByOffset []*Entry
func (o entriesByOffset) Len() int {
return len(o)
}
func (o entriesByOffset) Less(i int, j int) bool {
return o[i].Offset < o[j].Offset
}
func (o entriesByOffset) Swap(i int, j int) {
o[i], o[j] = o[j], o[i]
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/idxfile/writer.go
================================================
package idxfile
import (
"bytes"
"fmt"
"math"
"sort"
"sync"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/binary"
)
// objects implements sort.Interface and uses hash as sorting key.
type objects []Entry
// Writer implements a packfile Observer interface and is used to generate
// indexes.
type Writer struct {
m sync.Mutex
count uint32
checksum plumbing.Hash
objects objects
offset64 uint32
finished bool
index *MemoryIndex
added map[plumbing.Hash]struct{}
}
// Index returns a previously created MemoryIndex or creates a new one if
// needed.
func (w *Writer) Index() (*MemoryIndex, error) {
w.m.Lock()
defer w.m.Unlock()
if w.index == nil {
return w.createIndex()
}
return w.index, nil
}
// Add appends new object data.
func (w *Writer) Add(h plumbing.Hash, pos uint64, crc uint32) {
w.m.Lock()
defer w.m.Unlock()
if w.added == nil {
w.added = make(map[plumbing.Hash]struct{})
}
if _, ok := w.added[h]; !ok {
w.added[h] = struct{}{}
w.objects = append(w.objects, Entry{h, crc, pos})
}
}
func (w *Writer) Finished() bool {
return w.finished
}
// OnHeader implements packfile.Observer interface.
func (w *Writer) OnHeader(count uint32) error {
w.count = count
w.objects = make(objects, 0, count)
return nil
}
// OnInflatedObjectHeader implements packfile.Observer interface.
func (w *Writer) OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error {
return nil
}
// OnInflatedObjectContent implements packfile.Observer interface.
func (w *Writer) OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, _ []byte) error {
w.Add(h, uint64(pos), crc)
return nil
}
// OnFooter implements packfile.Observer interface.
func (w *Writer) OnFooter(h plumbing.Hash) error {
w.checksum = h
w.finished = true
_, err := w.createIndex()
return err
}
// creatIndex returns a filled MemoryIndex with the information filled by
// the observer callbacks.
func (w *Writer) createIndex() (*MemoryIndex, error) {
if !w.finished {
return nil, fmt.Errorf("the index still hasn't finished building")
}
idx := new(MemoryIndex)
w.index = idx
sort.Sort(w.objects)
// unmap all fans by default
for i := range idx.FanoutMapping {
idx.FanoutMapping[i] = noMapping
}
buf := new(bytes.Buffer)
last := -1
bucket := -1
for i, o := range w.objects {
fan := o.Hash[0]
// fill the gaps between fans
for j := last + 1; j < int(fan); j++ {
idx.Fanout[j] = uint32(i)
}
// update the number of objects for this position
idx.Fanout[fan] = uint32(i + 1)
// we move from one bucket to another, update counters and allocate
// memory
if last != int(fan) {
bucket++
idx.FanoutMapping[fan] = bucket
last = int(fan)
idx.Names = append(idx.Names, make([]byte, 0))
idx.Offset32 = append(idx.Offset32, make([]byte, 0))
idx.CRC32 = append(idx.CRC32, make([]byte, 0))
}
idx.Names[bucket] = append(idx.Names[bucket], o.Hash[:]...)
offset := o.Offset
if offset > math.MaxInt32 {
var err error
offset, err = w.addOffset64(offset)
if err != nil {
return nil, err
}
}
buf.Truncate(0)
if err := binary.WriteUint32(buf, uint32(offset)); err != nil {
return nil, err
}
idx.Offset32[bucket] = append(idx.Offset32[bucket], buf.Bytes()...)
buf.Truncate(0)
if err := binary.WriteUint32(buf, o.CRC32); err != nil {
return nil, err
}
idx.CRC32[bucket] = append(idx.CRC32[bucket], buf.Bytes()...)
}
for j := last + 1; j < 256; j++ {
idx.Fanout[j] = uint32(len(w.objects))
}
idx.Version = VersionSupported
idx.PackfileChecksum = w.checksum
return idx, nil
}
func (w *Writer) addOffset64(pos uint64) (uint64, error) {
buf := new(bytes.Buffer)
if err := binary.WriteUint64(buf, pos); err != nil {
return 0, err
}
w.index.Offset64 = append(w.index.Offset64, buf.Bytes()...)
index := uint64(w.offset64 | (1 << 31))
w.offset64++
return index, nil
}
func (o objects) Len() int {
return len(o)
}
func (o objects) Less(i int, j int) bool {
cmp := bytes.Compare(o[i].Hash[:], o[j].Hash[:])
return cmp < 0
}
func (o objects) Swap(i int, j int) {
o[i], o[j] = o[j], o[i]
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/index/decoder.go
================================================
package index
import (
"bufio"
"bytes"
"errors"
"io"
"strconv"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/utils/binary"
)
var (
// DecodeVersionSupported is the range of supported index versions
DecodeVersionSupported = struct{ Min, Max uint32 }{Min: 2, Max: 4}
// ErrMalformedSignature is returned by Decode when the index header file is
// malformed
ErrMalformedSignature = errors.New("malformed index signature file")
// ErrInvalidChecksum is returned by Decode if the SHA1 hash mismatch with
// the read content
ErrInvalidChecksum = errors.New("invalid checksum")
// ErrUnknownExtension is returned when an index extension is encountered that is considered mandatory
ErrUnknownExtension = errors.New("unknown extension")
)
const (
entryHeaderLength = 62
entryExtended = 0x4000
entryValid = 0x8000
nameMask = 0xfff
intentToAddMask = 1 << 13
skipWorkTreeMask = 1 << 14
)
// A Decoder reads and decodes index files from an input stream.
type Decoder struct {
buf *bufio.Reader
r io.Reader
hash hash.Hash
lastEntry *Entry
extReader *bufio.Reader
}
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
h := hash.New(hash.CryptoType)
buf := bufio.NewReader(r)
return &Decoder{
buf: buf,
r: io.TeeReader(buf, h),
hash: h,
extReader: bufio.NewReader(nil),
}
}
// Decode reads the whole index object from its input and stores it in the
// value pointed to by idx.
func (d *Decoder) Decode(idx *Index) error {
var err error
idx.Version, err = validateHeader(d.r)
if err != nil {
return err
}
entryCount, err := binary.ReadUint32(d.r)
if err != nil {
return err
}
if err := d.readEntries(idx, int(entryCount)); err != nil {
return err
}
return d.readExtensions(idx)
}
func (d *Decoder) readEntries(idx *Index, count int) error {
for i := 0; i < count; i++ {
e, err := d.readEntry(idx)
if err != nil {
return err
}
d.lastEntry = e
idx.Entries = append(idx.Entries, e)
}
return nil
}
func (d *Decoder) readEntry(idx *Index) (*Entry, error) {
e := &Entry{}
var msec, mnsec, sec, nsec uint32
var flags uint16
flow := []interface{}{
&sec, &nsec,
&msec, &mnsec,
&e.Dev,
&e.Inode,
&e.Mode,
&e.UID,
&e.GID,
&e.Size,
&e.Hash,
&flags,
}
if err := binary.Read(d.r, flow...); err != nil {
return nil, err
}
read := entryHeaderLength
if sec != 0 || nsec != 0 {
e.CreatedAt = time.Unix(int64(sec), int64(nsec))
}
if msec != 0 || mnsec != 0 {
e.ModifiedAt = time.Unix(int64(msec), int64(mnsec))
}
e.Stage = Stage(flags>>12) & 0x3
if flags&entryExtended != 0 {
extended, err := binary.ReadUint16(d.r)
if err != nil {
return nil, err
}
read += 2
e.IntentToAdd = extended&intentToAddMask != 0
e.SkipWorktree = extended&skipWorkTreeMask != 0
}
if err := d.readEntryName(idx, e, flags); err != nil {
return nil, err
}
return e, d.padEntry(idx, e, read)
}
func (d *Decoder) readEntryName(idx *Index, e *Entry, flags uint16) error {
var name string
var err error
switch idx.Version {
case 2, 3:
len := flags & nameMask
name, err = d.doReadEntryName(len)
case 4:
name, err = d.doReadEntryNameV4()
default:
return ErrUnsupportedVersion
}
if err != nil {
return err
}
e.Name = name
return nil
}
func (d *Decoder) doReadEntryNameV4() (string, error) {
l, err := binary.ReadVariableWidthInt(d.r)
if err != nil {
return "", err
}
var base string
if d.lastEntry != nil {
base = d.lastEntry.Name[:len(d.lastEntry.Name)-int(l)]
}
name, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return "", err
}
return base + string(name), nil
}
func (d *Decoder) doReadEntryName(len uint16) (string, error) {
name := make([]byte, len)
_, err := io.ReadFull(d.r, name)
return string(name), err
}
// Index entries are padded out to the next 8 byte alignment
// for historical reasons related to how C Git read the files.
func (d *Decoder) padEntry(idx *Index, e *Entry, read int) error {
if idx.Version == 4 {
return nil
}
entrySize := read + len(e.Name)
padLen := 8 - entrySize%8
_, err := io.CopyN(io.Discard, d.r, int64(padLen))
return err
}
func (d *Decoder) readExtensions(idx *Index) error {
// TODO: support 'Split index' and 'Untracked cache' extensions, take in
// count that they are not supported by jgit or libgit
var expected []byte
var peeked []byte
var err error
// we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash
// if this fails, we know that we're at the end of the index
peekLen := 4 + 4 + d.hash.Size()
for {
expected = d.hash.Sum(nil)
peeked, err = d.buf.Peek(peekLen)
if len(peeked) < peekLen {
// there can't be an extension at this point, so let's bail out
break
}
if err != nil {
return err
}
err = d.readExtension(idx)
if err != nil {
return err
}
}
return d.readChecksum(expected)
}
func (d *Decoder) readExtension(idx *Index) error {
var header [4]byte
if _, err := io.ReadFull(d.r, header[:]); err != nil {
return err
}
r, err := d.getExtensionReader()
if err != nil {
return err
}
switch {
case bytes.Equal(header[:], treeExtSignature):
idx.Cache = &Tree{}
d := &treeExtensionDecoder{r}
if err := d.Decode(idx.Cache); err != nil {
return err
}
case bytes.Equal(header[:], resolveUndoExtSignature):
idx.ResolveUndo = &ResolveUndo{}
d := &resolveUndoDecoder{r}
if err := d.Decode(idx.ResolveUndo); err != nil {
return err
}
case bytes.Equal(header[:], endOfIndexEntryExtSignature):
idx.EndOfIndexEntry = &EndOfIndexEntry{}
d := &endOfIndexEntryDecoder{r}
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
return err
}
default:
// See https://git-scm.com/docs/index-format, which says:
// If the first byte is 'A'..'Z' the extension is optional and can be ignored.
if header[0] < 'A' || header[0] > 'Z' {
return ErrUnknownExtension
}
d := &unknownExtensionDecoder{r}
if err := d.Decode(); err != nil {
return err
}
}
return nil
}
func (d *Decoder) getExtensionReader() (*bufio.Reader, error) {
len, err := binary.ReadUint32(d.r)
if err != nil {
return nil, err
}
d.extReader.Reset(&io.LimitedReader{R: d.r, N: int64(len)})
return d.extReader, nil
}
func (d *Decoder) readChecksum(expected []byte) error {
var h plumbing.Hash
if _, err := io.ReadFull(d.r, h[:]); err != nil {
return err
}
if !bytes.Equal(h[:], expected) {
return ErrInvalidChecksum
}
return nil
}
func validateHeader(r io.Reader) (version uint32, err error) {
var s = make([]byte, 4)
if _, err := io.ReadFull(r, s); err != nil {
return 0, err
}
if !bytes.Equal(s, indexSignature) {
return 0, ErrMalformedSignature
}
version, err = binary.ReadUint32(r)
if err != nil {
return 0, err
}
if version < DecodeVersionSupported.Min || version > DecodeVersionSupported.Max {
return 0, ErrUnsupportedVersion
}
return
}
type treeExtensionDecoder struct {
r *bufio.Reader
}
func (d *treeExtensionDecoder) Decode(t *Tree) error {
for {
e, err := d.readEntry()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if e == nil {
continue
}
t.Entries = append(t.Entries, *e)
}
}
func (d *treeExtensionDecoder) readEntry() (*TreeEntry, error) {
e := &TreeEntry{}
path, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return nil, err
}
e.Path = string(path)
count, err := binary.ReadUntil(d.r, ' ')
if err != nil {
return nil, err
}
i, err := strconv.Atoi(string(count))
if err != nil {
return nil, err
}
// An entry can be in an invalidated state and is represented by having a
// negative number in the entry_count field.
if i == -1 {
return nil, nil
}
e.Entries = i
trees, err := binary.ReadUntil(d.r, '\n')
if err != nil {
return nil, err
}
i, err = strconv.Atoi(string(trees))
if err != nil {
return nil, err
}
e.Trees = i
_, err = io.ReadFull(d.r, e.Hash[:])
if err != nil {
return nil, err
}
return e, nil
}
type resolveUndoDecoder struct {
r *bufio.Reader
}
func (d *resolveUndoDecoder) Decode(ru *ResolveUndo) error {
for {
e, err := d.readEntry()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
ru.Entries = append(ru.Entries, *e)
}
}
func (d *resolveUndoDecoder) readEntry() (*ResolveUndoEntry, error) {
e := &ResolveUndoEntry{
Stages: make(map[Stage]plumbing.Hash),
}
path, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return nil, err
}
e.Path = string(path)
for i := 0; i < 3; i++ {
if err := d.readStage(e, Stage(i+1)); err != nil {
return nil, err
}
}
for s := range e.Stages {
var hash plumbing.Hash
if _, err := io.ReadFull(d.r, hash[:]); err != nil {
return nil, err
}
e.Stages[s] = hash
}
return e, nil
}
func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error {
ascii, err := binary.ReadUntil(d.r, '\x00')
if err != nil {
return err
}
stage, err := strconv.ParseInt(string(ascii), 8, 64)
if err != nil {
return err
}
if stage != 0 {
e.Stages[s] = plumbing.ZeroHash
}
return nil
}
type endOfIndexEntryDecoder struct {
r *bufio.Reader
}
func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
var err error
e.Offset, err = binary.ReadUint32(d.r)
if err != nil {
return err
}
_, err = io.ReadFull(d.r, e.Hash[:])
return err
}
type unknownExtensionDecoder struct {
r *bufio.Reader
}
func (d *unknownExtensionDecoder) Decode() error {
var buf [1024]byte
for {
_, err := d.r.Read(buf[:])
if err == io.EOF {
break
}
if err != nil {
return err
}
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/index/doc.go
================================================
// Package index implements encoding and decoding of index format files.
//
// Git index format
// ================
//
// == The Git index file has the following format
//
// All binary numbers are in network byte order. Version 2 is described
// here unless stated otherwise.
//
// - A 12-byte header consisting of
//
// 4-byte signature:
// The signature is { 'D', 'I', 'R', 'C' } (stands for "dircache")
//
// 4-byte version number:
// The current supported versions are 2, 3 and 4.
//
// 32-bit number of index entries.
//
// - A number of sorted index entries (see below).
//
// - Extensions
//
// Extensions are identified by signature. Optional extensions can
// be ignored if Git does not understand them.
//
// Git currently supports cached tree and resolve undo extensions.
//
// 4-byte extension signature. If the first byte is 'A'..'Z' the
// extension is optional and can be ignored.
//
// 32-bit size of the extension
//
// Extension data
//
// - 160-bit SHA-1 over the content of the index file before this
// checksum.
//
// == Index entry
//
// Index entries are sorted in ascending order on the name field,
// interpreted as a string of unsigned bytes (i.e. memcmp() order, no
// localization, no special casing of directory separator '/'). Entries
// with the same name are sorted by their stage field.
//
// 32-bit ctime seconds, the last time a file's metadata changed
// this is stat(2) data
//
// 32-bit ctime nanosecond fractions
// this is stat(2) data
//
// 32-bit mtime seconds, the last time a file's data changed
// this is stat(2) data
//
// 32-bit mtime nanosecond fractions
// this is stat(2) data
//
// 32-bit dev
// this is stat(2) data
//
// 32-bit ino
// this is stat(2) data
//
// 32-bit mode, split into (high to low bits)
//
// 4-bit object type
// valid values in binary are 1000 (regular file), 1010 (symbolic link)
// and 1110 (gitlink)
//
// 3-bit unused
//
// 9-bit unix permission. Only 0755 and 0644 are valid for regular files.
// Symbolic links and gitlinks have value 0 in this field.
//
// 32-bit uid
// this is stat(2) data
//
// 32-bit gid
// this is stat(2) data
//
// 32-bit file size
// This is the on-disk size from stat(2), truncated to 32-bit.
//
// 160-bit SHA-1 for the represented object
//
// A 16-bit 'flags' field split into (high to low bits)
//
// 1-bit assume-valid flag
//
// 1-bit extended flag (must be zero in version 2)
//
// 2-bit stage (during merge)
//
// 12-bit name length if the length is less than 0xFFF; otherwise 0xFFF
// is stored in this field.
//
// (Version 3 or later) A 16-bit field, only applicable if the
// "extended flag" above is 1, split into (high to low bits).
//
// 1-bit reserved for future
//
// 1-bit skip-worktree flag (used by sparse checkout)
//
// 1-bit intent-to-add flag (used by "git add -N")
//
// 13-bit unused, must be zero
//
// Entry path name (variable length) relative to top level directory
// (without leading slash). '/' is used as path separator. The special
// path components ".", ".." and ".git" (without quotes) are disallowed.
// Trailing slash is also disallowed.
//
// The exact encoding is undefined, but the '.' and '/' characters
// are encoded in 7-bit ASCII and the encoding cannot contain a NUL
// byte (iow, this is a UNIX pathname).
//
// (Version 4) In version 4, the entry path name is prefix-compressed
// relative to the path name for the previous entry (the very first
// entry is encoded as if the path name for the previous entry is an
// empty string). At the beginning of an entry, an integer N in the
// variable width encoding (the same encoding as the offset is encoded
// for OFS_DELTA pack entries; see pack-format.txt) is stored, followed
// by a NUL-terminated string S. Removing N bytes from the end of the
// path name for the previous entry, and replacing it with the string S
// yields the path name for this entry.
//
// 1-8 nul bytes as necessary to pad the entry to a multiple of eight bytes
// while keeping the name NUL-terminated.
//
// (Version 4) In version 4, the padding after the pathname does not
// exist.
//
// Interpretation of index entries in split index mode is completely
// different. See below for details.
//
// == Extensions
//
// === Cached tree
//
// Cached tree extension contains pre-computed hashes for trees that can
// be derived from the index. It helps speed up tree object generation
// from index for a new commit.
//
// When a path is updated in index, the path must be invalidated and
// removed from tree cache.
//
// The signature for this extension is { 'T', 'R', 'E', 'E' }.
//
// A series of entries fill the entire extension; each of which
// consists of:
//
// - NUL-terminated path component (relative to its parent directory);
//
// - ASCII decimal number of entries in the index that is covered by the
// tree this entry represents (entry_count);
//
// - A space (ASCII 32);
//
// - ASCII decimal number that represents the number of subtrees this
// tree has;
//
// - A newline (ASCII 10); and
//
// - 160-bit object name for the object that would result from writing
// this span of index as a tree.
//
// An entry can be in an invalidated state and is represented by having
// a negative number in the entry_count field. In this case, there is no
// object name and the next entry starts immediately after the newline.
// When writing an invalid entry, -1 should always be used as entry_count.
//
// The entries are written out in the top-down, depth-first order. The
// first entry represents the root level of the repository, followed by the
// first subtree--let's call this A--of the root level (with its name
// relative to the root level), followed by the first subtree of A (with
// its name relative to A), ...
//
// === Resolve undo
//
// A conflict is represented in the index as a set of higher stage entries.
// When a conflict is resolved (e.g. with "git add path"), these higher
// stage entries will be removed and a stage-0 entry with proper resolution
// is added.
//
// When these higher stage entries are removed, they are saved in the
// resolve undo extension, so that conflicts can be recreated (e.g. with
// "git checkout -m"), in case users want to redo a conflict resolution
// from scratch.
//
// The signature for this extension is { 'R', 'E', 'U', 'C' }.
//
// A series of entries fill the entire extension; each of which
// consists of:
//
// - NUL-terminated pathname the entry describes (relative to the root of
// the repository, i.e. full pathname);
//
// - Three NUL-terminated ASCII octal numbers, entry mode of entries in
// stage 1 to 3 (a missing stage is represented by "0" in this field);
// and
//
// - At most three 160-bit object names of the entry in stages from 1 to 3
// (nothing is written for a missing stage).
//
// === Split index
//
// In split index mode, the majority of index entries could be stored
// in a separate file. This extension records the changes to be made on
// top of that to produce the final index.
//
// The signature for this extension is { 'l', 'i', 'n', 'k' }.
//
// The extension consists of:
//
// - 160-bit SHA-1 of the shared index file. The shared index file path
// is $GIT_DIR/sharedindex.. If all 160 bits are zero, the
// index does not require a shared index file.
//
// - An ewah-encoded delete bitmap, each bit represents an entry in the
// shared index. If a bit is set, its corresponding entry in the
// shared index will be removed from the final index. Note, because
// a delete operation changes index entry positions, but we do need
// original positions in replace phase, it's best to just mark
// entries for removal, then do a mass deletion after replacement.
//
// - An ewah-encoded replace bitmap, each bit represents an entry in
// the shared index. If a bit is set, its corresponding entry in the
// shared index will be replaced with an entry in this index
// file. All replaced entries are stored in sorted order in this
// index. The first "1" bit in the replace bitmap corresponds to the
// first index entry, the second "1" bit to the second entry and so
// on. Replaced entries may have empty path names to save space.
//
// The remaining index entries after replaced ones will be added to the
// final index. These added entries are also sorted by entry name then
// stage.
//
// == Untracked cache
//
// Untracked cache saves the untracked file list and necessary data to
// verify the cache. The signature for this extension is { 'U', 'N',
// 'T', 'R' }.
//
// The extension starts with
//
// - A sequence of NUL-terminated strings, preceded by the size of the
// sequence in variable width encoding. Each string describes the
// environment where the cache can be used.
//
// - Stat data of $GIT_DIR/info/exclude. See "Index entry" section from
// ctime field until "file size".
//
// - Stat data of plumbing.excludesfile
//
// - 32-bit dir_flags (see struct dir_struct)
//
// - 160-bit SHA-1 of $GIT_DIR/info/exclude. Null SHA-1 means the file
// does not exist.
//
// - 160-bit SHA-1 of plumbing.excludesfile. Null SHA-1 means the file does
// not exist.
//
// - NUL-terminated string of per-dir exclude file name. This usually
// is ".gitignore".
//
// - The number of following directory blocks, variable width
// encoding. If this number is zero, the extension ends here with a
// following NUL.
//
// - A number of directory blocks in depth-first-search order, each
// consists of
//
// - The number of untracked entries, variable width encoding.
//
// - The number of sub-directory blocks, variable width encoding.
//
// - The directory name terminated by NUL.
//
// - A number of untracked file/dir names terminated by NUL.
//
// The remaining data of each directory block is grouped by type:
//
// - An ewah bitmap, the n-th bit marks whether the n-th directory has
// valid untracked cache entries.
//
// - An ewah bitmap, the n-th bit records "check-only" bit of
// read_directory_recursive() for the n-th directory.
//
// - An ewah bitmap, the n-th bit indicates whether SHA-1 and stat data
// is valid for the n-th directory and exists in the next data.
//
// - An array of stat data. The n-th data corresponds with the n-th
// "one" bit in the previous ewah bitmap.
//
// - An array of SHA-1. The n-th SHA-1 corresponds with the n-th "one" bit
// in the previous ewah bitmap.
//
// - One NUL.
//
// == File System Monitor cache
//
// The file system monitor cache tracks files for which the core.fsmonitor
// hook has told us about changes. The signature for this extension is
// { 'F', 'S', 'M', 'N' }.
//
// The extension starts with
//
// - 32-bit version number: the current supported version is 1.
//
// - 64-bit time: the extension data reflects all changes through the given
// time which is stored as the nanoseconds elapsed since midnight,
// January 1, 1970.
//
// - 32-bit bitmap size: the size of the CE_FSMONITOR_VALID bitmap.
//
// - An ewah bitmap, the n-th bit indicates whether the n-th index entry
// is not CE_FSMONITOR_VALID.
//
// == End of Index Entry
//
// The End of Index Entry (EOIE) is used to locate the end of the variable
// length index entries and the beginning of the extensions. Code can take
// advantage of this to quickly locate the index extensions without having
// to parse through all of the index entries.
//
// Because it must be able to be loaded before the variable length cache
// entries and other index extensions, this extension must be written last.
// The signature for this extension is { 'E', 'O', 'I', 'E' }.
//
// The extension consists of:
//
// - 32-bit offset to the end of the index entries
//
// - 160-bit SHA-1 over the extension types and their sizes (but not
// their contents). E.g. if we have "TREE" extension that is N-bytes
// long, "REUC" extension that is M-bytes long, followed by "EOIE",
// then the hash would be:
//
// SHA-1("TREE" + +
// "REUC" + )
//
// == Index Entry Offset Table
//
// The Index Entry Offset Table (IEOT) is used to help address the CPU
// cost of loading the index by enabling multi-threading the process of
// converting cache entries from the on-disk format to the in-memory format.
// The signature for this extension is { 'I', 'E', 'O', 'T' }.
//
// The extension consists of:
//
// - 32-bit version (currently 1)
//
// - A number of index offset entries each consisting of:
//
// - 32-bit offset from the beginning of the file to the first cache entry
// in this block of entries.
//
// - 32-bit count of cache entries in this blockpackage index
package index
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/index/encoder.go
================================================
package index
import (
"bytes"
"errors"
"fmt"
"io"
"path"
"sort"
"strings"
"time"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/utils/binary"
)
var (
// EncodeVersionSupported is the range of supported index versions
EncodeVersionSupported uint32 = 4
// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
// negative timestamp values
ErrInvalidTimestamp = errors.New("negative timestamps are not allowed")
)
// An Encoder writes an Index to an output stream.
type Encoder struct {
w io.Writer
hash hash.Hash
lastEntry *Entry
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
h := hash.New(hash.CryptoType)
mw := io.MultiWriter(w, h)
return &Encoder{mw, h, nil}
}
// Encode writes the Index to the stream of the encoder.
func (e *Encoder) Encode(idx *Index) error {
return e.encode(idx, true)
}
func (e *Encoder) encode(idx *Index, footer bool) error {
// TODO: support extensions
if idx.Version > EncodeVersionSupported {
return ErrUnsupportedVersion
}
if err := e.encodeHeader(idx); err != nil {
return err
}
if err := e.encodeEntries(idx); err != nil {
return err
}
if footer {
return e.encodeFooter()
}
return nil
}
func (e *Encoder) encodeHeader(idx *Index) error {
return binary.Write(e.w,
indexSignature,
idx.Version,
uint32(len(idx.Entries)),
)
}
func (e *Encoder) encodeEntries(idx *Index) error {
sort.Sort(byName(idx.Entries))
for _, entry := range idx.Entries {
if err := e.encodeEntry(idx, entry); err != nil {
return err
}
entryLength := entryHeaderLength
if entry.IntentToAdd || entry.SkipWorktree {
entryLength += 2
}
wrote := entryLength + len(entry.Name)
if err := e.padEntry(idx, wrote); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeEntry(idx *Index, entry *Entry) error {
sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
if err != nil {
return err
}
msec, mnsec, err := e.timeToUint32(&entry.ModifiedAt)
if err != nil {
return err
}
flags := uint16(entry.Stage&0x3) << 12
if l := len(entry.Name); l < nameMask {
flags |= uint16(l)
} else {
flags |= nameMask
}
flow := []interface{}{
sec, nsec,
msec, mnsec,
entry.Dev,
entry.Inode,
entry.Mode,
entry.UID,
entry.GID,
entry.Size,
entry.Hash[:],
}
flagsFlow := []interface{}{flags}
if entry.IntentToAdd || entry.SkipWorktree {
var extendedFlags uint16
if entry.IntentToAdd {
extendedFlags |= intentToAddMask
}
if entry.SkipWorktree {
extendedFlags |= skipWorkTreeMask
}
flagsFlow = []interface{}{flags | entryExtended, extendedFlags}
}
flow = append(flow, flagsFlow...)
if err := binary.Write(e.w, flow...); err != nil {
return err
}
switch idx.Version {
case 2, 3:
err = e.encodeEntryName(entry)
case 4:
err = e.encodeEntryNameV4(entry)
default:
err = ErrUnsupportedVersion
}
return err
}
func (e *Encoder) encodeEntryName(entry *Entry) error {
return binary.Write(e.w, []byte(entry.Name))
}
func (e *Encoder) encodeEntryNameV4(entry *Entry) error {
name := entry.Name
l := 0
if e.lastEntry != nil {
dir := path.Dir(e.lastEntry.Name) + "/"
if strings.HasPrefix(entry.Name, dir) {
l = len(e.lastEntry.Name) - len(dir)
name = strings.TrimPrefix(entry.Name, dir)
} else {
l = len(e.lastEntry.Name)
}
}
e.lastEntry = entry
err := binary.WriteVariableWidthInt(e.w, int64(l))
if err != nil {
return err
}
return binary.Write(e.w, []byte(name+string('\x00')))
}
func (e *Encoder) encodeRawExtension(signature string, data []byte) error {
if len(signature) != 4 {
return fmt.Errorf("invalid signature length")
}
_, err := e.w.Write([]byte(signature))
if err != nil {
return err
}
err = binary.WriteUint32(e.w, uint32(len(data)))
if err != nil {
return err
}
_, err = e.w.Write(data)
if err != nil {
return err
}
return nil
}
func (e *Encoder) timeToUint32(t *time.Time) (uint32, uint32, error) {
if t.IsZero() {
return 0, 0, nil
}
if t.Unix() < 0 || t.UnixNano() < 0 {
return 0, 0, ErrInvalidTimestamp
}
return uint32(t.Unix()), uint32(t.Nanosecond()), nil
}
func (e *Encoder) padEntry(idx *Index, wrote int) error {
if idx.Version == 4 {
return nil
}
padLen := 8 - wrote%8
_, err := e.w.Write(bytes.Repeat([]byte{'\x00'}, padLen))
return err
}
func (e *Encoder) encodeFooter() error {
return binary.Write(e.w, e.hash.Sum(nil))
}
type byName []*Entry
func (l byName) Len() int { return len(l) }
func (l byName) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l byName) Less(i, j int) bool { return l[i].Name < l[j].Name }
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/index/index.go
================================================
package index
import (
"bytes"
"errors"
"fmt"
"path/filepath"
"strings"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
)
var (
// ErrUnsupportedVersion is returned by Decode when the index file version
// is not supported.
ErrUnsupportedVersion = errors.New("unsupported version")
// ErrEntryNotFound is returned by Index.Entry, if an entry is not found.
ErrEntryNotFound = errors.New("entry not found")
indexSignature = []byte{'D', 'I', 'R', 'C'}
treeExtSignature = []byte{'T', 'R', 'E', 'E'}
resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'}
endOfIndexEntryExtSignature = []byte{'E', 'O', 'I', 'E'}
)
// Stage during merge
type Stage int
const (
// Merged is the default stage, fully merged
Merged Stage = 1
// AncestorMode is the base revision
AncestorMode Stage = 1
// OurMode is the first tree revision, ours
OurMode Stage = 2
// TheirMode is the second tree revision, theirs
TheirMode Stage = 3
)
// Index contains the information about which objects are currently checked out
// in the worktree, having information about the working files. Changes in
// worktree are detected using this Index. The Index is also used during merges
type Index struct {
// Version is index version
Version uint32
// Entries collection of entries represented by this Index. The order of
// this collection is not guaranteed
Entries []*Entry
// Cache represents the 'Cached tree' extension
Cache *Tree
// ResolveUndo represents the 'Resolve undo' extension
ResolveUndo *ResolveUndo
// EndOfIndexEntry represents the 'End of Index Entry' extension
EndOfIndexEntry *EndOfIndexEntry
}
// Add creates a new Entry and returns it. The caller should first check that
// another entry with the same path does not exist.
func (i *Index) Add(path string) *Entry {
e := &Entry{
Name: filepath.ToSlash(path),
}
i.Entries = append(i.Entries, e)
return e
}
// Entry returns the entry that match the given path, if any.
func (i *Index) Entry(path string) (*Entry, error) {
path = filepath.ToSlash(path)
for _, e := range i.Entries {
if e.Name == path {
return e, nil
}
}
return nil, ErrEntryNotFound
}
// Remove remove the entry that match the give path and returns deleted entry.
func (i *Index) Remove(path string) (*Entry, error) {
path = filepath.ToSlash(path)
for index, e := range i.Entries {
if e.Name == path {
i.Entries = append(i.Entries[:index], i.Entries[index+1:]...)
return e, nil
}
}
return nil, ErrEntryNotFound
}
// Glob returns the all entries matching pattern or nil if there is no matching
// entry. The syntax of patterns is the same as in filepath.Glob.
func (i *Index) Glob(pattern string) (matches []*Entry, err error) {
pattern = filepath.ToSlash(pattern)
for _, e := range i.Entries {
m, err := match(pattern, e.Name)
if err != nil {
return nil, err
}
if m {
matches = append(matches, e)
}
}
return
}
// String is equivalent to `git ls-files --stage --debug`
func (i *Index) String() string {
buf := bytes.NewBuffer(nil)
for _, e := range i.Entries {
buf.WriteString(e.String())
}
return buf.String()
}
// Entry represents a single file (or stage of a file) in the cache. An entry
// represents exactly one stage of a file. If a file path is unmerged then
// multiple Entry instances may appear for the same path name.
type Entry struct {
// Hash is the SHA1 of the represented file
Hash plumbing.Hash
// Name is the Entry path name relative to top level directory
Name string
// CreatedAt time when the tracked path was created
CreatedAt time.Time
// ModifiedAt time when the tracked path was changed
ModifiedAt time.Time
// Dev and Inode of the tracked path
Dev, Inode uint32
// Mode of the path
Mode filemode.FileMode
// UID and GID, userid and group id of the owner
UID, GID uint32
// Size is the length in bytes for regular files
Size uint32
// Stage on a merge is defines what stage is representing this entry
// https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging
Stage Stage
// SkipWorktree used in sparse checkouts
// https://git-scm.com/docs/git-read-tree#_sparse_checkout
SkipWorktree bool
// IntentToAdd record only the fact that the path will be added later
// https://git-scm.com/docs/git-add ("git add -N")
IntentToAdd bool
}
func (e Entry) String() string {
buf := bytes.NewBuffer(nil)
fmt.Fprintf(buf, "%06o %s %d\t%s\n", e.Mode, e.Hash, e.Stage, e.Name)
fmt.Fprintf(buf, " ctime: %d:%d\n", e.CreatedAt.Unix(), e.CreatedAt.Nanosecond())
fmt.Fprintf(buf, " mtime: %d:%d\n", e.ModifiedAt.Unix(), e.ModifiedAt.Nanosecond())
fmt.Fprintf(buf, " dev: %d\tino: %d\n", e.Dev, e.Inode)
fmt.Fprintf(buf, " uid: %d\tgid: %d\n", e.UID, e.GID)
fmt.Fprintf(buf, " size: %d\tflags: %x\n", e.Size, 0)
return buf.String()
}
// Tree contains pre-computed hashes for trees that can be derived from the
// index. It helps speed up tree object generation from index for a new commit.
type Tree struct {
Entries []TreeEntry
}
// TreeEntry entry of a cached Tree
type TreeEntry struct {
// Path component (relative to its parent directory)
Path string
// Entries is the number of entries in the index that is covered by the tree
// this entry represents.
Entries int
// Trees is the number that represents the number of subtrees this tree has
Trees int
// Hash object name for the object that would result from writing this span
// of index as a tree.
Hash plumbing.Hash
}
// ResolveUndo is used when a conflict is resolved (e.g. with "git add path"),
// these higher stage entries are removed and a stage-0 entry with proper
// resolution is added. When these higher stage entries are removed, they are
// saved in the resolve undo extension.
type ResolveUndo struct {
Entries []ResolveUndoEntry
}
// ResolveUndoEntry contains the information about a conflict when is resolved
type ResolveUndoEntry struct {
Path string
Stages map[Stage]plumbing.Hash
}
// EndOfIndexEntry is the End of Index Entry (EOIE) is used to locate the end of
// the variable length index entries and the beginning of the extensions. Code
// can take advantage of this to quickly locate the index extensions without
// having to parse through all of the index entries.
//
// Because it must be able to be loaded before the variable length cache
// entries and other index extensions, this extension must be written last.
type EndOfIndexEntry struct {
// Offset to the end of the index entries
Offset uint32
// Hash is a SHA-1 over the extension types and their sizes (but not
// their contents).
Hash plumbing.Hash
}
// SkipUnless applies patterns in the form of A, A/B, A/B/C
// to the index to prevent the files from being checked out
func (i *Index) SkipUnless(patterns []string) {
for _, e := range i.Entries {
var include bool
for _, pattern := range patterns {
if strings.HasPrefix(e.Name, pattern) {
include = true
break
}
}
if !include {
e.SkipWorktree = true
}
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/index/match.go
================================================
package index
import (
"path/filepath"
"runtime"
"unicode/utf8"
)
// match is filepath.Match with support to match fullpath and not only filenames
// code from:
// https://github.com/golang/go/blob/39852bf4cce6927e01d0136c7843f65a801738cb/src/path/filepath/match.go#L44-L224
func match(pattern, name string) (matched bool, err error) {
Pattern:
for len(pattern) > 0 {
var star bool
var chunk string
star, chunk, pattern = scanChunk(pattern)
// Look for match at current position.
t, ok, err := matchChunk(chunk, name)
// if we're the last chunk, make sure we've exhausted the name
// otherwise we'll give a false result even if we could still match
// using the star
if ok && (len(t) == 0 || len(pattern) > 0) {
name = t
continue
}
if err != nil {
return false, err
}
if star {
// Look for match skipping i+1 bytes.
// Cannot skip /.
for i := 0; i < len(name); i++ {
t, ok, err := matchChunk(chunk, name[i+1:])
if ok {
// if we're the last chunk, make sure we exhausted the name
if len(pattern) == 0 && len(t) > 0 {
continue
}
name = t
continue Pattern
}
if err != nil {
return false, err
}
}
}
return false, nil
}
return len(name) == 0, nil
}
// scanChunk gets the next segment of pattern, which is a non-star string
// possibly preceded by a star.
func scanChunk(pattern string) (star bool, chunk, rest string) {
for len(pattern) > 0 && pattern[0] == '*' {
pattern = pattern[1:]
star = true
}
inrange := false
var i int
Scan:
for i = 0; i < len(pattern); i++ {
switch pattern[i] {
case '\\':
if runtime.GOOS != "windows" {
// error check handled in matchChunk: bad pattern.
if i+1 < len(pattern) {
i++
}
}
case '[':
inrange = true
case ']':
inrange = false
case '*':
if !inrange {
break Scan
}
}
}
return star, pattern[0:i], pattern[i:]
}
// matchChunk checks whether chunk matches the beginning of s.
// If so, it returns the remainder of s (after the match).
// Chunk is all single-character operators: literals, char classes, and ?.
func matchChunk(chunk, s string) (rest string, ok bool, err error) {
for len(chunk) > 0 {
if len(s) == 0 {
return
}
switch chunk[0] {
case '[':
// character class
r, n := utf8.DecodeRuneInString(s)
s = s[n:]
chunk = chunk[1:]
// We can't end right after '[', we're expecting at least
// a closing bracket and possibly a caret.
if len(chunk) == 0 {
err = filepath.ErrBadPattern
return
}
// possibly negated
negated := chunk[0] == '^'
if negated {
chunk = chunk[1:]
}
// parse all ranges
match := false
nrange := 0
for {
if len(chunk) > 0 && chunk[0] == ']' && nrange > 0 {
chunk = chunk[1:]
break
}
var lo, hi rune
if lo, chunk, err = getEsc(chunk); err != nil {
return
}
hi = lo
if chunk[0] == '-' {
if hi, chunk, err = getEsc(chunk[1:]); err != nil {
return
}
}
if lo <= r && r <= hi {
match = true
}
nrange++
}
if match == negated {
return
}
case '?':
_, n := utf8.DecodeRuneInString(s)
s = s[n:]
chunk = chunk[1:]
case '\\':
if runtime.GOOS != "windows" {
chunk = chunk[1:]
if len(chunk) == 0 {
err = filepath.ErrBadPattern
return
}
}
fallthrough
default:
if chunk[0] != s[0] {
return
}
s = s[1:]
chunk = chunk[1:]
}
}
return s, true, nil
}
// getEsc gets a possibly-escaped character from chunk, for a character class.
func getEsc(chunk string) (r rune, nchunk string, err error) {
if len(chunk) == 0 || chunk[0] == '-' || chunk[0] == ']' {
err = filepath.ErrBadPattern
return
}
if chunk[0] == '\\' && runtime.GOOS != "windows" {
chunk = chunk[1:]
if len(chunk) == 0 {
err = filepath.ErrBadPattern
return
}
}
r, n := utf8.DecodeRuneInString(chunk)
if r == utf8.RuneError && n == 1 {
err = filepath.ErrBadPattern
}
nchunk = chunk[n:]
if len(nchunk) == 0 {
err = filepath.ErrBadPattern
}
return
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/doc.go
================================================
// Package objfile implements encoding and decoding of object files.
package objfile
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/reader.go
================================================
package objfile
import (
"errors"
"io"
"strconv"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
ErrClosed = errors.New("objfile: already closed")
ErrHeader = errors.New("objfile: invalid header")
ErrNegativeSize = errors.New("objfile: negative object size")
)
// Reader reads and decodes compressed objfile data from a provided io.Reader.
// Reader implements io.ReadCloser. Close should be called when finished with
// the Reader. Close will not close the underlying io.Reader.
type Reader struct {
multi io.Reader
zlib io.Reader
zlibref sync.ZLibReader
hasher plumbing.Hasher
}
// NewReader returns a new Reader reading from r.
func NewReader(r io.Reader) (*Reader, error) {
zlib, err := sync.GetZlibReader(r)
if err != nil {
return nil, packfile.ErrZLib.AddDetails(err.Error())
}
return &Reader{
zlib: zlib.Reader,
zlibref: zlib,
}, nil
}
// Header reads the type and the size of object, and prepares the reader for read
func (r *Reader) Header() (t plumbing.ObjectType, size int64, err error) {
var raw []byte
raw, err = r.readUntil(' ')
if err != nil {
return
}
t, err = plumbing.ParseObjectType(string(raw))
if err != nil {
return
}
raw, err = r.readUntil(0)
if err != nil {
return
}
size, err = strconv.ParseInt(string(raw), 10, 64)
if err != nil {
err = ErrHeader
return
}
defer r.prepareForRead(t, size)
return
}
// readSlice reads one byte at a time from r until it encounters delim or an
// error.
func (r *Reader) readUntil(delim byte) ([]byte, error) {
var buf [1]byte
value := make([]byte, 0, 16)
for {
if n, err := r.zlib.Read(buf[:]); err != nil && (err != io.EOF || n == 0) {
if err == io.EOF {
return nil, ErrHeader
}
return nil, err
}
if buf[0] == delim {
return value, nil
}
value = append(value, buf[0])
}
}
func (r *Reader) prepareForRead(t plumbing.ObjectType, size int64) {
r.hasher = plumbing.NewHasher(t, size)
r.multi = io.TeeReader(r.zlib, r.hasher)
}
// Read reads len(p) bytes into p from the object data stream. It returns
// the number of bytes read (0 <= n <= len(p)) and any error encountered. Even
// if Read returns n < len(p), it may use all of p as scratch space during the
// call.
//
// If Read encounters the end of the data stream it will return err == io.EOF,
// either in the current call if n > 0 or in a subsequent call.
func (r *Reader) Read(p []byte) (n int, err error) {
return r.multi.Read(p)
}
// Hash returns the hash of the object data stream that has been read so far.
func (r *Reader) Hash() plumbing.Hash {
return r.hasher.Sum()
}
// Close releases any resources consumed by the Reader. Calling Close does not
// close the wrapped io.Reader originally passed to NewReader.
func (r *Reader) Close() error {
sync.PutZlibReader(r.zlibref)
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/objfile/writer.go
================================================
package objfile
import (
"compress/zlib"
"errors"
"io"
"strconv"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
ErrOverflow = errors.New("objfile: declared data length exceeded (overflow)")
)
// Writer writes and encodes data in compressed objfile format to a provided
// io.Writer. Close should be called when finished with the Writer. Close will
// not close the underlying io.Writer.
type Writer struct {
raw io.Writer
hasher plumbing.Hasher
multi io.Writer
zlib *zlib.Writer
closed bool
pending int64 // number of unwritten bytes
}
// NewWriter returns a new Writer writing to w.
//
// The returned Writer implements io.WriteCloser. Close should be called when
// finished with the Writer. Close will not close the underlying io.Writer.
func NewWriter(w io.Writer) *Writer {
zlib := sync.GetZlibWriter(w)
return &Writer{
raw: w,
zlib: zlib,
}
}
// WriteHeader writes the type and the size and prepares to accept the object's
// contents. If an invalid t is provided, plumbing.ErrInvalidType is returned. If a
// negative size is provided, ErrNegativeSize is returned.
func (w *Writer) WriteHeader(t plumbing.ObjectType, size int64) error {
if !t.Valid() {
return plumbing.ErrInvalidType
}
if size < 0 {
return ErrNegativeSize
}
b := t.Bytes()
b = append(b, ' ')
b = append(b, []byte(strconv.FormatInt(size, 10))...)
b = append(b, 0)
defer w.prepareForWrite(t, size)
_, err := w.zlib.Write(b)
return err
}
func (w *Writer) prepareForWrite(t plumbing.ObjectType, size int64) {
w.pending = size
w.hasher = plumbing.NewHasher(t, size)
w.multi = io.MultiWriter(w.zlib, w.hasher)
}
// Write writes the object's contents. Write returns the error ErrOverflow if
// more than size bytes are written after WriteHeader.
func (w *Writer) Write(p []byte) (n int, err error) {
if w.closed {
return 0, ErrClosed
}
overwrite := false
if int64(len(p)) > w.pending {
p = p[0:w.pending]
overwrite = true
}
n, err = w.multi.Write(p)
w.pending -= int64(n)
if err == nil && overwrite {
err = ErrOverflow
return
}
return
}
// Hash returns the hash of the object data stream that has been written so far.
// It can be called before or after Close.
func (w *Writer) Hash() plumbing.Hash {
return w.hasher.Sum() // Not yet closed, return hash of data written so far
}
// Close releases any resources consumed by the Writer.
//
// Calling Close does not close the wrapped io.Writer originally passed to
// NewWriter.
func (w *Writer) Close() error {
defer sync.PutZlibWriter(w.zlib)
if err := w.zlib.Close(); err != nil {
return err
}
w.closed = true
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/common.go
================================================
package packfile
import (
"io"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
)
var signature = []byte{'P', 'A', 'C', 'K'}
const (
// VersionSupported is the packfile version supported by this package
VersionSupported uint32 = 2
firstLengthBits = uint8(4) // the first byte into object header has 4 bits to store the length
lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
maskFirstLength = 15 // 0000 1111
maskContinue = 0x80 // 1000 0000
maskLength = uint8(127) // 0111 1111
maskType = uint8(112) // 0111 0000
)
// UpdateObjectStorage updates the storer with the objects in the given
// packfile.
func UpdateObjectStorage(s storer.Storer, packfile io.Reader) error {
if pw, ok := s.(storer.PackfileWriter); ok {
return WritePackfileToObjectStorage(pw, packfile)
}
p, err := NewParserWithStorage(NewScanner(packfile), s)
if err != nil {
return err
}
_, err = p.Parse()
return err
}
// WritePackfileToObjectStorage writes all the packfile objects into the given
// object storage.
func WritePackfileToObjectStorage(
sw storer.PackfileWriter,
packfile io.Reader,
) (err error) {
w, err := sw.PackfileWriter()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
var n int64
n, err = io.Copy(w, packfile)
if err == nil && n == 0 {
return ErrEmptyPackfile
}
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_index.go
================================================
package packfile
const blksz = 16
const maxChainLength = 64
// deltaIndex is a modified version of JGit's DeltaIndex adapted to our current
// design.
type deltaIndex struct {
table []int
entries []int
mask int
}
func (idx *deltaIndex) init(buf []byte) {
scanner := newDeltaIndexScanner(buf, len(buf))
idx.mask = scanner.mask
idx.table = scanner.table
idx.entries = make([]int, countEntries(scanner)+1)
idx.copyEntries(scanner)
}
// findMatch returns the offset of src where the block starting at tgtOffset
// is and the length of the match. A length of 0 means there was no match. A
// length of -1 means the src length is lower than the blksz and whatever
// other positive length is the length of the match in bytes.
func (idx *deltaIndex) findMatch(src, tgt []byte, tgtOffset int) (srcOffset, l int) {
if len(tgt) < tgtOffset+s {
return 0, len(tgt) - tgtOffset
}
if len(src) < blksz {
return 0, -1
}
h := hashBlock(tgt, tgtOffset)
tIdx := h & idx.mask
eIdx := idx.table[tIdx]
if eIdx == 0 {
return
}
srcOffset = idx.entries[eIdx]
l = matchLength(src, tgt, tgtOffset, srcOffset)
return
}
func matchLength(src, tgt []byte, otgt, osrc int) (l int) {
lensrc := len(src)
lentgt := len(tgt)
for (osrc < lensrc && otgt < lentgt) && src[osrc] == tgt[otgt] {
l++
osrc++
otgt++
}
return
}
func countEntries(scan *deltaIndexScanner) (cnt int) {
// Figure out exactly how many entries we need. As we do the
// enumeration truncate any delta chains longer than what we
// are willing to scan during encode. This keeps the encode
// logic linear in the size of the input rather than quadratic.
for i := 0; i < len(scan.table); i++ {
h := scan.table[i]
if h == 0 {
continue
}
size := 0
for {
size++
if size == maxChainLength {
scan.next[h] = 0
break
}
h = scan.next[h]
if h == 0 {
break
}
}
cnt += size
}
return
}
func (idx *deltaIndex) copyEntries(scanner *deltaIndexScanner) {
// Rebuild the entries list from the scanner, positioning all
// blocks in the same hash chain next to each other. We can
// then later discard the next list, along with the scanner.
//
next := 1
for i := 0; i < len(idx.table); i++ {
h := idx.table[i]
if h == 0 {
continue
}
idx.table[i] = next
for {
idx.entries[next] = scanner.entries[h]
next++
h = scanner.next[h]
if h == 0 {
break
}
}
}
}
type deltaIndexScanner struct {
table []int
entries []int
next []int
mask int
count int
}
func newDeltaIndexScanner(buf []byte, size int) *deltaIndexScanner {
size -= size % blksz
worstCaseBlockCnt := size / blksz
if worstCaseBlockCnt < 1 {
return new(deltaIndexScanner)
}
tableSize := tableSize(worstCaseBlockCnt)
scanner := &deltaIndexScanner{
table: make([]int, tableSize),
mask: tableSize - 1,
entries: make([]int, worstCaseBlockCnt+1),
next: make([]int, worstCaseBlockCnt+1),
}
scanner.scan(buf, size)
return scanner
}
// slightly modified version of JGit's DeltaIndexScanner. We store the offset on the entries
// instead of the entries and the key, so we avoid operations to retrieve the offset later, as
// we don't use the key.
// See: https://github.com/eclipse/jgit/blob/005e5feb4ecd08c4e4d141a38b9e7942accb3212/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/DeltaIndexScanner.java
func (s *deltaIndexScanner) scan(buf []byte, end int) {
lastHash := 0
ptr := end - blksz
for {
key := hashBlock(buf, ptr)
tIdx := key & s.mask
head := s.table[tIdx]
if head != 0 && lastHash == key {
s.entries[head] = ptr
} else {
s.count++
eIdx := s.count
s.entries[eIdx] = ptr
s.next[eIdx] = head
s.table[tIdx] = eIdx
}
lastHash = key
ptr -= blksz
if 0 > ptr {
break
}
}
}
func tableSize(worstCaseBlockCnt int) int {
shift := 32 - leadingZeros(uint32(worstCaseBlockCnt))
sz := 1 << uint(shift-1)
if sz < worstCaseBlockCnt {
sz <<= 1
}
return sz
}
// use https://golang.org/pkg/math/bits/#LeadingZeros32 in the future
func leadingZeros(x uint32) (n int) {
if x >= 1<<16 {
x >>= 16
n = 16
}
if x >= 1<<8 {
x >>= 8
n += 8
}
n += int(len8tab[x])
return 32 - n
}
var len8tab = [256]uint8{
0x00, 0x01, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
}
func hashBlock(raw []byte, ptr int) int {
// The first 4 steps collapse out into a 4 byte big-endian decode,
// with a larger right shift as we combined shift lefts together.
//
hash := ((uint32(raw[ptr]) & 0xff) << 24) |
((uint32(raw[ptr+1]) & 0xff) << 16) |
((uint32(raw[ptr+2]) & 0xff) << 8) |
(uint32(raw[ptr+3]) & 0xff)
hash ^= T[hash>>31]
hash = ((hash << 8) | (uint32(raw[ptr+4]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+5]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+6]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+7]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+8]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+9]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+10]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+11]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+12]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+13]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+14]) & 0xff)) ^ T[hash>>23]
hash = ((hash << 8) | (uint32(raw[ptr+15]) & 0xff)) ^ T[hash>>23]
return int(hash)
}
var T = []uint32{0x00000000, 0xd4c6b32d, 0x7d4bd577,
0xa98d665a, 0x2e5119c3, 0xfa97aaee, 0x531accb4, 0x87dc7f99,
0x5ca23386, 0x886480ab, 0x21e9e6f1, 0xf52f55dc, 0x72f32a45,
0xa6359968, 0x0fb8ff32, 0xdb7e4c1f, 0x6d82d421, 0xb944670c,
0x10c90156, 0xc40fb27b, 0x43d3cde2, 0x97157ecf, 0x3e981895,
0xea5eabb8, 0x3120e7a7, 0xe5e6548a, 0x4c6b32d0, 0x98ad81fd,
0x1f71fe64, 0xcbb74d49, 0x623a2b13, 0xb6fc983e, 0x0fc31b6f,
0xdb05a842, 0x7288ce18, 0xa64e7d35, 0x219202ac, 0xf554b181,
0x5cd9d7db, 0x881f64f6, 0x536128e9, 0x87a79bc4, 0x2e2afd9e,
0xfaec4eb3, 0x7d30312a, 0xa9f68207, 0x007be45d, 0xd4bd5770,
0x6241cf4e, 0xb6877c63, 0x1f0a1a39, 0xcbcca914, 0x4c10d68d,
0x98d665a0, 0x315b03fa, 0xe59db0d7, 0x3ee3fcc8, 0xea254fe5,
0x43a829bf, 0x976e9a92, 0x10b2e50b, 0xc4745626, 0x6df9307c,
0xb93f8351, 0x1f8636de, 0xcb4085f3, 0x62cde3a9, 0xb60b5084,
0x31d72f1d, 0xe5119c30, 0x4c9cfa6a, 0x985a4947, 0x43240558,
0x97e2b675, 0x3e6fd02f, 0xeaa96302, 0x6d751c9b, 0xb9b3afb6,
0x103ec9ec, 0xc4f87ac1, 0x7204e2ff, 0xa6c251d2, 0x0f4f3788,
0xdb8984a5, 0x5c55fb3c, 0x88934811, 0x211e2e4b, 0xf5d89d66,
0x2ea6d179, 0xfa606254, 0x53ed040e, 0x872bb723, 0x00f7c8ba,
0xd4317b97, 0x7dbc1dcd, 0xa97aaee0, 0x10452db1, 0xc4839e9c,
0x6d0ef8c6, 0xb9c84beb, 0x3e143472, 0xead2875f, 0x435fe105,
0x97995228, 0x4ce71e37, 0x9821ad1a, 0x31accb40, 0xe56a786d,
0x62b607f4, 0xb670b4d9, 0x1ffdd283, 0xcb3b61ae, 0x7dc7f990,
0xa9014abd, 0x008c2ce7, 0xd44a9fca, 0x5396e053, 0x8750537e,
0x2edd3524, 0xfa1b8609, 0x2165ca16, 0xf5a3793b, 0x5c2e1f61,
0x88e8ac4c, 0x0f34d3d5, 0xdbf260f8, 0x727f06a2, 0xa6b9b58f,
0x3f0c6dbc, 0xebcade91, 0x4247b8cb, 0x96810be6, 0x115d747f,
0xc59bc752, 0x6c16a108, 0xb8d01225, 0x63ae5e3a, 0xb768ed17,
0x1ee58b4d, 0xca233860, 0x4dff47f9, 0x9939f4d4, 0x30b4928e,
0xe47221a3, 0x528eb99d, 0x86480ab0, 0x2fc56cea, 0xfb03dfc7,
0x7cdfa05e, 0xa8191373, 0x01947529, 0xd552c604, 0x0e2c8a1b,
0xdaea3936, 0x73675f6c, 0xa7a1ec41, 0x207d93d8, 0xf4bb20f5,
0x5d3646af, 0x89f0f582, 0x30cf76d3, 0xe409c5fe, 0x4d84a3a4,
0x99421089, 0x1e9e6f10, 0xca58dc3d, 0x63d5ba67, 0xb713094a,
0x6c6d4555, 0xb8abf678, 0x11269022, 0xc5e0230f, 0x423c5c96,
0x96faefbb, 0x3f7789e1, 0xebb13acc, 0x5d4da2f2, 0x898b11df,
0x20067785, 0xf4c0c4a8, 0x731cbb31, 0xa7da081c, 0x0e576e46,
0xda91dd6b, 0x01ef9174, 0xd5292259, 0x7ca44403, 0xa862f72e,
0x2fbe88b7, 0xfb783b9a, 0x52f55dc0, 0x8633eeed, 0x208a5b62,
0xf44ce84f, 0x5dc18e15, 0x89073d38, 0x0edb42a1, 0xda1df18c,
0x739097d6, 0xa75624fb, 0x7c2868e4, 0xa8eedbc9, 0x0163bd93,
0xd5a50ebe, 0x52797127, 0x86bfc20a, 0x2f32a450, 0xfbf4177d,
0x4d088f43, 0x99ce3c6e, 0x30435a34, 0xe485e919, 0x63599680,
0xb79f25ad, 0x1e1243f7, 0xcad4f0da, 0x11aabcc5, 0xc56c0fe8,
0x6ce169b2, 0xb827da9f, 0x3ffba506, 0xeb3d162b, 0x42b07071,
0x9676c35c, 0x2f49400d, 0xfb8ff320, 0x5202957a, 0x86c42657,
0x011859ce, 0xd5deeae3, 0x7c538cb9, 0xa8953f94, 0x73eb738b,
0xa72dc0a6, 0x0ea0a6fc, 0xda6615d1, 0x5dba6a48, 0x897cd965,
0x20f1bf3f, 0xf4370c12, 0x42cb942c, 0x960d2701, 0x3f80415b,
0xeb46f276, 0x6c9a8def, 0xb85c3ec2, 0x11d15898, 0xc517ebb5,
0x1e69a7aa, 0xcaaf1487, 0x632272dd, 0xb7e4c1f0, 0x3038be69,
0xe4fe0d44, 0x4d736b1e, 0x99b5d833,
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/delta_selector.go
================================================
package packfile
import (
"sort"
"sync"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
const (
// deltas based on deltas, how many steps we can do.
// 50 is the default value used in JGit
maxDepth = int64(50)
)
// applyDelta is the set of object types that we should apply deltas
var applyDelta = map[plumbing.ObjectType]bool{
plumbing.BlobObject: true,
plumbing.TreeObject: true,
}
type deltaSelector struct {
storer storer.EncodedObjectStorer
}
func newDeltaSelector(s storer.EncodedObjectStorer) *deltaSelector {
return &deltaSelector{s}
}
// ObjectsToPack creates a list of ObjectToPack from the hashes
// provided, creating deltas if it's suitable, using an specific
// internal logic. `packWindow` specifies the size of the sliding
// window used to compare objects for delta compression; 0 turns off
// delta compression entirely.
func (dw *deltaSelector) ObjectsToPack(
hashes []plumbing.Hash,
packWindow uint,
) ([]*ObjectToPack, error) {
otp, err := dw.objectsToPack(hashes, packWindow)
if err != nil {
return nil, err
}
if packWindow == 0 {
return otp, nil
}
dw.sort(otp)
var objectGroups [][]*ObjectToPack
var prev *ObjectToPack
i := -1
for _, obj := range otp {
if prev == nil || prev.Type() != obj.Type() {
objectGroups = append(objectGroups, []*ObjectToPack{obj})
i++
prev = obj
} else {
objectGroups[i] = append(objectGroups[i], obj)
}
}
var wg sync.WaitGroup
var once sync.Once
for _, objs := range objectGroups {
objs := objs
wg.Add(1)
go func() {
if walkErr := dw.walk(objs, packWindow); walkErr != nil {
once.Do(func() {
err = walkErr
})
}
wg.Done()
}()
}
wg.Wait()
if err != nil {
return nil, err
}
return otp, nil
}
func (dw *deltaSelector) objectsToPack(
hashes []plumbing.Hash,
packWindow uint,
) ([]*ObjectToPack, error) {
var objectsToPack []*ObjectToPack
for _, h := range hashes {
var o plumbing.EncodedObject
var err error
if packWindow == 0 {
o, err = dw.encodedObject(h)
} else {
o, err = dw.encodedDeltaObject(h)
}
if err != nil {
return nil, err
}
otp := newObjectToPack(o)
if _, ok := o.(plumbing.DeltaObject); ok {
otp.CleanOriginal()
}
objectsToPack = append(objectsToPack, otp)
}
if packWindow == 0 {
return objectsToPack, nil
}
if err := dw.fixAndBreakChains(objectsToPack); err != nil {
return nil, err
}
return objectsToPack, nil
}
func (dw *deltaSelector) encodedDeltaObject(h plumbing.Hash) (plumbing.EncodedObject, error) {
edos, ok := dw.storer.(storer.DeltaObjectStorer)
if !ok {
return dw.encodedObject(h)
}
return edos.DeltaObject(plumbing.AnyObject, h)
}
func (dw *deltaSelector) encodedObject(h plumbing.Hash) (plumbing.EncodedObject, error) {
return dw.storer.EncodedObject(plumbing.AnyObject, h)
}
func (dw *deltaSelector) fixAndBreakChains(objectsToPack []*ObjectToPack) error {
m := make(map[plumbing.Hash]*ObjectToPack, len(objectsToPack))
for _, otp := range objectsToPack {
m[otp.Hash()] = otp
}
for _, otp := range objectsToPack {
if err := dw.fixAndBreakChainsOne(m, otp); err != nil {
return err
}
}
return nil
}
func (dw *deltaSelector) fixAndBreakChainsOne(objectsToPack map[plumbing.Hash]*ObjectToPack, otp *ObjectToPack) error {
if !otp.Object.Type().IsDelta() {
return nil
}
// Initial ObjectToPack instances might have a delta assigned to Object
// but no actual base initially. Once Base is assigned to a delta, it means
// we already fixed it.
if otp.Base != nil {
return nil
}
do, ok := otp.Object.(plumbing.DeltaObject)
if !ok {
// if this is not a DeltaObject, then we cannot retrieve its base,
// so we have to break the delta chain here.
return dw.undeltify(otp)
}
base, ok := objectsToPack[do.BaseHash()]
if !ok {
// The base of the delta is not in our list of objects to pack, so
// we break the chain.
return dw.undeltify(otp)
}
if err := dw.fixAndBreakChainsOne(objectsToPack, base); err != nil {
return err
}
otp.SetDelta(base, otp.Object)
return nil
}
func (dw *deltaSelector) restoreOriginal(otp *ObjectToPack) error {
if otp.Original != nil {
return nil
}
if !otp.Object.Type().IsDelta() {
return nil
}
obj, err := dw.encodedObject(otp.Hash())
if err != nil {
return err
}
otp.SetOriginal(obj)
return nil
}
// undeltify undeltifies an *ObjectToPack by retrieving the original object from
// the storer and resetting it.
func (dw *deltaSelector) undeltify(otp *ObjectToPack) error {
if err := dw.restoreOriginal(otp); err != nil {
return err
}
otp.Object = otp.Original
otp.Depth = 0
return nil
}
func (dw *deltaSelector) sort(objectsToPack []*ObjectToPack) {
sort.Sort(byTypeAndSize(objectsToPack))
}
func (dw *deltaSelector) walk(
objectsToPack []*ObjectToPack,
packWindow uint,
) error {
indexMap := make(map[plumbing.Hash]*deltaIndex)
for i := 0; i < len(objectsToPack); i++ {
// Clean up the index map and reconstructed delta objects for anything
// outside our pack window, to save memory.
if i > int(packWindow) {
obj := objectsToPack[i-int(packWindow)]
delete(indexMap, obj.Hash())
if obj.IsDelta() {
obj.SaveOriginalMetadata()
obj.CleanOriginal()
}
}
target := objectsToPack[i]
// If we already have a delta, we don't try to find a new one for this
// object. This happens when a delta is set to be reused from an existing
// packfile.
if target.IsDelta() {
continue
}
// We only want to create deltas from specific types.
if !applyDelta[target.Type()] {
continue
}
for j := i - 1; j >= 0 && i-j < int(packWindow); j-- {
base := objectsToPack[j]
// Objects must use only the same type as their delta base.
// Since objectsToPack is sorted by type and size, once we find
// a different type, we know we won't find more of them.
if base.Type() != target.Type() {
break
}
if err := dw.tryToDeltify(indexMap, base, target); err != nil {
return err
}
}
}
return nil
}
func (dw *deltaSelector) tryToDeltify(indexMap map[plumbing.Hash]*deltaIndex, base, target *ObjectToPack) error {
// Original object might not be present if we're reusing a delta, so we
// ensure it is restored.
if err := dw.restoreOriginal(target); err != nil {
return err
}
if err := dw.restoreOriginal(base); err != nil {
return err
}
// If the sizes are radically different, this is a bad pairing.
if target.Size() < base.Size()>>4 {
return nil
}
msz := dw.deltaSizeLimit(
target.Object.Size(),
base.Depth,
target.Depth,
target.IsDelta(),
)
// Nearly impossible to fit useful delta.
if msz <= 8 {
return nil
}
// If we have to insert a lot to make this work, find another.
if base.Size()-target.Size() > msz {
return nil
}
if _, ok := indexMap[base.Hash()]; !ok {
indexMap[base.Hash()] = new(deltaIndex)
}
// Now we can generate the delta using originals
delta, err := getDelta(indexMap[base.Hash()], base.Original, target.Original)
if err != nil {
return err
}
// if delta better than target
if delta.Size() < msz {
target.SetDelta(base, delta)
}
return nil
}
func (dw *deltaSelector) deltaSizeLimit(targetSize int64, baseDepth int,
targetDepth int, targetDelta bool) int64 {
if !targetDelta {
// Any delta should be no more than 50% of the original size
// (for text files deflate of whole form should shrink 50%).
n := targetSize >> 1
// Evenly distribute delta size limits over allowed depth.
// If src is non-delta (depth = 0), delta <= 50% of original.
// If src is almost at limit (9/10), delta <= 10% of original.
return n * (maxDepth - int64(baseDepth)) / maxDepth
}
// With a delta base chosen any new delta must be "better".
// Retain the distribution described above.
d := int64(targetDepth)
n := targetSize
// If target depth is bigger than maxDepth, this delta is not suitable to be used.
if d >= maxDepth {
return 0
}
// If src is whole (depth=0) and base is near limit (depth=9/10)
// any delta using src can be 10x larger and still be better.
//
// If src is near limit (depth=9/10) and base is whole (depth=0)
// a new delta dependent on src must be 1/10th the size.
return n * (maxDepth - int64(baseDepth)) / (maxDepth - d)
}
type byTypeAndSize []*ObjectToPack
func (a byTypeAndSize) Len() int { return len(a) }
func (a byTypeAndSize) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byTypeAndSize) Less(i, j int) bool {
if a[i].Type() < a[j].Type() {
return false
}
if a[i].Type() > a[j].Type() {
return true
}
return a[i].Size() > a[j].Size()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/diff_delta.go
================================================
package packfile
import (
"bytes"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
// See https://github.com/jelmer/dulwich/blob/master/dulwich/pack.py and
// https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js
// for more info
const (
// Standard chunk size used to generate fingerprints
s = 16
// https://github.com/git/git/blob/f7466e94375b3be27f229c78873f0acf8301c0a5/diff-delta.c#L428
// Max size of a copy operation (64KB).
maxCopySize = 64 * 1024
// Min size of a copy operation.
minCopySize = 4
)
// GetDelta returns an EncodedObject of type OFSDeltaObject. Base and Target object,
// will be loaded into memory to be able to create the delta object.
// To generate target again, you will need the obtained object and "base" one.
// Error will be returned if base or target object cannot be read.
func GetDelta(base, target plumbing.EncodedObject) (plumbing.EncodedObject, error) {
return getDelta(new(deltaIndex), base, target)
}
func getDelta(index *deltaIndex, base, target plumbing.EncodedObject) (o plumbing.EncodedObject, err error) {
br, err := base.Reader()
if err != nil {
return nil, err
}
defer ioutil.CheckClose(br, &err)
tr, err := target.Reader()
if err != nil {
return nil, err
}
defer ioutil.CheckClose(tr, &err)
bb := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(bb)
_, err = bb.ReadFrom(br)
if err != nil {
return nil, err
}
tb := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(tb)
_, err = tb.ReadFrom(tr)
if err != nil {
return nil, err
}
db := diffDelta(index, bb.Bytes(), tb.Bytes())
delta := &plumbing.MemoryObject{}
_, err = delta.Write(db)
if err != nil {
return nil, err
}
delta.SetSize(int64(len(db)))
delta.SetType(plumbing.OFSDeltaObject)
return delta, nil
}
// DiffDelta returns the delta that transforms src into tgt.
func DiffDelta(src, tgt []byte) []byte {
return diffDelta(new(deltaIndex), src, tgt)
}
func diffDelta(index *deltaIndex, src []byte, tgt []byte) []byte {
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
buf.Write(deltaEncodeSize(len(src)))
buf.Write(deltaEncodeSize(len(tgt)))
if len(index.entries) == 0 {
index.init(src)
}
ibuf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(ibuf)
for i := 0; i < len(tgt); i++ {
offset, l := index.findMatch(src, tgt, i)
if l == 0 {
// couldn't find a match, just write the current byte and continue
ibuf.WriteByte(tgt[i])
} else if l < 0 {
// src is less than blksz, copy the rest of the target to avoid
// calls to findMatch
for ; i < len(tgt); i++ {
ibuf.WriteByte(tgt[i])
}
} else if l < s {
// remaining target is less than blksz, copy what's left of it
// and avoid calls to findMatch
for j := i; j < i+l; j++ {
ibuf.WriteByte(tgt[j])
}
i += l - 1
} else {
encodeInsertOperation(ibuf, buf)
rl := l
aOffset := offset
for rl > 0 {
if rl < maxCopySize {
buf.Write(encodeCopyOperation(aOffset, rl))
break
}
buf.Write(encodeCopyOperation(aOffset, maxCopySize))
rl -= maxCopySize
aOffset += maxCopySize
}
i += l - 1
}
}
encodeInsertOperation(ibuf, buf)
// buf.Bytes() is only valid until the next modifying operation on the buffer. Copy it.
return append([]byte{}, buf.Bytes()...)
}
func encodeInsertOperation(ibuf, buf *bytes.Buffer) {
if ibuf.Len() == 0 {
return
}
b := ibuf.Bytes()
s := ibuf.Len()
o := 0
for {
if s <= 127 {
break
}
buf.WriteByte(byte(127))
buf.Write(b[o : o+127])
s -= 127
o += 127
}
buf.WriteByte(byte(s))
buf.Write(b[o : o+s])
ibuf.Reset()
}
func deltaEncodeSize(size int) []byte {
var ret []byte
c := size & 0x7f
size >>= 7
for {
if size == 0 {
break
}
ret = append(ret, byte(c|0x80))
c = size & 0x7f
size >>= 7
}
ret = append(ret, byte(c))
return ret
}
func encodeCopyOperation(offset, length int) []byte {
code := 0x80
var opcodes []byte
var i uint
for i = 0; i < 4; i++ {
f := 0xff << (i * 8)
if offset&f != 0 {
opcodes = append(opcodes, byte(offset&f>>(i*8)))
code |= 0x01 << i
}
}
for i = 0; i < 3; i++ {
f := 0xff << (i * 8)
if length&f != 0 {
opcodes = append(opcodes, byte(length&f>>(i*8)))
code |= 0x10 << i
}
}
return append([]byte{byte(code)}, opcodes...)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/doc.go
================================================
// Package packfile implements encoding and decoding of packfile format.
//
// == pack-*.pack files have the following format:
//
// - A header appears at the beginning and consists of the following:
//
// 4-byte signature:
// The signature is: {'P', 'A', 'C', 'K'}
//
// 4-byte version number (network byte order):
// GIT currently accepts version number 2 or 3 but
// generates version 2 only.
//
// 4-byte number of objects contained in the pack (network byte order)
//
// Observation: we cannot have more than 4G versions ;-) and
// more than 4G objects in a pack.
//
// - The header is followed by number of object entries, each of
// which looks like this:
//
// (undeltified representation)
// n-byte type and length (3-bit type, (n-1)*7+4-bit length)
// compressed data
//
// (deltified representation)
// n-byte type and length (3-bit type, (n-1)*7+4-bit length)
// 20-byte base object name
// compressed delta data
//
// Observation: length of each object is encoded in a variable
// length format and is not constrained to 32-bit or anything.
//
// - The trailer records 20-byte SHA1 checksum of all of the above.
//
//
// Source:
// https://www.kernel.org/pub/software/scm/git/docs/v1.7.5/technical/pack-protocol.txt
package packfile
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/encoder.go
================================================
package packfile
import (
"compress/zlib"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/binary"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// Encoder gets the data from the storage and write it into the writer in PACK
// format
type Encoder struct {
selector *deltaSelector
w *offsetWriter
zw *zlib.Writer
hasher plumbing.Hasher
useRefDeltas bool
}
// NewEncoder creates a new packfile encoder using a specific Writer and
// EncodedObjectStorer. By default deltas used to generate the packfile will be
// OFSDeltaObject. To use Reference deltas, set useRefDeltas to true.
func NewEncoder(w io.Writer, s storer.EncodedObjectStorer, useRefDeltas bool) *Encoder {
h := plumbing.Hasher{
Hash: hash.New(hash.CryptoType),
}
mw := io.MultiWriter(w, h)
ow := newOffsetWriter(mw)
zw := zlib.NewWriter(mw)
return &Encoder{
selector: newDeltaSelector(s),
w: ow,
zw: zw,
hasher: h,
useRefDeltas: useRefDeltas,
}
}
// Encode creates a packfile containing all the objects referenced in
// hashes and writes it to the writer in the Encoder. `packWindow`
// specifies the size of the sliding window used to compare objects
// for delta compression; 0 turns off delta compression entirely.
func (e *Encoder) Encode(
hashes []plumbing.Hash,
packWindow uint,
) (plumbing.Hash, error) {
objects, err := e.selector.ObjectsToPack(hashes, packWindow)
if err != nil {
return plumbing.ZeroHash, err
}
return e.encode(objects)
}
func (e *Encoder) encode(objects []*ObjectToPack) (plumbing.Hash, error) {
if err := e.head(len(objects)); err != nil {
return plumbing.ZeroHash, err
}
for _, o := range objects {
if err := e.entry(o); err != nil {
return plumbing.ZeroHash, err
}
}
return e.footer()
}
func (e *Encoder) head(numEntries int) error {
return binary.Write(
e.w,
signature,
int32(VersionSupported),
int32(numEntries),
)
}
func (e *Encoder) entry(o *ObjectToPack) (err error) {
if o.WantWrite() {
// A cycle exists in this delta chain. This should only occur if a
// selected object representation disappeared during writing
// (for example due to a concurrent repack) and a different base
// was chosen, forcing a cycle. Select something other than a
// delta, and write this object.
e.selector.restoreOriginal(o)
o.BackToOriginal()
}
if o.IsWritten() {
return nil
}
o.MarkWantWrite()
if err := e.writeBaseIfDelta(o); err != nil {
return err
}
// We need to check if we already write that object due a cyclic delta chain
if o.IsWritten() {
return nil
}
o.Offset = e.w.Offset()
if o.IsDelta() {
if err := e.writeDeltaHeader(o); err != nil {
return err
}
} else {
if err := e.entryHead(o.Type(), o.Size()); err != nil {
return err
}
}
e.zw.Reset(e.w)
defer ioutil.CheckClose(e.zw, &err)
or, err := o.Object.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(or, &err)
_, err = io.Copy(e.zw, or)
return err
}
func (e *Encoder) writeBaseIfDelta(o *ObjectToPack) error {
if o.IsDelta() && !o.Base.IsWritten() {
// We must write base first
return e.entry(o.Base)
}
return nil
}
func (e *Encoder) writeDeltaHeader(o *ObjectToPack) error {
// Write offset deltas by default
t := plumbing.OFSDeltaObject
if e.useRefDeltas {
t = plumbing.REFDeltaObject
}
if err := e.entryHead(t, o.Object.Size()); err != nil {
return err
}
if e.useRefDeltas {
return e.writeRefDeltaHeader(o.Base.Hash())
} else {
return e.writeOfsDeltaHeader(o)
}
}
func (e *Encoder) writeRefDeltaHeader(base plumbing.Hash) error {
return binary.Write(e.w, base)
}
func (e *Encoder) writeOfsDeltaHeader(o *ObjectToPack) error {
// for OFS_DELTA, offset of the base is interpreted as negative offset
// relative to the type-byte of the header of the ofs-delta entry.
relativeOffset := o.Offset - o.Base.Offset
if relativeOffset <= 0 {
return fmt.Errorf("bad offset for OFS_DELTA entry: %d", relativeOffset)
}
return binary.WriteVariableWidthInt(e.w, relativeOffset)
}
func (e *Encoder) entryHead(typeNum plumbing.ObjectType, size int64) error {
t := int64(typeNum)
header := []byte{}
c := (t << firstLengthBits) | (size & maskFirstLength)
size >>= firstLengthBits
for {
if size == 0 {
break
}
header = append(header, byte(c|maskContinue))
c = size & int64(maskLength)
size >>= lengthBits
}
header = append(header, byte(c))
_, err := e.w.Write(header)
return err
}
func (e *Encoder) footer() (plumbing.Hash, error) {
h := e.hasher.Sum()
return h, binary.Write(e.w, h)
}
type offsetWriter struct {
w io.Writer
offset int64
}
func newOffsetWriter(w io.Writer) *offsetWriter {
return &offsetWriter{w: w}
}
func (ow *offsetWriter) Write(p []byte) (n int, err error) {
n, err = ow.w.Write(p)
ow.offset += int64(n)
return n, err
}
func (ow *offsetWriter) Offset() int64 {
return ow.offset
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/error.go
================================================
package packfile
import "fmt"
// Error specifies errors returned during packfile parsing.
type Error struct {
reason, details string
}
// NewError returns a new error.
func NewError(reason string) *Error {
return &Error{reason: reason}
}
// Error returns a text representation of the error.
func (e *Error) Error() string {
if e.details == "" {
return e.reason
}
return fmt.Sprintf("%s: %s", e.reason, e.details)
}
// AddDetails adds details to an error, with additional text.
func (e *Error) AddDetails(format string, args ...interface{}) *Error {
return &Error{
reason: e.reason,
details: fmt.Sprintf(format, args...),
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/fsobject.go
================================================
package packfile
import (
"io"
billy "github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// FSObject is an object from the packfile on the filesystem.
type FSObject struct {
hash plumbing.Hash
offset int64
size int64
typ plumbing.ObjectType
index idxfile.Index
fs billy.Filesystem
path string
cache cache.Object
largeObjectThreshold int64
}
// NewFSObject creates a new filesystem object.
func NewFSObject(
hash plumbing.Hash,
finalType plumbing.ObjectType,
offset int64,
contentSize int64,
index idxfile.Index,
fs billy.Filesystem,
path string,
cache cache.Object,
largeObjectThreshold int64,
) *FSObject {
return &FSObject{
hash: hash,
offset: offset,
size: contentSize,
typ: finalType,
index: index,
fs: fs,
path: path,
cache: cache,
largeObjectThreshold: largeObjectThreshold,
}
}
// Reader implements the plumbing.EncodedObject interface.
func (o *FSObject) Reader() (io.ReadCloser, error) {
obj, ok := o.cache.Get(o.hash)
if ok && obj != o {
reader, err := obj.Reader()
if err != nil {
return nil, err
}
return reader, nil
}
f, err := o.fs.Open(o.path)
if err != nil {
return nil, err
}
p := NewPackfileWithCache(o.index, nil, f, o.cache, o.largeObjectThreshold)
if o.largeObjectThreshold > 0 && o.size > o.largeObjectThreshold {
// We have a big object
h, err := p.objectHeaderAtOffset(o.offset)
if err != nil {
return nil, err
}
r, err := p.getReaderDirect(h)
if err != nil {
_ = f.Close()
return nil, err
}
return ioutil.NewReadCloserWithCloser(r, f.Close), nil
}
r, err := p.getObjectContent(o.offset)
if err != nil {
_ = f.Close()
return nil, err
}
if err := f.Close(); err != nil {
return nil, err
}
return r, nil
}
// SetSize implements the plumbing.EncodedObject interface. This method
// is a noop.
func (o *FSObject) SetSize(int64) {}
// SetType implements the plumbing.EncodedObject interface. This method is
// a noop.
func (o *FSObject) SetType(plumbing.ObjectType) {}
// Hash implements the plumbing.EncodedObject interface.
func (o *FSObject) Hash() plumbing.Hash { return o.hash }
// Size implements the plumbing.EncodedObject interface.
func (o *FSObject) Size() int64 { return o.size }
// Type implements the plumbing.EncodedObject interface.
func (o *FSObject) Type() plumbing.ObjectType {
return o.typ
}
// Writer implements the plumbing.EncodedObject interface. This method always
// returns a nil writer.
func (o *FSObject) Writer() (io.WriteCloser, error) {
return nil, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/object_pack.go
================================================
package packfile
import (
"github.com/go-git/go-git/v5/plumbing"
)
// ObjectToPack is a representation of an object that is going to be into a
// pack file.
type ObjectToPack struct {
// The main object to pack, it could be any object, including deltas
Object plumbing.EncodedObject
// Base is the object that a delta is based on (it could be also another delta).
// If the main object is not a delta, Base will be null
Base *ObjectToPack
// Original is the object that we can generate applying the delta to
// Base, or the same object as Object in the case of a non-delta
// object.
Original plumbing.EncodedObject
// Depth is the amount of deltas needed to resolve to obtain Original
// (delta based on delta based on ...)
Depth int
// offset in pack when object has been already written, or 0 if it
// has not been written yet
Offset int64
// Information from the original object
resolvedOriginal bool
originalType plumbing.ObjectType
originalSize int64
originalHash plumbing.Hash
}
// newObjectToPack creates a correct ObjectToPack based on a non-delta object
func newObjectToPack(o plumbing.EncodedObject) *ObjectToPack {
return &ObjectToPack{
Object: o,
Original: o,
}
}
// newDeltaObjectToPack creates a correct ObjectToPack for a delta object, based on
// his base (could be another delta), the delta target (in this case called original),
// and the delta Object itself
func newDeltaObjectToPack(base *ObjectToPack, original, delta plumbing.EncodedObject) *ObjectToPack {
return &ObjectToPack{
Object: delta,
Base: base,
Original: original,
Depth: base.Depth + 1,
}
}
// BackToOriginal converts that ObjectToPack to a non-deltified object if it was one
func (o *ObjectToPack) BackToOriginal() {
if o.IsDelta() && o.Original != nil {
o.Object = o.Original
o.Base = nil
o.Depth = 0
}
}
// IsWritten returns if that ObjectToPack was
// already written into the packfile or not
func (o *ObjectToPack) IsWritten() bool {
return o.Offset > 1
}
// MarkWantWrite marks this ObjectToPack as WantWrite
// to avoid delta chain loops
func (o *ObjectToPack) MarkWantWrite() {
o.Offset = 1
}
// WantWrite checks if this ObjectToPack was marked as WantWrite before
func (o *ObjectToPack) WantWrite() bool {
return o.Offset == 1
}
// SetOriginal sets both Original and saves size, type and hash. If object
// is nil Original is set but previous resolved values are kept
func (o *ObjectToPack) SetOriginal(obj plumbing.EncodedObject) {
o.Original = obj
o.SaveOriginalMetadata()
}
// SaveOriginalMetadata saves size, type and hash of Original object
func (o *ObjectToPack) SaveOriginalMetadata() {
if o.Original != nil {
o.originalSize = o.Original.Size()
o.originalType = o.Original.Type()
o.originalHash = o.Original.Hash()
o.resolvedOriginal = true
}
}
// CleanOriginal sets Original to nil
func (o *ObjectToPack) CleanOriginal() {
o.Original = nil
}
func (o *ObjectToPack) Type() plumbing.ObjectType {
if o.Original != nil {
return o.Original.Type()
}
if o.resolvedOriginal {
return o.originalType
}
if o.Base != nil {
return o.Base.Type()
}
if o.Object != nil {
return o.Object.Type()
}
panic("cannot get type")
}
func (o *ObjectToPack) Hash() plumbing.Hash {
if o.Original != nil {
return o.Original.Hash()
}
if o.resolvedOriginal {
return o.originalHash
}
do, ok := o.Object.(plumbing.DeltaObject)
if ok {
return do.ActualHash()
}
panic("cannot get hash")
}
func (o *ObjectToPack) Size() int64 {
if o.Original != nil {
return o.Original.Size()
}
if o.resolvedOriginal {
return o.originalSize
}
do, ok := o.Object.(plumbing.DeltaObject)
if ok {
return do.ActualSize()
}
panic("cannot get ObjectToPack size")
}
func (o *ObjectToPack) IsDelta() bool {
return o.Base != nil
}
func (o *ObjectToPack) SetDelta(base *ObjectToPack, delta plumbing.EncodedObject) {
o.Object = delta
o.Base = base
o.Depth = base.Depth + 1
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/packfile.go
================================================
package packfile
import (
"bytes"
"fmt"
"io"
"os"
billy "github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
// ErrInvalidObject is returned by Decode when an invalid object is
// found in the packfile.
ErrInvalidObject = NewError("invalid git object")
// ErrZLib is returned by Decode when there was an error unzipping
// the packfile contents.
ErrZLib = NewError("zlib reading error")
)
// When reading small objects from packfile it is beneficial to do so at
// once to exploit the buffered I/O. In many cases the objects are so small
// that they were already loaded to memory when the object header was
// loaded from the packfile. Wrapping in FSObject would cause this buffered
// data to be thrown away and then re-read later, with the additional
// seeking causing reloads from disk. Objects smaller than this threshold
// are now always read into memory and stored in cache instead of being
// wrapped in FSObject.
const smallObjectThreshold = 16 * 1024
// Packfile allows retrieving information from inside a packfile.
type Packfile struct {
idxfile.Index
fs billy.Filesystem
file billy.File
s *Scanner
deltaBaseCache cache.Object
offsetToType map[int64]plumbing.ObjectType
largeObjectThreshold int64
}
// NewPackfileWithCache creates a new Packfile with the given object cache.
// If the filesystem is provided, the packfile will return FSObjects, otherwise
// it will return MemoryObjects.
func NewPackfileWithCache(
index idxfile.Index,
fs billy.Filesystem,
file billy.File,
cache cache.Object,
largeObjectThreshold int64,
) *Packfile {
s := NewScanner(file)
return &Packfile{
index,
fs,
file,
s,
cache,
make(map[int64]plumbing.ObjectType),
largeObjectThreshold,
}
}
// NewPackfile returns a packfile representation for the given packfile file
// and packfile idx.
// If the filesystem is provided, the packfile will return FSObjects, otherwise
// it will return MemoryObjects.
func NewPackfile(index idxfile.Index, fs billy.Filesystem, file billy.File, largeObjectThreshold int64) *Packfile {
return NewPackfileWithCache(index, fs, file, cache.NewObjectLRUDefault(), largeObjectThreshold)
}
// Get retrieves the encoded object in the packfile with the given hash.
func (p *Packfile) Get(h plumbing.Hash) (plumbing.EncodedObject, error) {
offset, err := p.FindOffset(h)
if err != nil {
return nil, err
}
return p.objectAtOffset(offset, h)
}
// GetByOffset retrieves the encoded object from the packfile at the given
// offset.
func (p *Packfile) GetByOffset(o int64) (plumbing.EncodedObject, error) {
hash, err := p.FindHash(o)
if err != nil {
return nil, err
}
return p.objectAtOffset(o, hash)
}
// GetSizeByOffset retrieves the size of the encoded object from the
// packfile with the given offset.
func (p *Packfile) GetSizeByOffset(o int64) (size int64, err error) {
if _, err := p.s.SeekFromStart(o); err != nil {
if err == io.EOF || isInvalid(err) {
return 0, plumbing.ErrObjectNotFound
}
return 0, err
}
h, err := p.nextObjectHeader()
if err != nil {
return 0, err
}
return p.getObjectSize(h)
}
func (p *Packfile) objectHeaderAtOffset(offset int64) (*ObjectHeader, error) {
h, err := p.s.SeekObjectHeader(offset)
p.s.pendingObject = nil
return h, err
}
func (p *Packfile) nextObjectHeader() (*ObjectHeader, error) {
h, err := p.s.NextObjectHeader()
p.s.pendingObject = nil
return h, err
}
func (p *Packfile) getDeltaObjectSize(buf *bytes.Buffer) int64 {
delta := buf.Bytes()
_, delta = decodeLEB128(delta) // skip src size
sz, _ := decodeLEB128(delta)
return int64(sz)
}
func (p *Packfile) getObjectSize(h *ObjectHeader) (int64, error) {
switch h.Type {
case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject:
return h.Length, nil
case plumbing.REFDeltaObject, plumbing.OFSDeltaObject:
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
if _, _, err := p.s.NextObject(buf); err != nil {
return 0, err
}
return p.getDeltaObjectSize(buf), nil
default:
return 0, ErrInvalidObject.AddDetails("type %q", h.Type)
}
}
func (p *Packfile) getObjectType(h *ObjectHeader) (typ plumbing.ObjectType, err error) {
switch h.Type {
case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject:
return h.Type, nil
case plumbing.REFDeltaObject, plumbing.OFSDeltaObject:
var offset int64
if h.Type == plumbing.REFDeltaObject {
offset, err = p.FindOffset(h.Reference)
if err != nil {
return
}
} else {
offset = h.OffsetReference
}
if baseType, ok := p.offsetToType[offset]; ok {
typ = baseType
} else {
h, err = p.objectHeaderAtOffset(offset)
if err != nil {
return
}
typ, err = p.getObjectType(h)
if err != nil {
return
}
}
default:
err = ErrInvalidObject.AddDetails("type %q", h.Type)
}
p.offsetToType[h.Offset] = typ
return
}
func (p *Packfile) objectAtOffset(offset int64, hash plumbing.Hash) (plumbing.EncodedObject, error) {
if obj, ok := p.cacheGet(hash); ok {
return obj, nil
}
h, err := p.objectHeaderAtOffset(offset)
if err != nil {
if err == io.EOF || isInvalid(err) {
return nil, plumbing.ErrObjectNotFound
}
return nil, err
}
return p.getNextObject(h, hash)
}
func (p *Packfile) getNextObject(h *ObjectHeader, hash plumbing.Hash) (plumbing.EncodedObject, error) {
var err error
// If we have no filesystem, we will return a MemoryObject instead
// of an FSObject.
if p.fs == nil {
return p.getNextMemoryObject(h)
}
// If the object is small enough then read it completely into memory now since
// it is already read from disk into buffer anyway. For delta objects we want
// to perform the optimization too, but we have to be careful about applying
// small deltas on big objects.
var size int64
if h.Length <= smallObjectThreshold {
if h.Type != plumbing.OFSDeltaObject && h.Type != plumbing.REFDeltaObject {
return p.getNextMemoryObject(h)
}
// For delta objects we read the delta data and apply the small object
// optimization only if the expanded version of the object still meets
// the small object threshold condition.
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
if _, _, err := p.s.NextObject(buf); err != nil {
return nil, err
}
size = p.getDeltaObjectSize(buf)
if size <= smallObjectThreshold {
var obj = new(plumbing.MemoryObject)
obj.SetSize(size)
if h.Type == plumbing.REFDeltaObject {
err = p.fillREFDeltaObjectContentWithBuffer(obj, h.Reference, buf)
} else {
err = p.fillOFSDeltaObjectContentWithBuffer(obj, h.OffsetReference, buf)
}
return obj, err
}
} else {
size, err = p.getObjectSize(h)
if err != nil {
return nil, err
}
}
typ, err := p.getObjectType(h)
if err != nil {
return nil, err
}
p.offsetToType[h.Offset] = typ
return NewFSObject(
hash,
typ,
h.Offset,
size,
p.Index,
p.fs,
p.file.Name(),
p.deltaBaseCache,
p.largeObjectThreshold,
), nil
}
func (p *Packfile) getObjectContent(offset int64) (io.ReadCloser, error) {
h, err := p.objectHeaderAtOffset(offset)
if err != nil {
return nil, err
}
// getObjectContent is called from FSObject, so we have to explicitly
// get memory object here to avoid recursive cycle
obj, err := p.getNextMemoryObject(h)
if err != nil {
return nil, err
}
return obj.Reader()
}
func asyncReader(p *Packfile) (io.ReadCloser, error) {
reader := ioutil.NewReaderUsingReaderAt(p.file, p.s.r.offset)
zr, err := sync.GetZlibReader(reader)
if err != nil {
return nil, fmt.Errorf("zlib reset error: %s", err)
}
return ioutil.NewReadCloserWithCloser(zr.Reader, func() error {
sync.PutZlibReader(zr)
return nil
}), nil
}
func (p *Packfile) getReaderDirect(h *ObjectHeader) (io.ReadCloser, error) {
switch h.Type {
case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject:
return asyncReader(p)
case plumbing.REFDeltaObject:
deltaRc, err := asyncReader(p)
if err != nil {
return nil, err
}
r, err := p.readREFDeltaObjectContent(h, deltaRc)
if err != nil {
return nil, err
}
return r, nil
case plumbing.OFSDeltaObject:
deltaRc, err := asyncReader(p)
if err != nil {
return nil, err
}
r, err := p.readOFSDeltaObjectContent(h, deltaRc)
if err != nil {
return nil, err
}
return r, nil
default:
return nil, ErrInvalidObject.AddDetails("type %q", h.Type)
}
}
func (p *Packfile) getNextMemoryObject(h *ObjectHeader) (plumbing.EncodedObject, error) {
var obj = new(plumbing.MemoryObject)
obj.SetSize(h.Length)
obj.SetType(h.Type)
var err error
switch h.Type {
case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject:
err = p.fillRegularObjectContent(obj)
case plumbing.REFDeltaObject:
err = p.fillREFDeltaObjectContent(obj, h.Reference)
case plumbing.OFSDeltaObject:
err = p.fillOFSDeltaObjectContent(obj, h.OffsetReference)
default:
err = ErrInvalidObject.AddDetails("type %q", h.Type)
}
if err != nil {
return nil, err
}
p.offsetToType[h.Offset] = obj.Type()
return obj, nil
}
func (p *Packfile) fillRegularObjectContent(obj plumbing.EncodedObject) (err error) {
w, err := obj.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
_, _, err = p.s.NextObject(w)
p.cachePut(obj)
return err
}
func (p *Packfile) fillREFDeltaObjectContent(obj plumbing.EncodedObject, ref plumbing.Hash) error {
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
_, _, err := p.s.NextObject(buf)
if err != nil {
return err
}
return p.fillREFDeltaObjectContentWithBuffer(obj, ref, buf)
}
func (p *Packfile) readREFDeltaObjectContent(h *ObjectHeader, deltaRC io.Reader) (io.ReadCloser, error) {
var err error
base, ok := p.cacheGet(h.Reference)
if !ok {
base, err = p.Get(h.Reference)
if err != nil {
return nil, err
}
}
return ReaderFromDelta(base, deltaRC)
}
func (p *Packfile) fillREFDeltaObjectContentWithBuffer(obj plumbing.EncodedObject, ref plumbing.Hash, buf *bytes.Buffer) error {
var err error
base, ok := p.cacheGet(ref)
if !ok {
base, err = p.Get(ref)
if err != nil {
return err
}
}
obj.SetType(base.Type())
err = ApplyDelta(obj, base, buf.Bytes())
p.cachePut(obj)
return err
}
func (p *Packfile) fillOFSDeltaObjectContent(obj plumbing.EncodedObject, offset int64) error {
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
_, _, err := p.s.NextObject(buf)
if err != nil {
return err
}
return p.fillOFSDeltaObjectContentWithBuffer(obj, offset, buf)
}
func (p *Packfile) readOFSDeltaObjectContent(h *ObjectHeader, deltaRC io.Reader) (io.ReadCloser, error) {
hash, err := p.FindHash(h.OffsetReference)
if err != nil {
return nil, err
}
base, err := p.objectAtOffset(h.OffsetReference, hash)
if err != nil {
return nil, err
}
return ReaderFromDelta(base, deltaRC)
}
func (p *Packfile) fillOFSDeltaObjectContentWithBuffer(obj plumbing.EncodedObject, offset int64, buf *bytes.Buffer) error {
hash, err := p.FindHash(offset)
if err != nil {
return err
}
base, err := p.objectAtOffset(offset, hash)
if err != nil {
return err
}
obj.SetType(base.Type())
err = ApplyDelta(obj, base, buf.Bytes())
p.cachePut(obj)
return err
}
func (p *Packfile) cacheGet(h plumbing.Hash) (plumbing.EncodedObject, bool) {
if p.deltaBaseCache == nil {
return nil, false
}
return p.deltaBaseCache.Get(h)
}
func (p *Packfile) cachePut(obj plumbing.EncodedObject) {
if p.deltaBaseCache == nil {
return
}
p.deltaBaseCache.Put(obj)
}
// GetAll returns an iterator with all encoded objects in the packfile.
// The iterator returned is not thread-safe, it should be used in the same
// thread as the Packfile instance.
func (p *Packfile) GetAll() (storer.EncodedObjectIter, error) {
return p.GetByType(plumbing.AnyObject)
}
// GetByType returns all the objects of the given type.
func (p *Packfile) GetByType(typ plumbing.ObjectType) (storer.EncodedObjectIter, error) {
switch typ {
case plumbing.AnyObject,
plumbing.BlobObject,
plumbing.TreeObject,
plumbing.CommitObject,
plumbing.TagObject:
entries, err := p.EntriesByOffset()
if err != nil {
return nil, err
}
return &objectIter{
// Easiest way to provide an object decoder is just to pass a Packfile
// instance. To not mess with the seeks, it's a new instance with a
// different scanner but the same cache and offset to hash map for
// reusing as much cache as possible.
p: p,
iter: entries,
typ: typ,
}, nil
default:
return nil, plumbing.ErrInvalidType
}
}
// ID returns the ID of the packfile, which is the checksum at the end of it.
func (p *Packfile) ID() (plumbing.Hash, error) {
prev, err := p.file.Seek(-20, io.SeekEnd)
if err != nil {
return plumbing.ZeroHash, err
}
var hash plumbing.Hash
if _, err := io.ReadFull(p.file, hash[:]); err != nil {
return plumbing.ZeroHash, err
}
if _, err := p.file.Seek(prev, io.SeekStart); err != nil {
return plumbing.ZeroHash, err
}
return hash, nil
}
// Scanner returns the packfile's Scanner
func (p *Packfile) Scanner() *Scanner {
return p.s
}
// Close the packfile and its resources.
func (p *Packfile) Close() error {
closer, ok := p.file.(io.Closer)
if !ok {
return nil
}
return closer.Close()
}
type objectIter struct {
p *Packfile
typ plumbing.ObjectType
iter idxfile.EntryIter
}
func (i *objectIter) Next() (plumbing.EncodedObject, error) {
for {
e, err := i.iter.Next()
if err != nil {
return nil, err
}
if i.typ != plumbing.AnyObject {
if typ, ok := i.p.offsetToType[int64(e.Offset)]; ok {
if typ != i.typ {
continue
}
} else if obj, ok := i.p.cacheGet(e.Hash); ok {
if obj.Type() != i.typ {
i.p.offsetToType[int64(e.Offset)] = obj.Type()
continue
}
return obj, nil
} else {
h, err := i.p.objectHeaderAtOffset(int64(e.Offset))
if err != nil {
return nil, err
}
if h.Type == plumbing.REFDeltaObject || h.Type == plumbing.OFSDeltaObject {
typ, err := i.p.getObjectType(h)
if err != nil {
return nil, err
}
if typ != i.typ {
i.p.offsetToType[int64(e.Offset)] = typ
continue
}
// getObjectType will seek in the file so we cannot use getNextObject safely
return i.p.objectAtOffset(int64(e.Offset), e.Hash)
} else {
if h.Type != i.typ {
i.p.offsetToType[int64(e.Offset)] = h.Type
continue
}
return i.p.getNextObject(h, e.Hash)
}
}
}
obj, err := i.p.objectAtOffset(int64(e.Offset), e.Hash)
if err != nil {
return nil, err
}
return obj, nil
}
}
func (i *objectIter) ForEach(f func(plumbing.EncodedObject) error) error {
for {
o, err := i.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if err := f(o); err != nil {
return err
}
}
}
func (i *objectIter) Close() {
i.iter.Close()
}
// isInvalid checks whether an error is an os.PathError with an os.ErrInvalid
// error inside. It also checks for the windows error, which is different from
// os.ErrInvalid.
func isInvalid(err error) bool {
pe, ok := err.(*os.PathError)
if !ok {
return false
}
errstr := pe.Err.Error()
return errstr == errInvalidUnix || errstr == errInvalidWindows
}
// errInvalidWindows is the Windows equivalent to os.ErrInvalid
const errInvalidWindows = "The parameter is incorrect."
var errInvalidUnix = os.ErrInvalid.Error()
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/parser.go
================================================
package packfile
import (
"bytes"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
// ErrReferenceDeltaNotFound is returned when the reference delta is not
// found.
ErrReferenceDeltaNotFound = errors.New("reference delta not found")
// ErrNotSeekableSource is returned when the source for the parser is not
// seekable and a storage was not provided, so it can't be parsed.
ErrNotSeekableSource = errors.New("parser source is not seekable and storage was not provided")
// ErrDeltaNotCached is returned when the delta could not be found in cache.
ErrDeltaNotCached = errors.New("delta could not be found in cache")
)
// Observer interface is implemented by index encoders.
type Observer interface {
// OnHeader is called when a new packfile is opened.
OnHeader(count uint32) error
// OnInflatedObjectHeader is called for each object header read.
OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error
// OnInflatedObjectContent is called for each decoded object.
OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, content []byte) error
// OnFooter is called when decoding is done.
OnFooter(h plumbing.Hash) error
}
// Parser decodes a packfile and calls any observer associated to it. Is used
// to generate indexes.
type Parser struct {
storage storer.EncodedObjectStorer
scanner *Scanner
count uint32
oi []*objectInfo
oiByHash map[plumbing.Hash]*objectInfo
oiByOffset map[int64]*objectInfo
checksum plumbing.Hash
cache *cache.BufferLRU
// delta content by offset, only used if source is not seekable
deltas map[int64][]byte
ob []Observer
}
// NewParser creates a new Parser. The Scanner source must be seekable.
// If it's not, NewParserWithStorage should be used instead.
func NewParser(scanner *Scanner, ob ...Observer) (*Parser, error) {
return NewParserWithStorage(scanner, nil, ob...)
}
// NewParserWithStorage creates a new Parser. The scanner source must either
// be seekable or a storage must be provided.
func NewParserWithStorage(
scanner *Scanner,
storage storer.EncodedObjectStorer,
ob ...Observer,
) (*Parser, error) {
if !scanner.IsSeekable && storage == nil {
return nil, ErrNotSeekableSource
}
var deltas map[int64][]byte
if !scanner.IsSeekable {
deltas = make(map[int64][]byte)
}
return &Parser{
storage: storage,
scanner: scanner,
ob: ob,
count: 0,
cache: cache.NewBufferLRUDefault(),
deltas: deltas,
}, nil
}
func (p *Parser) forEachObserver(f func(o Observer) error) error {
for _, o := range p.ob {
if err := f(o); err != nil {
return err
}
}
return nil
}
func (p *Parser) onHeader(count uint32) error {
return p.forEachObserver(func(o Observer) error {
return o.OnHeader(count)
})
}
func (p *Parser) onInflatedObjectHeader(
t plumbing.ObjectType,
objSize int64,
pos int64,
) error {
return p.forEachObserver(func(o Observer) error {
return o.OnInflatedObjectHeader(t, objSize, pos)
})
}
func (p *Parser) onInflatedObjectContent(
h plumbing.Hash,
pos int64,
crc uint32,
content []byte,
) error {
return p.forEachObserver(func(o Observer) error {
return o.OnInflatedObjectContent(h, pos, crc, content)
})
}
func (p *Parser) onFooter(h plumbing.Hash) error {
return p.forEachObserver(func(o Observer) error {
return o.OnFooter(h)
})
}
// Parse start decoding phase of the packfile.
func (p *Parser) Parse() (plumbing.Hash, error) {
if err := p.init(); err != nil {
return plumbing.ZeroHash, err
}
if err := p.indexObjects(); err != nil {
return plumbing.ZeroHash, err
}
var err error
p.checksum, err = p.scanner.Checksum()
if err != nil && err != io.EOF {
return plumbing.ZeroHash, err
}
if err := p.resolveDeltas(); err != nil {
return plumbing.ZeroHash, err
}
if err := p.onFooter(p.checksum); err != nil {
return plumbing.ZeroHash, err
}
return p.checksum, nil
}
func (p *Parser) init() error {
_, c, err := p.scanner.Header()
if err != nil {
return err
}
if err := p.onHeader(c); err != nil {
return err
}
p.count = c
p.oiByHash = make(map[plumbing.Hash]*objectInfo, p.count)
p.oiByOffset = make(map[int64]*objectInfo, p.count)
p.oi = make([]*objectInfo, p.count)
return nil
}
type objectHeaderWriter func(typ plumbing.ObjectType, sz int64) error
type lazyObjectWriter interface {
// LazyWriter enables an object to be lazily written.
// It returns:
// - w: a writer to receive the object's content.
// - lwh: a func to write the object header.
// - err: any error from the initial writer creation process.
//
// Note that if the object header is not written BEFORE the writer
// is used, this will result in an invalid object.
LazyWriter() (w io.WriteCloser, lwh objectHeaderWriter, err error)
}
func (p *Parser) indexObjects() error {
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
for i := uint32(0); i < p.count; i++ {
oh, err := p.scanner.NextObjectHeader()
if err != nil {
return err
}
delta := false
var ota *objectInfo
switch t := oh.Type; t {
case plumbing.OFSDeltaObject:
delta = true
parent, ok := p.oiByOffset[oh.OffsetReference]
if !ok {
return plumbing.ErrObjectNotFound
}
ota = newDeltaObject(oh.Offset, oh.Length, t, parent)
parent.Children = append(parent.Children, ota)
case plumbing.REFDeltaObject:
delta = true
parent, ok := p.oiByHash[oh.Reference]
if !ok {
// can't find referenced object in this pack file
// this must be a "thin" pack.
parent = &objectInfo{ //Placeholder parent
SHA1: oh.Reference,
ExternalRef: true, // mark as an external reference that must be resolved
Type: plumbing.AnyObject,
DiskType: plumbing.AnyObject,
}
p.oiByHash[oh.Reference] = parent
}
ota = newDeltaObject(oh.Offset, oh.Length, t, parent)
parent.Children = append(parent.Children, ota)
default:
ota = newBaseObject(oh.Offset, oh.Length, t)
}
hasher := plumbing.NewHasher(oh.Type, oh.Length)
writers := []io.Writer{hasher}
var obj *plumbing.MemoryObject
// Lazy writing is only available for non-delta objects.
if p.storage != nil && !delta {
// When a storage is set and supports lazy writing,
// use that instead of creating a memory object.
if low, ok := p.storage.(lazyObjectWriter); ok {
ow, lwh, err := low.LazyWriter()
if err != nil {
return err
}
if err = lwh(oh.Type, oh.Length); err != nil {
return err
}
defer ow.Close()
writers = append(writers, ow)
} else {
obj = new(plumbing.MemoryObject)
obj.SetSize(oh.Length)
obj.SetType(oh.Type)
writers = append(writers, obj)
}
}
if delta && !p.scanner.IsSeekable {
buf.Reset()
buf.Grow(int(oh.Length))
writers = append(writers, buf)
}
mw := io.MultiWriter(writers...)
_, crc, err := p.scanner.NextObject(mw)
if err != nil {
return err
}
// Non delta objects needs to be added into the storage. This
// is only required when lazy writing is not supported.
if obj != nil {
if _, err := p.storage.SetEncodedObject(obj); err != nil {
return err
}
}
ota.Crc32 = crc
ota.Length = oh.Length
if !delta {
sha1 := hasher.Sum()
// Move children of placeholder parent into actual parent, in case this
// was a non-external delta reference.
if placeholder, ok := p.oiByHash[sha1]; ok {
ota.Children = placeholder.Children
for _, c := range ota.Children {
c.Parent = ota
}
}
ota.SHA1 = sha1
p.oiByHash[ota.SHA1] = ota
}
if delta && !p.scanner.IsSeekable {
data := buf.Bytes()
p.deltas[oh.Offset] = make([]byte, len(data))
copy(p.deltas[oh.Offset], data)
}
p.oiByOffset[oh.Offset] = ota
p.oi[i] = ota
}
return nil
}
func (p *Parser) resolveDeltas() error {
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
for _, obj := range p.oi {
buf.Reset()
buf.Grow(int(obj.Length))
err := p.get(obj, buf)
if err != nil {
return err
}
if err := p.onInflatedObjectHeader(obj.Type, obj.Length, obj.Offset); err != nil {
return err
}
if err := p.onInflatedObjectContent(obj.SHA1, obj.Offset, obj.Crc32, nil); err != nil {
return err
}
if !obj.IsDelta() && len(obj.Children) > 0 {
// Dealing with an io.ReaderAt object, means we can
// create it once and reuse across all children.
r := bytes.NewReader(buf.Bytes())
for _, child := range obj.Children {
// Even though we are discarding the output, we still need to read it to
// so that the scanner can advance to the next object, and the SHA1 can be
// calculated.
if err := p.resolveObject(io.Discard, child, r); err != nil {
return err
}
p.resolveExternalRef(child)
}
// Remove the delta from the cache.
if obj.DiskType.IsDelta() && !p.scanner.IsSeekable {
delete(p.deltas, obj.Offset)
}
}
}
return nil
}
func (p *Parser) resolveExternalRef(o *objectInfo) {
if ref, ok := p.oiByHash[o.SHA1]; ok && ref.ExternalRef {
p.oiByHash[o.SHA1] = o
o.Children = ref.Children
for _, c := range o.Children {
c.Parent = o
}
}
}
func (p *Parser) get(o *objectInfo, buf *bytes.Buffer) (err error) {
if !o.ExternalRef { // skip cache check for placeholder parents
b, ok := p.cache.Get(o.Offset)
if ok {
_, err := buf.Write(b)
return err
}
}
// If it's not on the cache and is not a delta we can try to find it in the
// storage, if there's one. External refs must enter here.
if p.storage != nil && !o.Type.IsDelta() {
var e plumbing.EncodedObject
e, err = p.storage.EncodedObject(plumbing.AnyObject, o.SHA1)
if err != nil {
return err
}
o.Type = e.Type()
var r io.ReadCloser
r, err = e.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(r, &err)
_, err = buf.ReadFrom(io.LimitReader(r, e.Size()))
return err
}
if o.ExternalRef {
// we were not able to resolve a ref in a thin pack
return ErrReferenceDeltaNotFound
}
if o.DiskType.IsDelta() {
b := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(b)
buf.Grow(int(o.Length))
err := p.get(o.Parent, b)
if err != nil {
return err
}
err = p.resolveObject(buf, o, bytes.NewReader(b.Bytes()))
if err != nil {
return err
}
} else {
err := p.readData(buf, o)
if err != nil {
return err
}
}
// If the scanner is seekable, caching this data into
// memory by offset seems wasteful.
// There is a trade-off to be considered here in terms
// of execution time vs memory consumption.
//
// TODO: improve seekable execution time, so that we can
// skip this cache.
if len(o.Children) > 0 {
data := make([]byte, buf.Len())
copy(data, buf.Bytes())
p.cache.Put(o.Offset, data)
}
return nil
}
// resolveObject resolves an object from base, using information
// provided by o.
//
// This call has the side-effect of changing field values
// from the object info o:
// - Type: OFSDeltaObject may become the target type (e.g. Blob).
// - Size: The size may be update with the target size.
// - Hash: Zero hashes will be calculated as part of the object
// resolution. Hence why this process can't be avoided even when w
// is an io.Discard.
//
// base must be an io.ReaderAt, which is a requirement from
// patchDeltaStream. The main reason being that reversing an
// delta object may lead to going backs and forths within base,
// which is not supported by io.Reader.
func (p *Parser) resolveObject(
w io.Writer,
o *objectInfo,
base io.ReaderAt,
) error {
if !o.DiskType.IsDelta() {
return nil
}
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
err := p.readData(buf, o)
if err != nil {
return err
}
writers := []io.Writer{w}
var obj *plumbing.MemoryObject
var lwh objectHeaderWriter
if p.storage != nil {
if low, ok := p.storage.(lazyObjectWriter); ok {
ow, wh, err := low.LazyWriter()
if err != nil {
return err
}
lwh = wh
defer ow.Close()
writers = append(writers, ow)
} else {
obj = new(plumbing.MemoryObject)
ow, err := obj.Writer()
if err != nil {
return err
}
writers = append(writers, ow)
}
}
mw := io.MultiWriter(writers...)
err = applyPatchBase(o, base, buf, mw, lwh)
if err != nil {
return err
}
if obj != nil {
obj.SetType(o.Type)
obj.SetSize(o.Size()) // Size here is correct as it was populated by applyPatchBase.
if _, err := p.storage.SetEncodedObject(obj); err != nil {
return err
}
}
return err
}
func (p *Parser) readData(w io.Writer, o *objectInfo) error {
if !p.scanner.IsSeekable && o.DiskType.IsDelta() {
data, ok := p.deltas[o.Offset]
if !ok {
return ErrDeltaNotCached
}
_, err := w.Write(data)
return err
}
if _, err := p.scanner.SeekObjectHeader(o.Offset); err != nil {
return err
}
if _, _, err := p.scanner.NextObject(w); err != nil {
return err
}
return nil
}
// applyPatchBase applies the patch to target.
//
// Note that ota will be updated based on the description in resolveObject.
func applyPatchBase(ota *objectInfo, base io.ReaderAt, delta io.Reader, target io.Writer, wh objectHeaderWriter) error {
if target == nil {
return fmt.Errorf("cannot apply patch against nil target")
}
typ := ota.Type
if ota.SHA1 == plumbing.ZeroHash {
typ = ota.Parent.Type
}
sz, h, err := patchDeltaWriter(target, base, delta, typ, wh)
if err != nil {
return err
}
if ota.SHA1 == plumbing.ZeroHash {
ota.Type = typ
ota.Length = int64(sz)
ota.SHA1 = h
}
return nil
}
func getSHA1(t plumbing.ObjectType, data []byte) (plumbing.Hash, error) {
hasher := plumbing.NewHasher(t, int64(len(data)))
if _, err := hasher.Write(data); err != nil {
return plumbing.ZeroHash, err
}
return hasher.Sum(), nil
}
type objectInfo struct {
Offset int64
Length int64
Type plumbing.ObjectType
DiskType plumbing.ObjectType
ExternalRef bool // indicates this is an external reference in a thin pack file
Crc32 uint32
Parent *objectInfo
Children []*objectInfo
SHA1 plumbing.Hash
}
func newBaseObject(offset, length int64, t plumbing.ObjectType) *objectInfo {
return newDeltaObject(offset, length, t, nil)
}
func newDeltaObject(
offset, length int64,
t plumbing.ObjectType,
parent *objectInfo,
) *objectInfo {
obj := &objectInfo{
Offset: offset,
Length: length,
Type: t,
DiskType: t,
Crc32: 0,
Parent: parent,
}
return obj
}
func (o *objectInfo) IsDelta() bool {
return o.Type.IsDelta()
}
func (o *objectInfo) Size() int64 {
return o.Length
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/patch_delta.go
================================================
package packfile
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"math"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
// See https://github.com/git/git/blob/49fa3dc76179e04b0833542fa52d0f287a4955ac/delta.h
// https://github.com/git/git/blob/c2c5f6b1e479f2c38e0e01345350620944e3527f/patch-delta.c,
// and https://github.com/tarruda/node-git-core/blob/master/src/js/delta.js
// for details about the delta format.
var (
ErrInvalidDelta = errors.New("invalid delta")
ErrDeltaCmd = errors.New("wrong delta command")
)
const (
payload = 0x7f // 0111 1111
continuation = 0x80 // 1000 0000
// maxPatchPreemptionSize defines what is the max size of bytes to be
// premptively made available for a patch operation.
maxPatchPreemptionSize uint = 65536
// minDeltaSize defines the smallest size for a delta.
minDeltaSize = 4
)
type offset struct {
mask byte
shift uint
}
var offsets = []offset{
{mask: 0x01, shift: 0},
{mask: 0x02, shift: 8},
{mask: 0x04, shift: 16},
{mask: 0x08, shift: 24},
}
var sizes = []offset{
{mask: 0x10, shift: 0},
{mask: 0x20, shift: 8},
{mask: 0x40, shift: 16},
}
// ApplyDelta writes to target the result of applying the modification deltas in delta to base.
func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
r, err := base.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(r, &err)
w, err := target.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
buf := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(buf)
_, err = buf.ReadFrom(r)
if err != nil {
return err
}
src := buf.Bytes()
dst := sync.GetBytesBuffer()
defer sync.PutBytesBuffer(dst)
err = patchDelta(dst, src, delta)
if err != nil {
return err
}
target.SetSize(int64(dst.Len()))
b := sync.GetByteSlice()
_, err = io.CopyBuffer(w, dst, *b)
sync.PutByteSlice(b)
return err
}
// PatchDelta returns the result of applying the modification deltas in delta to src.
// An error will be returned if delta is corrupted (ErrInvalidDelta) or an action command
// is not copy from source or copy from delta (ErrDeltaCmd).
func PatchDelta(src, delta []byte) ([]byte, error) {
if len(src) == 0 || len(delta) < minDeltaSize {
return nil, ErrInvalidDelta
}
b := &bytes.Buffer{}
if err := patchDelta(b, src, delta); err != nil {
return nil, err
}
return b.Bytes(), nil
}
func ReaderFromDelta(base plumbing.EncodedObject, deltaRC io.Reader) (io.ReadCloser, error) {
deltaBuf := bufio.NewReaderSize(deltaRC, 1024)
srcSz, err := decodeLEB128ByteReader(deltaBuf)
if err != nil {
if err == io.EOF {
return nil, ErrInvalidDelta
}
return nil, err
}
if srcSz != uint(base.Size()) {
return nil, ErrInvalidDelta
}
targetSz, err := decodeLEB128ByteReader(deltaBuf)
if err != nil {
if err == io.EOF {
return nil, ErrInvalidDelta
}
return nil, err
}
remainingTargetSz := targetSz
dstRd, dstWr := io.Pipe()
go func() {
baseRd, err := base.Reader()
if err != nil {
_ = dstWr.CloseWithError(ErrInvalidDelta)
return
}
defer baseRd.Close()
baseBuf := bufio.NewReader(baseRd)
basePos := uint(0)
for {
cmd, err := deltaBuf.ReadByte()
if err == io.EOF {
_ = dstWr.CloseWithError(ErrInvalidDelta)
return
}
if err != nil {
_ = dstWr.CloseWithError(err)
return
}
switch {
case isCopyFromSrc(cmd):
offset, err := decodeOffsetByteReader(cmd, deltaBuf)
if err != nil {
_ = dstWr.CloseWithError(err)
return
}
sz, err := decodeSizeByteReader(cmd, deltaBuf)
if err != nil {
_ = dstWr.CloseWithError(err)
return
}
if invalidSize(sz, targetSz) ||
invalidOffsetSize(offset, sz, srcSz) {
_ = dstWr.Close()
return
}
discard := offset - basePos
if basePos > offset {
_ = baseRd.Close()
baseRd, err = base.Reader()
if err != nil {
_ = dstWr.CloseWithError(ErrInvalidDelta)
return
}
baseBuf.Reset(baseRd)
discard = offset
}
for discard > math.MaxInt32 {
n, err := baseBuf.Discard(math.MaxInt32)
if err != nil {
_ = dstWr.CloseWithError(err)
return
}
basePos += uint(n)
discard -= uint(n)
}
for discard > 0 {
n, err := baseBuf.Discard(int(discard))
if err != nil {
_ = dstWr.CloseWithError(err)
return
}
basePos += uint(n)
discard -= uint(n)
}
if _, err := io.Copy(dstWr, io.LimitReader(baseBuf, int64(sz))); err != nil {
_ = dstWr.CloseWithError(err)
return
}
remainingTargetSz -= sz
basePos += sz
case isCopyFromDelta(cmd):
sz := uint(cmd) // cmd is the size itself
if invalidSize(sz, targetSz) {
_ = dstWr.CloseWithError(ErrInvalidDelta)
return
}
if _, err := io.Copy(dstWr, io.LimitReader(deltaBuf, int64(sz))); err != nil {
_ = dstWr.CloseWithError(err)
return
}
remainingTargetSz -= sz
default:
_ = dstWr.CloseWithError(ErrDeltaCmd)
return
}
if remainingTargetSz <= 0 {
_ = dstWr.Close()
return
}
}
}()
return dstRd, nil
}
func patchDelta(dst *bytes.Buffer, src, delta []byte) error {
if len(delta) < minCopySize {
return ErrInvalidDelta
}
srcSz, delta := decodeLEB128(delta)
if srcSz != uint(len(src)) {
return ErrInvalidDelta
}
targetSz, delta := decodeLEB128(delta)
remainingTargetSz := targetSz
var cmd byte
growSz := min(targetSz, maxPatchPreemptionSize)
dst.Grow(int(growSz))
for {
if len(delta) == 0 {
return ErrInvalidDelta
}
cmd = delta[0]
delta = delta[1:]
switch {
case isCopyFromSrc(cmd):
var offset, sz uint
var err error
offset, delta, err = decodeOffset(cmd, delta)
if err != nil {
return err
}
sz, delta, err = decodeSize(cmd, delta)
if err != nil {
return err
}
if invalidSize(sz, targetSz) ||
invalidOffsetSize(offset, sz, srcSz) {
break
}
dst.Write(src[offset : offset+sz])
remainingTargetSz -= sz
case isCopyFromDelta(cmd):
sz := uint(cmd) // cmd is the size itself
if invalidSize(sz, targetSz) {
return ErrInvalidDelta
}
if uint(len(delta)) < sz {
return ErrInvalidDelta
}
dst.Write(delta[0:sz])
remainingTargetSz -= sz
delta = delta[sz:]
default:
return ErrDeltaCmd
}
if remainingTargetSz <= 0 {
break
}
}
return nil
}
func patchDeltaWriter(dst io.Writer, base io.ReaderAt, delta io.Reader,
typ plumbing.ObjectType, writeHeader objectHeaderWriter) (uint, plumbing.Hash, error) {
deltaBuf := bufio.NewReaderSize(delta, 1024)
srcSz, err := decodeLEB128ByteReader(deltaBuf)
if err != nil {
if err == io.EOF {
return 0, plumbing.ZeroHash, ErrInvalidDelta
}
return 0, plumbing.ZeroHash, err
}
if r, ok := base.(*bytes.Reader); ok && srcSz != uint(r.Size()) {
return 0, plumbing.ZeroHash, ErrInvalidDelta
}
targetSz, err := decodeLEB128ByteReader(deltaBuf)
if err != nil {
if err == io.EOF {
return 0, plumbing.ZeroHash, ErrInvalidDelta
}
return 0, plumbing.ZeroHash, err
}
// If header still needs to be written, caller will provide
// a LazyObjectWriterHeader. This seems to be the case when
// dealing with thin-packs.
if writeHeader != nil {
err = writeHeader(typ, int64(targetSz))
if err != nil {
return 0, plumbing.ZeroHash, fmt.Errorf("could not lazy write header: %w", err)
}
}
remainingTargetSz := targetSz
hasher := plumbing.NewHasher(typ, int64(targetSz))
mw := io.MultiWriter(dst, hasher)
bufp := sync.GetByteSlice()
defer sync.PutByteSlice(bufp)
sr := io.NewSectionReader(base, int64(0), int64(srcSz))
// Keep both the io.LimitedReader types, so we can reset N.
baselr := io.LimitReader(sr, 0).(*io.LimitedReader)
deltalr := io.LimitReader(deltaBuf, 0).(*io.LimitedReader)
for {
buf := *bufp
cmd, err := deltaBuf.ReadByte()
if err == io.EOF {
return 0, plumbing.ZeroHash, ErrInvalidDelta
}
if err != nil {
return 0, plumbing.ZeroHash, err
}
if isCopyFromSrc(cmd) {
offset, err := decodeOffsetByteReader(cmd, deltaBuf)
if err != nil {
return 0, plumbing.ZeroHash, err
}
sz, err := decodeSizeByteReader(cmd, deltaBuf)
if err != nil {
return 0, plumbing.ZeroHash, err
}
if invalidSize(sz, targetSz) ||
invalidOffsetSize(offset, sz, srcSz) {
return 0, plumbing.ZeroHash, err
}
if _, err := sr.Seek(int64(offset), io.SeekStart); err != nil {
return 0, plumbing.ZeroHash, err
}
baselr.N = int64(sz)
if _, err := io.CopyBuffer(mw, baselr, buf); err != nil {
return 0, plumbing.ZeroHash, err
}
remainingTargetSz -= sz
} else if isCopyFromDelta(cmd) {
sz := uint(cmd) // cmd is the size itself
if invalidSize(sz, targetSz) {
return 0, plumbing.ZeroHash, ErrInvalidDelta
}
deltalr.N = int64(sz)
if _, err := io.CopyBuffer(mw, deltalr, buf); err != nil {
return 0, plumbing.ZeroHash, err
}
remainingTargetSz -= sz
} else {
return 0, plumbing.ZeroHash, err
}
if remainingTargetSz <= 0 {
break
}
}
return targetSz, hasher.Sum(), nil
}
// Decodes a number encoded as an unsigned LEB128 at the start of some
// binary data and returns the decoded number and the rest of the
// stream.
//
// This must be called twice on the delta data buffer, first to get the
// expected source buffer size, and again to get the target buffer size.
func decodeLEB128(input []byte) (uint, []byte) {
if len(input) == 0 {
return 0, input
}
var num, sz uint
var b byte
for {
b = input[sz]
num |= (uint(b) & payload) << (sz * 7) // concats 7 bits chunks
sz++
if uint(b)&continuation == 0 || sz == uint(len(input)) {
break
}
}
return num, input[sz:]
}
func decodeLEB128ByteReader(input io.ByteReader) (uint, error) {
var num, sz uint
for {
b, err := input.ReadByte()
if err != nil {
return 0, err
}
num |= (uint(b) & payload) << (sz * 7) // concats 7 bits chunks
sz++
if uint(b)&continuation == 0 {
break
}
}
return num, nil
}
func isCopyFromSrc(cmd byte) bool {
return (cmd & continuation) != 0
}
func isCopyFromDelta(cmd byte) bool {
return (cmd&continuation) == 0 && cmd != 0
}
func decodeOffsetByteReader(cmd byte, delta io.ByteReader) (uint, error) {
var offset uint
for _, o := range offsets {
if (cmd & o.mask) != 0 {
next, err := delta.ReadByte()
if err != nil {
return 0, err
}
offset |= uint(next) << o.shift
}
}
return offset, nil
}
func decodeOffset(cmd byte, delta []byte) (uint, []byte, error) {
var offset uint
for _, o := range offsets {
if (cmd & o.mask) != 0 {
if len(delta) == 0 {
return 0, nil, ErrInvalidDelta
}
offset |= uint(delta[0]) << o.shift
delta = delta[1:]
}
}
return offset, delta, nil
}
func decodeSizeByteReader(cmd byte, delta io.ByteReader) (uint, error) {
var sz uint
for _, s := range sizes {
if (cmd & s.mask) != 0 {
next, err := delta.ReadByte()
if err != nil {
return 0, err
}
sz |= uint(next) << s.shift
}
}
if sz == 0 {
sz = maxCopySize
}
return sz, nil
}
func decodeSize(cmd byte, delta []byte) (uint, []byte, error) {
var sz uint
for _, s := range sizes {
if (cmd & s.mask) != 0 {
if len(delta) == 0 {
return 0, nil, ErrInvalidDelta
}
sz |= uint(delta[0]) << s.shift
delta = delta[1:]
}
}
if sz == 0 {
sz = maxCopySize
}
return sz, delta, nil
}
func invalidSize(sz, targetSz uint) bool {
return sz > targetSz
}
func invalidOffsetSize(offset, sz, srcSz uint) bool {
return sumOverflows(offset, sz) ||
offset+sz > srcSz
}
func sumOverflows(a, b uint) bool {
return a+b < a
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/packfile/scanner.go
================================================
package packfile
import (
"bufio"
"bytes"
"fmt"
"hash"
"hash/crc32"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/binary"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
// ErrEmptyPackfile is returned by ReadHeader when no data is found in the packfile
ErrEmptyPackfile = NewError("empty packfile")
// ErrBadSignature is returned by ReadHeader when the signature in the packfile is incorrect.
ErrBadSignature = NewError("malformed pack file signature")
// ErrUnsupportedVersion is returned by ReadHeader when the packfile version is
// different than VersionSupported.
ErrUnsupportedVersion = NewError("unsupported packfile version")
// ErrSeekNotSupported returned if seek is not support
ErrSeekNotSupported = NewError("not seek support")
)
// ObjectHeader contains the information related to the object, this information
// is collected from the previous bytes to the content of the object.
type ObjectHeader struct {
Type plumbing.ObjectType
Offset int64
Length int64
Reference plumbing.Hash
OffsetReference int64
}
type Scanner struct {
r *scannerReader
crc hash.Hash32
// pendingObject is used to detect if an object has been read, or still
// is waiting to be read
pendingObject *ObjectHeader
version, objects uint32
// lsSeekable says if this scanner can do Seek or not, to have a Scanner
// seekable a r implementing io.Seeker is required
IsSeekable bool
}
// NewScanner returns a new Scanner based on a reader, if the given reader
// implements io.ReadSeeker the Scanner will be also Seekable
func NewScanner(r io.Reader) *Scanner {
_, ok := r.(io.ReadSeeker)
crc := crc32.NewIEEE()
return &Scanner{
r: newScannerReader(r, crc),
crc: crc,
IsSeekable: ok,
}
}
func (s *Scanner) Reset(r io.Reader) {
_, ok := r.(io.ReadSeeker)
s.r.Reset(r)
s.crc.Reset()
s.IsSeekable = ok
s.pendingObject = nil
s.version = 0
s.objects = 0
}
// Header reads the whole packfile header (signature, version and object count).
// It returns the version and the object count and performs checks on the
// validity of the signature and the version fields.
func (s *Scanner) Header() (version, objects uint32, err error) {
if s.version != 0 {
return s.version, s.objects, nil
}
sig, err := s.readSignature()
if err != nil {
if err == io.EOF {
err = ErrEmptyPackfile
}
return
}
if !s.isValidSignature(sig) {
err = ErrBadSignature
return
}
version, err = s.readVersion()
s.version = version
if err != nil {
return
}
if !s.isSupportedVersion(version) {
err = ErrUnsupportedVersion.AddDetails("%d", version)
return
}
objects, err = s.readCount()
s.objects = objects
return
}
// readSignature reads a returns the signature field in the packfile.
func (s *Scanner) readSignature() ([]byte, error) {
var sig = make([]byte, 4)
if _, err := io.ReadFull(s.r, sig); err != nil {
return []byte{}, err
}
return sig, nil
}
// isValidSignature returns if sig is a valid packfile signature.
func (s *Scanner) isValidSignature(sig []byte) bool {
return bytes.Equal(sig, signature)
}
// readVersion reads and returns the version field of a packfile.
func (s *Scanner) readVersion() (uint32, error) {
return binary.ReadUint32(s.r)
}
// isSupportedVersion returns whether version v is supported by the parser.
// The current supported version is VersionSupported, defined above.
func (s *Scanner) isSupportedVersion(v uint32) bool {
return v == VersionSupported
}
// readCount reads and returns the count of objects field of a packfile.
func (s *Scanner) readCount() (uint32, error) {
return binary.ReadUint32(s.r)
}
// SeekObjectHeader seeks to specified offset and returns the ObjectHeader
// for the next object in the reader
func (s *Scanner) SeekObjectHeader(offset int64) (*ObjectHeader, error) {
// if seeking we assume that you are not interested in the header
if s.version == 0 {
s.version = VersionSupported
}
if _, err := s.r.Seek(offset, io.SeekStart); err != nil {
return nil, err
}
h, err := s.nextObjectHeader()
if err != nil {
return nil, err
}
h.Offset = offset
return h, nil
}
// NextObjectHeader returns the ObjectHeader for the next object in the reader
func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) {
if err := s.doPending(); err != nil {
return nil, err
}
offset, err := s.r.Seek(0, io.SeekCurrent)
if err != nil {
return nil, err
}
h, err := s.nextObjectHeader()
if err != nil {
return nil, err
}
h.Offset = offset
return h, nil
}
// nextObjectHeader returns the ObjectHeader for the next object in the reader
// without the Offset field
func (s *Scanner) nextObjectHeader() (*ObjectHeader, error) {
s.r.Flush()
s.crc.Reset()
h := &ObjectHeader{}
s.pendingObject = h
var err error
h.Offset, err = s.r.Seek(0, io.SeekCurrent)
if err != nil {
return nil, err
}
h.Type, h.Length, err = s.readObjectTypeAndLength()
if err != nil {
return nil, err
}
switch h.Type {
case plumbing.OFSDeltaObject:
no, err := binary.ReadVariableWidthInt(s.r)
if err != nil {
return nil, err
}
h.OffsetReference = h.Offset - no
case plumbing.REFDeltaObject:
var err error
h.Reference, err = binary.ReadHash(s.r)
if err != nil {
return nil, err
}
}
return h, nil
}
func (s *Scanner) doPending() error {
if s.version == 0 {
var err error
s.version, s.objects, err = s.Header()
if err != nil {
return err
}
}
return s.discardObjectIfNeeded()
}
func (s *Scanner) discardObjectIfNeeded() error {
if s.pendingObject == nil {
return nil
}
h := s.pendingObject
n, _, err := s.NextObject(io.Discard)
if err != nil {
return err
}
if n != h.Length {
return fmt.Errorf(
"error discarding object, discarded %d, expected %d",
n, h.Length,
)
}
return nil
}
// ReadObjectTypeAndLength reads and returns the object type and the
// length field from an object entry in a packfile.
func (s *Scanner) readObjectTypeAndLength() (plumbing.ObjectType, int64, error) {
t, c, err := s.readType()
if err != nil {
return t, 0, err
}
l, err := s.readLength(c)
return t, l, err
}
func (s *Scanner) readType() (plumbing.ObjectType, byte, error) {
var c byte
var err error
if c, err = s.r.ReadByte(); err != nil {
return plumbing.ObjectType(0), 0, err
}
typ := parseType(c)
return typ, c, nil
}
func parseType(b byte) plumbing.ObjectType {
return plumbing.ObjectType((b & maskType) >> firstLengthBits)
}
// the length is codified in the last 4 bits of the first byte and in
// the last 7 bits of subsequent bytes. Last byte has a 0 MSB.
func (s *Scanner) readLength(first byte) (int64, error) {
length := int64(first & maskFirstLength)
c := first
shift := firstLengthBits
var err error
for c&maskContinue > 0 {
if c, err = s.r.ReadByte(); err != nil {
return 0, err
}
length += int64(c&maskLength) << shift
shift += lengthBits
}
return length, nil
}
// NextObject writes the content of the next object into the reader, returns
// the number of bytes written, the CRC32 of the content and an error, if any
func (s *Scanner) NextObject(w io.Writer) (written int64, crc32 uint32, err error) {
s.pendingObject = nil
written, err = s.copyObject(w)
s.r.Flush()
crc32 = s.crc.Sum32()
s.crc.Reset()
return
}
// ReadObject returns a reader for the object content and an error
func (s *Scanner) ReadObject() (io.ReadCloser, error) {
s.pendingObject = nil
zr, err := sync.GetZlibReader(s.r)
if err != nil {
return nil, fmt.Errorf("zlib reset error: %s", err)
}
return ioutil.NewReadCloserWithCloser(zr.Reader, func() error {
sync.PutZlibReader(zr)
return nil
}), nil
}
// ReadRegularObject reads and write a non-deltified object
// from it zlib stream in an object entry in the packfile.
func (s *Scanner) copyObject(w io.Writer) (n int64, err error) {
zr, err := sync.GetZlibReader(s.r)
defer sync.PutZlibReader(zr)
if err != nil {
return 0, fmt.Errorf("zlib reset error: %s", err)
}
defer ioutil.CheckClose(zr.Reader, &err)
buf := sync.GetByteSlice()
n, err = io.CopyBuffer(w, zr.Reader, *buf)
sync.PutByteSlice(buf)
return
}
// SeekFromStart sets a new offset from start, returns the old position before
// the change.
func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) {
// if seeking we assume that you are not interested in the header
if s.version == 0 {
s.version = VersionSupported
}
previous, err = s.r.Seek(0, io.SeekCurrent)
if err != nil {
return -1, err
}
_, err = s.r.Seek(offset, io.SeekStart)
return previous, err
}
// Checksum returns the checksum of the packfile
func (s *Scanner) Checksum() (plumbing.Hash, error) {
err := s.discardObjectIfNeeded()
if err != nil {
return plumbing.ZeroHash, err
}
return binary.ReadHash(s.r)
}
// Close reads the reader until io.EOF
func (s *Scanner) Close() error {
buf := sync.GetByteSlice()
_, err := io.CopyBuffer(io.Discard, s.r, *buf)
sync.PutByteSlice(buf)
return err
}
// Flush is a no-op (deprecated)
func (s *Scanner) Flush() error {
return nil
}
// scannerReader has the following characteristics:
// - Provides an io.SeekReader impl for bufio.Reader, when the underlying
// reader supports it.
// - Keeps track of the current read position, for when the underlying reader
// isn't an io.SeekReader, but we still want to know the current offset.
// - Writes to the hash writer what it reads, with the aid of a smaller buffer.
// The buffer helps avoid a performance penalty for performing small writes
// to the crc32 hash writer.
type scannerReader struct {
reader io.Reader
crc io.Writer
rbuf *bufio.Reader
wbuf *bufio.Writer
offset int64
}
func newScannerReader(r io.Reader, h io.Writer) *scannerReader {
sr := &scannerReader{
rbuf: bufio.NewReader(nil),
wbuf: bufio.NewWriterSize(nil, 64),
crc: h,
}
sr.Reset(r)
return sr
}
func (r *scannerReader) Reset(reader io.Reader) {
r.reader = reader
r.rbuf.Reset(r.reader)
r.wbuf.Reset(r.crc)
r.offset = 0
if seeker, ok := r.reader.(io.ReadSeeker); ok {
r.offset, _ = seeker.Seek(0, io.SeekCurrent)
}
}
func (r *scannerReader) Read(p []byte) (n int, err error) {
n, err = r.rbuf.Read(p)
r.offset += int64(n)
if _, err := r.wbuf.Write(p[:n]); err != nil {
return n, err
}
return
}
func (r *scannerReader) ReadByte() (b byte, err error) {
b, err = r.rbuf.ReadByte()
if err == nil {
r.offset++
return b, r.wbuf.WriteByte(b)
}
return
}
func (r *scannerReader) Flush() error {
return r.wbuf.Flush()
}
// Seek seeks to a location. If the underlying reader is not an io.ReadSeeker,
// then only whence=io.SeekCurrent is supported, any other operation fails.
func (r *scannerReader) Seek(offset int64, whence int) (int64, error) {
var err error
if seeker, ok := r.reader.(io.ReadSeeker); !ok {
if whence != io.SeekCurrent || offset != 0 {
return -1, ErrSeekNotSupported
}
} else {
if whence == io.SeekCurrent && offset == 0 {
return r.offset, nil
}
r.offset, err = seeker.Seek(offset, whence)
r.rbuf.Reset(r.reader)
}
return r.offset, err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/encoder.go
================================================
// Package pktline implements reading payloads form pkt-lines and encoding
// pkt-lines from payloads.
package pktline
import (
"bytes"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/utils/trace"
)
// An Encoder writes pkt-lines to an output stream.
type Encoder struct {
w io.Writer
}
const (
// MaxPayloadSize is the maximum payload size of a pkt-line in bytes.
MaxPayloadSize = 65516
// For compatibility with canonical Git implementation, accept longer pkt-lines
OversizePayloadMax = 65520
)
var (
// FlushPkt are the contents of a flush-pkt pkt-line.
FlushPkt = []byte{'0', '0', '0', '0'}
// Flush is the payload to use with the Encode method to encode a flush-pkt.
Flush = []byte{}
// FlushString is the payload to use with the EncodeString method to encode a flush-pkt.
FlushString = ""
// ErrPayloadTooLong is returned by the Encode methods when any of the
// provided payloads is bigger than MaxPayloadSize.
ErrPayloadTooLong = errors.New("payload is too long")
)
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
w: w,
}
}
// Flush encodes a flush-pkt to the output stream.
func (e *Encoder) Flush() error {
defer trace.Packet.Print("packet: > 0000")
_, err := e.w.Write(FlushPkt)
return err
}
// Encode encodes a pkt-line with the payload specified and write it to
// the output stream. If several payloads are specified, each of them
// will get streamed in their own pkt-lines.
func (e *Encoder) Encode(payloads ...[]byte) error {
for _, p := range payloads {
if err := e.encodeLine(p); err != nil {
return err
}
}
return nil
}
func (e *Encoder) encodeLine(p []byte) error {
if len(p) > MaxPayloadSize {
return ErrPayloadTooLong
}
if bytes.Equal(p, Flush) {
return e.Flush()
}
n := len(p) + 4
defer trace.Packet.Printf("packet: > %04x %s", n, p)
if _, err := e.w.Write(asciiHex16(n)); err != nil {
return err
}
_, err := e.w.Write(p)
return err
}
// Returns the hexadecimal ascii representation of the 16 less
// significant bits of n. The length of the returned slice will always
// be 4. Example: if n is 1234 (0x4d2), the return value will be
// []byte{'0', '4', 'd', '2'}.
func asciiHex16(n int) []byte {
var ret [4]byte
ret[0] = byteToASCIIHex(byte(n & 0xf000 >> 12))
ret[1] = byteToASCIIHex(byte(n & 0x0f00 >> 8))
ret[2] = byteToASCIIHex(byte(n & 0x00f0 >> 4))
ret[3] = byteToASCIIHex(byte(n & 0x000f))
return ret[:]
}
// turns a byte into its hexadecimal ascii representation. Example:
// from 11 (0xb) to 'b'.
func byteToASCIIHex(n byte) byte {
if n < 10 {
return '0' + n
}
return 'a' - 10 + n
}
// EncodeString works similarly as Encode but payloads are specified as strings.
func (e *Encoder) EncodeString(payloads ...string) error {
for _, p := range payloads {
if err := e.Encode([]byte(p)); err != nil {
return err
}
}
return nil
}
// Encodef encodes a single pkt-line with the payload formatted as
// the format specifier. The rest of the arguments will be used in
// the format string.
func (e *Encoder) Encodef(format string, a ...interface{}) error {
return e.EncodeString(
fmt.Sprintf(format, a...),
)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/error.go
================================================
package pktline
import (
"bytes"
"errors"
"io"
"strings"
)
var (
// ErrInvalidErrorLine is returned by Decode when the packet line is not an
// error line.
ErrInvalidErrorLine = errors.New("expected an error-line")
errPrefix = []byte("ERR ")
)
// ErrorLine is a packet line that contains an error message.
// Once this packet is sent by client or server, the data transfer process is
// terminated.
// See https://git-scm.com/docs/pack-protocol#_pkt_line_format
type ErrorLine struct {
Text string
}
// Error implements the error interface.
func (e *ErrorLine) Error() string {
return e.Text
}
// Encode encodes the ErrorLine into a packet line.
func (e *ErrorLine) Encode(w io.Writer) error {
p := NewEncoder(w)
return p.Encodef("%s%s\n", string(errPrefix), e.Text)
}
// Decode decodes a packet line into an ErrorLine.
func (e *ErrorLine) Decode(r io.Reader) error {
s := NewScanner(r)
if !s.Scan() {
return s.Err()
}
line := s.Bytes()
if !bytes.HasPrefix(line, errPrefix) {
return ErrInvalidErrorLine
}
e.Text = strings.TrimSpace(string(line[4:]))
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/format/pktline/scanner.go
================================================
package pktline
import (
"bytes"
"errors"
"io"
"strings"
"github.com/go-git/go-git/v5/utils/trace"
)
const (
lenSize = 4
)
// ErrInvalidPktLen is returned by Err() when an invalid pkt-len is found.
var ErrInvalidPktLen = errors.New("invalid pkt-len found")
// Scanner provides a convenient interface for reading the payloads of a
// series of pkt-lines. It takes an io.Reader providing the source,
// which then can be tokenized through repeated calls to the Scan
// method.
//
// After each Scan call, the Bytes method will return the payload of the
// corresponding pkt-line on a shared buffer, which will be 65516 bytes
// or smaller. Flush pkt-lines are represented by empty byte slices.
//
// Scanning stops at EOF or the first I/O error.
type Scanner struct {
r io.Reader // The reader provided by the client
err error // Sticky error
payload []byte // Last pkt-payload
len [lenSize]byte // Last pkt-len
}
// NewScanner returns a new Scanner to read from r.
func NewScanner(r io.Reader) *Scanner {
return &Scanner{
r: r,
}
}
// Err returns the first error encountered by the Scanner.
func (s *Scanner) Err() error {
return s.err
}
// Scan advances the Scanner to the next pkt-line, whose payload will
// then be available through the Bytes method. Scanning stops at EOF
// or the first I/O error. After Scan returns false, the Err method
// will return any error that occurred during scanning, except that if
// it was io.EOF, Err will return nil.
func (s *Scanner) Scan() bool {
var l int
l, s.err = s.readPayloadLen()
if s.err == io.EOF {
s.err = nil
return false
}
if s.err != nil {
return false
}
if cap(s.payload) < l {
s.payload = make([]byte, 0, l)
}
if _, s.err = io.ReadFull(s.r, s.payload[:l]); s.err != nil {
return false
}
s.payload = s.payload[:l]
trace.Packet.Printf("packet: < %04x %s", l, s.payload)
if bytes.HasPrefix(s.payload, errPrefix) {
s.err = &ErrorLine{
Text: strings.TrimSpace(string(s.payload[4:])),
}
return false
}
return true
}
// Bytes returns the most recent payload generated by a call to Scan.
// The underlying array may point to data that will be overwritten by a
// subsequent call to Scan. It does no allocation.
func (s *Scanner) Bytes() []byte {
return s.payload
}
// Method readPayloadLen returns the payload length by reading the
// pkt-len and subtracting the pkt-len size.
func (s *Scanner) readPayloadLen() (int, error) {
if _, err := io.ReadFull(s.r, s.len[:]); err != nil {
if err == io.ErrUnexpectedEOF {
return 0, ErrInvalidPktLen
}
return 0, err
}
n, err := hexDecode(s.len)
if err != nil {
return 0, err
}
switch {
case n == 0:
return 0, nil
case n <= lenSize:
return 0, ErrInvalidPktLen
case n > OversizePayloadMax+lenSize:
return 0, ErrInvalidPktLen
default:
return n - lenSize, nil
}
}
// Turns the hexadecimal representation of a number in a byte slice into
// a number. This function substitute strconv.ParseUint(string(buf), 16,
// 16) and/or hex.Decode, to avoid generating new strings, thus helping the
// GC.
func hexDecode(buf [lenSize]byte) (int, error) {
var ret int
for i := 0; i < lenSize; i++ {
n, err := asciiHexToByte(buf[i])
if err != nil {
return 0, ErrInvalidPktLen
}
ret = 16*ret + int(n)
}
return ret, nil
}
// turns the hexadecimal ascii representation of a byte into its
// numerical value. Example: from 'b' to 11 (0xb).
func asciiHexToByte(b byte) (byte, error) {
switch {
case b >= '0' && b <= '9':
return b - '0', nil
case b >= 'a' && b <= 'f':
return b - 'a' + 10, nil
case b >= 'A' && b <= 'F':
return b - 'A' + 10, nil
default:
return 0, ErrInvalidPktLen
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/hash/hash.go
================================================
// package hash provides a way for managing the
// underlying hash implementations used across go-git.
package hash
import (
"crypto"
"fmt"
"hash"
"github.com/pjbgf/sha1cd"
)
// algos is a map of hash algorithms.
var algos = map[crypto.Hash]func() hash.Hash{}
func init() {
reset()
}
// reset resets the default algos value. Can be used after running tests
// that registers new algorithms to avoid side effects.
func reset() {
algos[crypto.SHA1] = sha1cd.New
algos[crypto.SHA256] = crypto.SHA256.New
}
// RegisterHash allows for the hash algorithm used to be overridden.
// This ensures the hash selection for go-git must be explicit, when
// overriding the default value.
func RegisterHash(h crypto.Hash, f func() hash.Hash) error {
if f == nil {
return fmt.Errorf("cannot register hash: f is nil")
}
switch h {
case crypto.SHA1:
algos[h] = f
case crypto.SHA256:
algos[h] = f
default:
return fmt.Errorf("unsupported hash function: %v", h)
}
return nil
}
// Hash is the same as hash.Hash. This allows consumers
// to not having to import this package alongside "hash".
type Hash interface {
hash.Hash
}
// New returns a new Hash for the given hash function.
// It panics if the hash function is not registered.
func New(h crypto.Hash) Hash {
hh, ok := algos[h]
if !ok {
panic(fmt.Sprintf("hash algorithm not registered: %v", h))
}
return hh()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/hash/hash_sha1.go
================================================
//go:build !sha256
// +build !sha256
package hash
import "crypto"
const (
// CryptoType defines what hash algorithm is being used.
CryptoType = crypto.SHA1
// Size defines the amount of bytes the hash yields.
Size = 20
// HexSize defines the strings size of the hash when represented in hexadecimal.
HexSize = 40
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/hash/hash_sha256.go
================================================
//go:build sha256
// +build sha256
package hash
import "crypto"
const (
// CryptoType defines what hash algorithm is being used.
CryptoType = crypto.SHA256
// Size defines the amount of bytes the hash yields.
Size = 32
// HexSize defines the strings size of the hash when represented in hexadecimal.
HexSize = 64
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/hash.go
================================================
package plumbing
import (
"bytes"
"encoding/hex"
"sort"
"strconv"
"github.com/go-git/go-git/v5/plumbing/hash"
)
// Hash SHA1 hashed content
type Hash [hash.Size]byte
// ZeroHash is Hash with value zero
var ZeroHash Hash
// ComputeHash compute the hash for a given ObjectType and content
func ComputeHash(t ObjectType, content []byte) Hash {
h := NewHasher(t, int64(len(content)))
h.Write(content)
return h.Sum()
}
// NewHash return a new Hash from a hexadecimal hash representation
func NewHash(s string) Hash {
b, _ := hex.DecodeString(s)
var h Hash
copy(h[:], b)
return h
}
func (h Hash) IsZero() bool {
var empty Hash
return h == empty
}
func (h Hash) String() string {
return hex.EncodeToString(h[:])
}
type Hasher struct {
hash.Hash
}
func NewHasher(t ObjectType, size int64) Hasher {
h := Hasher{hash.New(hash.CryptoType)}
h.Write(t.Bytes())
h.Write([]byte(" "))
h.Write([]byte(strconv.FormatInt(size, 10)))
h.Write([]byte{0})
return h
}
func (h Hasher) Sum() (hash Hash) {
copy(hash[:], h.Hash.Sum(nil))
return
}
// HashesSort sorts a slice of Hashes in increasing order.
func HashesSort(a []Hash) {
sort.Sort(HashSlice(a))
}
// HashSlice attaches the methods of sort.Interface to []Hash, sorting in
// increasing order.
type HashSlice []Hash
func (p HashSlice) Len() int { return len(p) }
func (p HashSlice) Less(i, j int) bool { return bytes.Compare(p[i][:], p[j][:]) < 0 }
func (p HashSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
// IsHash returns true if the given string is a valid hash.
func IsHash(s string) bool {
switch len(s) {
case hash.HexSize:
_, err := hex.DecodeString(s)
return err == nil
default:
return false
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/memory.go
================================================
package plumbing
import (
"bytes"
"io"
)
// MemoryObject on memory Object implementation
type MemoryObject struct {
t ObjectType
h Hash
cont []byte
sz int64
}
// Hash returns the object Hash, the hash is calculated on-the-fly the first
// time it's called, in all subsequent calls the same Hash is returned even
// if the type or the content have changed. The Hash is only generated if the
// size of the content is exactly the object size.
func (o *MemoryObject) Hash() Hash {
if o.h == ZeroHash && int64(len(o.cont)) == o.sz {
o.h = ComputeHash(o.t, o.cont)
}
return o.h
}
// Type returns the ObjectType
func (o *MemoryObject) Type() ObjectType { return o.t }
// SetType sets the ObjectType
func (o *MemoryObject) SetType(t ObjectType) { o.t = t }
// Size returns the size of the object
func (o *MemoryObject) Size() int64 { return o.sz }
// SetSize set the object size, a content of the given size should be written
// afterwards
func (o *MemoryObject) SetSize(s int64) { o.sz = s }
// Reader returns an io.ReadCloser used to read the object's content.
//
// For a MemoryObject, this reader is seekable.
func (o *MemoryObject) Reader() (io.ReadCloser, error) {
return nopCloser{bytes.NewReader(o.cont)}, nil
}
// Writer returns a ObjectWriter used to write the object's content.
func (o *MemoryObject) Writer() (io.WriteCloser, error) {
return o, nil
}
func (o *MemoryObject) Write(p []byte) (n int, err error) {
o.cont = append(o.cont, p...)
o.sz = int64(len(o.cont))
return len(p), nil
}
// Close releases any resources consumed by the object when it is acting as a
// ObjectWriter.
func (o *MemoryObject) Close() error { return nil }
// nopCloser exposes the extra methods of bytes.Reader while nopping Close().
//
// This allows clients to attempt seeking in a cached Blob's Reader.
type nopCloser struct {
*bytes.Reader
}
// Close does nothing.
func (nc nopCloser) Close() error { return nil }
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/blob.go
================================================
package object
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// Blob is used to store arbitrary data - it is generally a file.
type Blob struct {
// Hash of the blob.
Hash plumbing.Hash
// Size of the (uncompressed) blob.
Size int64
obj plumbing.EncodedObject
}
// GetBlob gets a blob from an object storer and decodes it.
func GetBlob(s storer.EncodedObjectStorer, h plumbing.Hash) (*Blob, error) {
o, err := s.EncodedObject(plumbing.BlobObject, h)
if err != nil {
return nil, err
}
return DecodeBlob(o)
}
// DecodeObject decodes an encoded object into a *Blob.
func DecodeBlob(o plumbing.EncodedObject) (*Blob, error) {
b := &Blob{}
if err := b.Decode(o); err != nil {
return nil, err
}
return b, nil
}
// ID returns the object ID of the blob. The returned value will always match
// the current value of Blob.Hash.
//
// ID is present to fulfill the Object interface.
func (b *Blob) ID() plumbing.Hash {
return b.Hash
}
// Type returns the type of object. It always returns plumbing.BlobObject.
//
// Type is present to fulfill the Object interface.
func (b *Blob) Type() plumbing.ObjectType {
return plumbing.BlobObject
}
// Decode transforms a plumbing.EncodedObject into a Blob struct.
func (b *Blob) Decode(o plumbing.EncodedObject) error {
if o.Type() != plumbing.BlobObject {
return ErrUnsupportedObject
}
b.Hash = o.Hash()
b.Size = o.Size()
b.obj = o
return nil
}
// Encode transforms a Blob into a plumbing.EncodedObject.
func (b *Blob) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.BlobObject)
w, err := o.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
r, err := b.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(r, &err)
_, err = io.Copy(w, r)
return err
}
// Reader returns a reader allow the access to the content of the blob
func (b *Blob) Reader() (io.ReadCloser, error) {
return b.obj.Reader()
}
// BlobIter provides an iterator for a set of blobs.
type BlobIter struct {
storer.EncodedObjectIter
s storer.EncodedObjectStorer
}
// NewBlobIter takes a storer.EncodedObjectStorer and a
// storer.EncodedObjectIter and returns a *BlobIter that iterates over all
// blobs contained in the storer.EncodedObjectIter.
//
// Any non-blob object returned by the storer.EncodedObjectIter is skipped.
func NewBlobIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *BlobIter {
return &BlobIter{iter, s}
}
// Next moves the iterator to the next blob and returns a pointer to it. If
// there are no more blobs, it returns io.EOF.
func (iter *BlobIter) Next() (*Blob, error) {
for {
obj, err := iter.EncodedObjectIter.Next()
if err != nil {
return nil, err
}
if obj.Type() != plumbing.BlobObject {
continue
}
return DecodeBlob(obj)
}
}
// ForEach call the cb function for each blob contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *BlobIter) ForEach(cb func(*Blob) error) error {
return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
if obj.Type() != plumbing.BlobObject {
return nil
}
b, err := DecodeBlob(obj)
if err != nil {
return err
}
return cb(b)
})
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/change.go
================================================
package object
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/go-git/go-git/v5/utils/merkletrie"
)
// Change values represent a detected change between two git trees. For
// modifications, From is the original status of the node and To is its
// final status. For insertions, From is the zero value and for
// deletions To is the zero value.
type Change struct {
From ChangeEntry
To ChangeEntry
}
var empty ChangeEntry
// Action returns the kind of action represented by the change, an
// insertion, a deletion or a modification.
func (c *Change) Action() (merkletrie.Action, error) {
if c.From == empty && c.To == empty {
return merkletrie.Action(0),
fmt.Errorf("malformed change: empty from and to")
}
if c.From == empty {
return merkletrie.Insert, nil
}
if c.To == empty {
return merkletrie.Delete, nil
}
return merkletrie.Modify, nil
}
// Files returns the files before and after a change.
// For insertions from will be nil. For deletions to will be nil.
func (c *Change) Files() (from, to *File, err error) {
action, err := c.Action()
if err != nil {
return
}
if action == merkletrie.Insert || action == merkletrie.Modify {
to, err = c.To.Tree.TreeEntryFile(&c.To.TreeEntry)
if !c.To.TreeEntry.Mode.IsFile() {
return nil, nil, nil
}
if err != nil {
return
}
}
if action == merkletrie.Delete || action == merkletrie.Modify {
from, err = c.From.Tree.TreeEntryFile(&c.From.TreeEntry)
if !c.From.TreeEntry.Mode.IsFile() {
return nil, nil, nil
}
if err != nil {
return
}
}
return
}
func (c *Change) String() string {
action, err := c.Action()
if err != nil {
return "malformed change"
}
return fmt.Sprintf("", action, c.name())
}
// Patch returns a Patch with all the file changes in chunks. This
// representation can be used to create several diff outputs.
func (c *Change) Patch() (*Patch, error) {
return c.PatchContext(context.Background())
}
// Patch returns a Patch with all the file changes in chunks. This
// representation can be used to create several diff outputs.
// If context expires, an non-nil error will be returned
// Provided context must be non-nil
func (c *Change) PatchContext(ctx context.Context) (*Patch, error) {
return getPatchContext(ctx, "", c)
}
func (c *Change) name() string {
if c.From != empty {
return c.From.Name
}
return c.To.Name
}
// ChangeEntry values represent a node that has suffered a change.
type ChangeEntry struct {
// Full path of the node using "/" as separator.
Name string
// Parent tree of the node that has changed.
Tree *Tree
// The entry of the node.
TreeEntry TreeEntry
}
// Changes represents a collection of changes between two git trees.
// Implements sort.Interface lexicographically over the path of the
// changed files.
type Changes []*Change
func (c Changes) Len() int {
return len(c)
}
func (c Changes) Swap(i, j int) {
c[i], c[j] = c[j], c[i]
}
func (c Changes) Less(i, j int) bool {
return strings.Compare(c[i].name(), c[j].name()) < 0
}
func (c Changes) String() string {
var buffer bytes.Buffer
buffer.WriteString("[")
comma := ""
for _, v := range c {
buffer.WriteString(comma)
buffer.WriteString(v.String())
comma = ", "
}
buffer.WriteString("]")
return buffer.String()
}
// Patch returns a Patch with all the changes in chunks. This
// representation can be used to create several diff outputs.
func (c Changes) Patch() (*Patch, error) {
return c.PatchContext(context.Background())
}
// Patch returns a Patch with all the changes in chunks. This
// representation can be used to create several diff outputs.
// If context expires, an non-nil error will be returned
// Provided context must be non-nil
func (c Changes) PatchContext(ctx context.Context) (*Patch, error) {
return getPatchContext(ctx, "", c...)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/change_adaptor.go
================================================
package object
import (
"errors"
"fmt"
"github.com/go-git/go-git/v5/utils/merkletrie"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// The following functions transform changes types form the merkletrie
// package to changes types from this package.
func newChange(c merkletrie.Change) (*Change, error) {
ret := &Change{}
var err error
if ret.From, err = newChangeEntry(c.From); err != nil {
return nil, fmt.Errorf("from field: %s", err)
}
if ret.To, err = newChangeEntry(c.To); err != nil {
return nil, fmt.Errorf("to field: %s", err)
}
return ret, nil
}
func newChangeEntry(p noder.Path) (ChangeEntry, error) {
if p == nil {
return empty, nil
}
asTreeNoder, ok := p.Last().(*treeNoder)
if !ok {
return ChangeEntry{}, errors.New("cannot transform non-TreeNoders")
}
return ChangeEntry{
Name: p.String(),
Tree: asTreeNoder.parent,
TreeEntry: TreeEntry{
Name: asTreeNoder.name,
Mode: asTreeNoder.mode,
Hash: asTreeNoder.hash,
},
}, nil
}
func newChanges(src merkletrie.Changes) (Changes, error) {
ret := make(Changes, len(src))
var err error
for i, e := range src {
ret[i], err = newChange(e)
if err != nil {
return nil, fmt.Errorf("change #%d: %s", i, err)
}
}
return ret, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit.go
================================================
package object
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strings"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
const (
beginpgp string = "-----BEGIN PGP SIGNATURE-----"
endpgp string = "-----END PGP SIGNATURE-----"
headerpgp string = "gpgsig"
headerencoding string = "encoding"
// https://github.com/git/git/blob/bcb6cae2966cc407ca1afc77413b3ef11103c175/Documentation/gitformat-signature.txt#L153
// When a merge commit is created from a signed tag, the tag is embedded in
// the commit with the "mergetag" header.
headermergetag string = "mergetag"
defaultUtf8CommitMessageEncoding MessageEncoding = "UTF-8"
)
// Hash represents the hash of an object
type Hash plumbing.Hash
// MessageEncoding represents the encoding of a commit
type MessageEncoding string
// Commit points to a single tree, marking it as what the project looked like
// at a certain point in time. It contains meta-information about that point
// in time, such as a timestamp, the author of the changes since the last
// commit, a pointer to the previous commit(s), etc.
// http://shafiulazam.com/gitbook/1_the_git_object_model.html
type Commit struct {
// Hash of the commit object.
Hash plumbing.Hash
// Author is the original author of the commit.
Author Signature
// Committer is the one performing the commit, might be different from
// Author.
Committer Signature
// MergeTag is the embedded tag object when a merge commit is created by
// merging a signed tag.
MergeTag string
// PGPSignature is the PGP signature of the commit.
PGPSignature string
// Message is the commit message, contains arbitrary text.
Message string
// TreeHash is the hash of the root tree of the commit.
TreeHash plumbing.Hash
// ParentHashes are the hashes of the parent commits of the commit.
ParentHashes []plumbing.Hash
// Encoding is the encoding of the commit.
Encoding MessageEncoding
s storer.EncodedObjectStorer
}
// GetCommit gets a commit from an object storer and decodes it.
func GetCommit(s storer.EncodedObjectStorer, h plumbing.Hash) (*Commit, error) {
o, err := s.EncodedObject(plumbing.CommitObject, h)
if err != nil {
return nil, err
}
return DecodeCommit(s, o)
}
// DecodeCommit decodes an encoded object into a *Commit and associates it to
// the given object storer.
func DecodeCommit(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Commit, error) {
c := &Commit{s: s}
if err := c.Decode(o); err != nil {
return nil, err
}
return c, nil
}
// Tree returns the Tree from the commit.
func (c *Commit) Tree() (*Tree, error) {
return GetTree(c.s, c.TreeHash)
}
// PatchContext returns the Patch between the actual commit and the provided one.
// Error will be return if context expires. Provided context must be non-nil.
//
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
// used are the recommended options DefaultDiffTreeOptions.
func (c *Commit) PatchContext(ctx context.Context, to *Commit) (*Patch, error) {
fromTree, err := c.Tree()
if err != nil {
return nil, err
}
var toTree *Tree
if to != nil {
toTree, err = to.Tree()
if err != nil {
return nil, err
}
}
return fromTree.PatchContext(ctx, toTree)
}
// Patch returns the Patch between the actual commit and the provided one.
//
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
// used are the recommended options DefaultDiffTreeOptions.
func (c *Commit) Patch(to *Commit) (*Patch, error) {
return c.PatchContext(context.Background(), to)
}
// Parents return a CommitIter to the parent Commits.
func (c *Commit) Parents() CommitIter {
return NewCommitIter(c.s,
storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, c.ParentHashes),
)
}
// NumParents returns the number of parents in a commit.
func (c *Commit) NumParents() int {
return len(c.ParentHashes)
}
var ErrParentNotFound = errors.New("commit parent not found")
// Parent returns the ith parent of a commit.
func (c *Commit) Parent(i int) (*Commit, error) {
if len(c.ParentHashes) == 0 || i > len(c.ParentHashes)-1 {
return nil, ErrParentNotFound
}
return GetCommit(c.s, c.ParentHashes[i])
}
// File returns the file with the specified "path" in the commit and a
// nil error if the file exists. If the file does not exist, it returns
// a nil file and the ErrFileNotFound error.
func (c *Commit) File(path string) (*File, error) {
tree, err := c.Tree()
if err != nil {
return nil, err
}
return tree.File(path)
}
// Files returns a FileIter allowing to iterate over the Tree
func (c *Commit) Files() (*FileIter, error) {
tree, err := c.Tree()
if err != nil {
return nil, err
}
return tree.Files(), nil
}
// ID returns the object ID of the commit. The returned value will always match
// the current value of Commit.Hash.
//
// ID is present to fulfill the Object interface.
func (c *Commit) ID() plumbing.Hash {
return c.Hash
}
// Type returns the type of object. It always returns plumbing.CommitObject.
//
// Type is present to fulfill the Object interface.
func (c *Commit) Type() plumbing.ObjectType {
return plumbing.CommitObject
}
// Decode transforms a plumbing.EncodedObject into a Commit struct.
func (c *Commit) Decode(o plumbing.EncodedObject) (err error) {
if o.Type() != plumbing.CommitObject {
return ErrUnsupportedObject
}
c.Hash = o.Hash()
c.Encoding = defaultUtf8CommitMessageEncoding
reader, err := o.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(reader, &err)
r := sync.GetBufioReader(reader)
defer sync.PutBufioReader(r)
var message bool
var mergetag bool
var pgpsig bool
var msgbuf bytes.Buffer
for {
line, err := r.ReadBytes('\n')
if err != nil && err != io.EOF {
return err
}
if mergetag {
if len(line) > 0 && line[0] == ' ' {
line = bytes.TrimLeft(line, " ")
c.MergeTag += string(line)
continue
} else {
mergetag = false
}
}
if pgpsig {
if len(line) > 0 && line[0] == ' ' {
line = bytes.TrimLeft(line, " ")
c.PGPSignature += string(line)
continue
} else {
pgpsig = false
}
}
if !message {
line = bytes.TrimSpace(line)
if len(line) == 0 {
message = true
continue
}
split := bytes.SplitN(line, []byte{' '}, 2)
var data []byte
if len(split) == 2 {
data = split[1]
}
switch string(split[0]) {
case "tree":
c.TreeHash = plumbing.NewHash(string(data))
case "parent":
c.ParentHashes = append(c.ParentHashes, plumbing.NewHash(string(data)))
case "author":
c.Author.Decode(data)
case "committer":
c.Committer.Decode(data)
case headermergetag:
c.MergeTag += string(data) + "\n"
mergetag = true
case headerencoding:
c.Encoding = MessageEncoding(data)
case headerpgp:
c.PGPSignature += string(data) + "\n"
pgpsig = true
}
} else {
msgbuf.Write(line)
}
if err == io.EOF {
break
}
}
c.Message = msgbuf.String()
return nil
}
// Encode transforms a Commit into a plumbing.EncodedObject.
func (c *Commit) Encode(o plumbing.EncodedObject) error {
return c.encode(o, true)
}
// EncodeWithoutSignature export a Commit into a plumbing.EncodedObject without the signature (correspond to the payload of the PGP signature).
func (c *Commit) EncodeWithoutSignature(o plumbing.EncodedObject) error {
return c.encode(o, false)
}
func (c *Commit) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
o.SetType(plumbing.CommitObject)
w, err := o.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
if _, err = fmt.Fprintf(w, "tree %s\n", c.TreeHash.String()); err != nil {
return err
}
for _, parent := range c.ParentHashes {
if _, err = fmt.Fprintf(w, "parent %s\n", parent.String()); err != nil {
return err
}
}
if _, err = fmt.Fprint(w, "author "); err != nil {
return err
}
if err = c.Author.Encode(w); err != nil {
return err
}
if _, err = fmt.Fprint(w, "\ncommitter "); err != nil {
return err
}
if err = c.Committer.Encode(w); err != nil {
return err
}
if c.MergeTag != "" {
if _, err = fmt.Fprint(w, "\n"+headermergetag+" "); err != nil {
return err
}
// Split tag information lines and re-write with a left padding and
// newline. Use join for this so it's clear that a newline should not be
// added after this section. The newline will be added either as part of
// the PGP signature or the commit message.
mergetag := strings.TrimSuffix(c.MergeTag, "\n")
lines := strings.Split(mergetag, "\n")
if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil {
return err
}
}
if string(c.Encoding) != "" && c.Encoding != defaultUtf8CommitMessageEncoding {
if _, err = fmt.Fprintf(w, "\n%s %s", headerencoding, c.Encoding); err != nil {
return err
}
}
if c.PGPSignature != "" && includeSig {
if _, err = fmt.Fprint(w, "\n"+headerpgp+" "); err != nil {
return err
}
// Split all the signature lines and re-write with a left padding and
// newline. Use join for this so it's clear that a newline should not be
// added after this section, as it will be added when the message is
// printed.
signature := strings.TrimSuffix(c.PGPSignature, "\n")
lines := strings.Split(signature, "\n")
if _, err = fmt.Fprint(w, strings.Join(lines, "\n ")); err != nil {
return err
}
}
if _, err = fmt.Fprintf(w, "\n\n%s", c.Message); err != nil {
return err
}
return err
}
// Stats returns the stats of a commit.
func (c *Commit) Stats() (FileStats, error) {
return c.StatsContext(context.Background())
}
// StatsContext returns the stats of a commit. Error will be return if context
// expires. Provided context must be non-nil.
func (c *Commit) StatsContext(ctx context.Context) (FileStats, error) {
fromTree, err := c.Tree()
if err != nil {
return nil, err
}
toTree := &Tree{}
if c.NumParents() != 0 {
firstParent, err := c.Parents().Next()
if err != nil {
return nil, err
}
toTree, err = firstParent.Tree()
if err != nil {
return nil, err
}
}
patch, err := toTree.PatchContext(ctx, fromTree)
if err != nil {
return nil, err
}
return getFileStatsFromFilePatches(patch.FilePatches()), nil
}
func (c *Commit) String() string {
return fmt.Sprintf(
"%s %s\nAuthor: %s\nDate: %s\n\n%s\n",
plumbing.CommitObject, c.Hash, c.Author.String(),
c.Author.When.Format(DateFormat), indent(c.Message),
)
}
// Verify performs PGP verification of the commit with a provided armored
// keyring and returns openpgp.Entity associated with verifying key on success.
func (c *Commit) Verify(armoredKeyRing string) (*openpgp.Entity, error) {
keyRingReader := strings.NewReader(armoredKeyRing)
keyring, err := openpgp.ReadArmoredKeyRing(keyRingReader)
if err != nil {
return nil, err
}
// Extract signature.
signature := strings.NewReader(c.PGPSignature)
encoded := &plumbing.MemoryObject{}
// Encode commit components, excluding signature and get a reader object.
if err := c.EncodeWithoutSignature(encoded); err != nil {
return nil, err
}
er, err := encoded.Reader()
if err != nil {
return nil, err
}
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil)
}
// Less defines a compare function to determine which commit is 'earlier' by:
// - First use Committer.When
// - If Committer.When are equal then use Author.When
// - If Author.When also equal then compare the string value of the hash
func (c *Commit) Less(rhs *Commit) bool {
return c.Committer.When.Before(rhs.Committer.When) ||
(c.Committer.When.Equal(rhs.Committer.When) &&
(c.Author.When.Before(rhs.Author.When) ||
(c.Author.When.Equal(rhs.Author.When) && bytes.Compare(c.Hash[:], rhs.Hash[:]) < 0)))
}
func indent(t string) string {
var output []string
for _, line := range strings.Split(t, "\n") {
if len(line) != 0 {
line = " " + line
}
output = append(output, line)
}
return strings.Join(output, "\n")
}
// CommitIter is a generic closable interface for iterating over commits.
type CommitIter interface {
Next() (*Commit, error)
ForEach(func(*Commit) error) error
Close()
}
// storerCommitIter provides an iterator from commits in an EncodedObjectStorer.
type storerCommitIter struct {
storer.EncodedObjectIter
s storer.EncodedObjectStorer
}
// NewCommitIter takes a storer.EncodedObjectStorer and a
// storer.EncodedObjectIter and returns a CommitIter that iterates over all
// commits contained in the storer.EncodedObjectIter.
//
// Any non-commit object returned by the storer.EncodedObjectIter is skipped.
func NewCommitIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) CommitIter {
return &storerCommitIter{iter, s}
}
// Next moves the iterator to the next commit and returns a pointer to it. If
// there are no more commits, it returns io.EOF.
func (iter *storerCommitIter) Next() (*Commit, error) {
obj, err := iter.EncodedObjectIter.Next()
if err != nil {
return nil, err
}
return DecodeCommit(iter.s, obj)
}
// ForEach call the cb function for each commit contained on this iter until
// an error appends or the end of the iter is reached. If ErrStop is sent
// the iteration is stopped but no error is returned. The iterator is closed.
func (iter *storerCommitIter) ForEach(cb func(*Commit) error) error {
return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
c, err := DecodeCommit(iter.s, obj)
if err != nil {
return err
}
return cb(c)
})
}
func (iter *storerCommitIter) Close() {
iter.EncodedObjectIter.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker.go
================================================
package object
import (
"container/list"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage"
)
type commitPreIterator struct {
seenExternal map[plumbing.Hash]bool
seen map[plumbing.Hash]bool
stack []CommitIter
start *Commit
}
// NewCommitPreorderIter returns a CommitIter that walks the commit history,
// starting at the given commit and visiting its parents in pre-order.
// The given callback will be called for each visited commit. Each commit will
// be visited only once. If the callback returns an error, walking will stop
// and will return the error. Other errors might be returned if the history
// cannot be traversed (e.g. missing objects). Ignore allows to skip some
// commits from being iterated.
func NewCommitPreorderIter(
c *Commit,
seenExternal map[plumbing.Hash]bool,
ignore []plumbing.Hash,
) CommitIter {
seen := make(map[plumbing.Hash]bool)
for _, h := range ignore {
seen[h] = true
}
return &commitPreIterator{
seenExternal: seenExternal,
seen: seen,
stack: make([]CommitIter, 0),
start: c,
}
}
func (w *commitPreIterator) Next() (*Commit, error) {
var c *Commit
for {
if w.start != nil {
c = w.start
w.start = nil
} else {
current := len(w.stack) - 1
if current < 0 {
return nil, io.EOF
}
var err error
c, err = w.stack[current].Next()
if err == io.EOF {
w.stack = w.stack[:current]
continue
}
if err != nil {
return nil, err
}
}
if w.seen[c.Hash] || w.seenExternal[c.Hash] {
continue
}
w.seen[c.Hash] = true
if c.NumParents() > 0 {
w.stack = append(w.stack, filteredParentIter(c, w.seen))
}
return c, nil
}
}
func filteredParentIter(c *Commit, seen map[plumbing.Hash]bool) CommitIter {
var hashes []plumbing.Hash
for _, h := range c.ParentHashes {
if !seen[h] {
hashes = append(hashes, h)
}
}
return NewCommitIter(c.s,
storer.NewEncodedObjectLookupIter(c.s, plumbing.CommitObject, hashes),
)
}
func (w *commitPreIterator) ForEach(cb func(*Commit) error) error {
for {
c, err := w.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
err = cb(c)
if err == storer.ErrStop {
break
}
if err != nil {
return err
}
}
return nil
}
func (w *commitPreIterator) Close() {}
type commitPostIterator struct {
stack []*Commit
seen map[plumbing.Hash]bool
}
// NewCommitPostorderIter returns a CommitIter that walks the commit
// history like WalkCommitHistory but in post-order. This means that after
// walking a merge commit, the merged commit will be walked before the base
// it was merged on. This can be useful if you wish to see the history in
// chronological order. Ignore allows to skip some commits from being iterated.
func NewCommitPostorderIter(c *Commit, ignore []plumbing.Hash) CommitIter {
seen := make(map[plumbing.Hash]bool)
for _, h := range ignore {
seen[h] = true
}
return &commitPostIterator{
stack: []*Commit{c},
seen: seen,
}
}
func (w *commitPostIterator) Next() (*Commit, error) {
for {
if len(w.stack) == 0 {
return nil, io.EOF
}
c := w.stack[len(w.stack)-1]
w.stack = w.stack[:len(w.stack)-1]
if w.seen[c.Hash] {
continue
}
w.seen[c.Hash] = true
return c, c.Parents().ForEach(func(p *Commit) error {
w.stack = append(w.stack, p)
return nil
})
}
}
func (w *commitPostIterator) ForEach(cb func(*Commit) error) error {
for {
c, err := w.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
err = cb(c)
if err == storer.ErrStop {
break
}
if err != nil {
return err
}
}
return nil
}
func (w *commitPostIterator) Close() {}
// commitAllIterator stands for commit iterator for all refs.
type commitAllIterator struct {
// currCommit points to the current commit.
currCommit *list.Element
}
// NewCommitAllIter returns a new commit iterator for all refs.
// repoStorer is a repo Storer used to get commits and references.
// commitIterFunc is a commit iterator function, used to iterate through ref commits in chosen order
func NewCommitAllIter(repoStorer storage.Storer, commitIterFunc func(*Commit) CommitIter) (CommitIter, error) {
commitsPath := list.New()
commitsLookup := make(map[plumbing.Hash]*list.Element)
head, err := storer.ResolveReference(repoStorer, plumbing.HEAD)
if err == nil {
err = addReference(repoStorer, commitIterFunc, head, commitsPath, commitsLookup)
}
if err != nil && err != plumbing.ErrReferenceNotFound {
return nil, err
}
// add all references along with the HEAD
refIter, err := repoStorer.IterReferences()
if err != nil {
return nil, err
}
defer refIter.Close()
for {
ref, err := refIter.Next()
if err == io.EOF {
break
}
if err == plumbing.ErrReferenceNotFound {
continue
}
if err != nil {
return nil, err
}
if err = addReference(repoStorer, commitIterFunc, ref, commitsPath, commitsLookup); err != nil {
return nil, err
}
}
return &commitAllIterator{commitsPath.Front()}, nil
}
func addReference(
repoStorer storage.Storer,
commitIterFunc func(*Commit) CommitIter,
ref *plumbing.Reference,
commitsPath *list.List,
commitsLookup map[plumbing.Hash]*list.Element) error {
_, exists := commitsLookup[ref.Hash()]
if exists {
// we already have it - skip the reference.
return nil
}
refCommit, _ := GetCommit(repoStorer, ref.Hash())
if refCommit == nil {
// if it's not a commit - skip it.
return nil
}
var (
refCommits []*Commit
parent *list.Element
)
// collect all ref commits to add
commitIter := commitIterFunc(refCommit)
for c, e := commitIter.Next(); e == nil; {
parent, exists = commitsLookup[c.Hash]
if exists {
break
}
refCommits = append(refCommits, c)
c, e = commitIter.Next()
}
commitIter.Close()
if parent == nil {
// common parent - not found
// add all commits to the path from this ref (maybe it's a HEAD and we don't have anything, yet)
for _, c := range refCommits {
parent = commitsPath.PushBack(c)
commitsLookup[c.Hash] = parent
}
} else {
// add ref's commits to the path in reverse order (from the latest)
for i := len(refCommits) - 1; i >= 0; i-- {
c := refCommits[i]
// insert before found common parent
parent = commitsPath.InsertBefore(c, parent)
commitsLookup[c.Hash] = parent
}
}
return nil
}
func (it *commitAllIterator) Next() (*Commit, error) {
if it.currCommit == nil {
return nil, io.EOF
}
c := it.currCommit.Value.(*Commit)
it.currCommit = it.currCommit.Next()
return c, nil
}
func (it *commitAllIterator) ForEach(cb func(*Commit) error) error {
for {
c, err := it.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
err = cb(c)
if err == storer.ErrStop {
break
}
if err != nil {
return err
}
}
return nil
}
func (it *commitAllIterator) Close() {
it.currCommit = nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_bfs.go
================================================
package object
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
type bfsCommitIterator struct {
seenExternal map[plumbing.Hash]bool
seen map[plumbing.Hash]bool
queue []*Commit
}
// NewCommitIterBSF returns a CommitIter that walks the commit history,
// starting at the given commit and visiting its parents in pre-order.
// The given callback will be called for each visited commit. Each commit will
// be visited only once. If the callback returns an error, walking will stop
// and will return the error. Other errors might be returned if the history
// cannot be traversed (e.g. missing objects). Ignore allows to skip some
// commits from being iterated.
func NewCommitIterBSF(
c *Commit,
seenExternal map[plumbing.Hash]bool,
ignore []plumbing.Hash,
) CommitIter {
seen := make(map[plumbing.Hash]bool)
for _, h := range ignore {
seen[h] = true
}
return &bfsCommitIterator{
seenExternal: seenExternal,
seen: seen,
queue: []*Commit{c},
}
}
func (w *bfsCommitIterator) appendHash(store storer.EncodedObjectStorer, h plumbing.Hash) error {
if w.seen[h] || w.seenExternal[h] {
return nil
}
c, err := GetCommit(store, h)
if err != nil {
return err
}
w.queue = append(w.queue, c)
return nil
}
func (w *bfsCommitIterator) Next() (*Commit, error) {
var c *Commit
for {
if len(w.queue) == 0 {
return nil, io.EOF
}
c = w.queue[0]
w.queue = w.queue[1:]
if w.seen[c.Hash] || w.seenExternal[c.Hash] {
continue
}
w.seen[c.Hash] = true
for _, h := range c.ParentHashes {
err := w.appendHash(c.s, h)
if err != nil {
return nil, err
}
}
return c, nil
}
}
func (w *bfsCommitIterator) ForEach(cb func(*Commit) error) error {
for {
c, err := w.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
err = cb(c)
if err == storer.ErrStop {
break
}
if err != nil {
return err
}
}
return nil
}
func (w *bfsCommitIterator) Close() {}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_bfs_filtered.go
================================================
package object
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// NewFilterCommitIter returns a CommitIter that walks the commit history,
// starting at the passed commit and visiting its parents in Breadth-first order.
// The commits returned by the CommitIter will validate the passed CommitFilter.
// The history won't be transversed beyond a commit if isLimit is true for it.
// Each commit will be visited only once.
// If the commit history can not be traversed, or the Close() method is called,
// the CommitIter won't return more commits.
// If no isValid is passed, all ancestors of from commit will be valid.
// If no isLimit is limit, all ancestors of all commits will be visited.
func NewFilterCommitIter(
from *Commit,
isValid *CommitFilter,
isLimit *CommitFilter,
) CommitIter {
var validFilter CommitFilter
if isValid == nil {
validFilter = func(_ *Commit) bool {
return true
}
} else {
validFilter = *isValid
}
var limitFilter CommitFilter
if isLimit == nil {
limitFilter = func(_ *Commit) bool {
return false
}
} else {
limitFilter = *isLimit
}
return &filterCommitIter{
isValid: validFilter,
isLimit: limitFilter,
visited: map[plumbing.Hash]struct{}{},
queue: []*Commit{from},
}
}
// CommitFilter returns a boolean for the passed Commit
type CommitFilter func(*Commit) bool
// filterCommitIter implements CommitIter
type filterCommitIter struct {
isValid CommitFilter
isLimit CommitFilter
visited map[plumbing.Hash]struct{}
queue []*Commit
lastErr error
}
// Next returns the next commit of the CommitIter.
// It will return io.EOF if there are no more commits to visit,
// or an error if the history could not be traversed.
func (w *filterCommitIter) Next() (*Commit, error) {
var commit *Commit
var err error
for {
commit, err = w.popNewFromQueue()
if err != nil {
return nil, w.close(err)
}
w.visited[commit.Hash] = struct{}{}
if !w.isLimit(commit) {
err = w.addToQueue(commit.s, commit.ParentHashes...)
if err != nil {
return nil, w.close(err)
}
}
if w.isValid(commit) {
return commit, nil
}
}
}
// ForEach runs the passed callback over each Commit returned by the CommitIter
// until the callback returns an error or there is no more commits to traverse.
func (w *filterCommitIter) ForEach(cb func(*Commit) error) error {
for {
commit, err := w.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if err := cb(commit); err == storer.ErrStop {
break
} else if err != nil {
return err
}
}
return nil
}
// Error returns the error that caused that the CommitIter is no longer returning commits
func (w *filterCommitIter) Error() error {
return w.lastErr
}
// Close closes the CommitIter
func (w *filterCommitIter) Close() {
w.visited = map[plumbing.Hash]struct{}{}
w.queue = []*Commit{}
w.isLimit = nil
w.isValid = nil
}
// close closes the CommitIter with an error
func (w *filterCommitIter) close(err error) error {
w.Close()
w.lastErr = err
return err
}
// popNewFromQueue returns the first new commit from the internal fifo queue,
// or an io.EOF error if the queue is empty
func (w *filterCommitIter) popNewFromQueue() (*Commit, error) {
var first *Commit
for {
if len(w.queue) == 0 {
if w.lastErr != nil {
return nil, w.lastErr
}
return nil, io.EOF
}
first = w.queue[0]
w.queue = w.queue[1:]
if _, ok := w.visited[first.Hash]; ok {
continue
}
return first, nil
}
}
// addToQueue adds the passed commits to the internal fifo queue if they weren't seen
// or returns an error if the passed hashes could not be used to get valid commits
func (w *filterCommitIter) addToQueue(
store storer.EncodedObjectStorer,
hashes ...plumbing.Hash,
) error {
for _, hash := range hashes {
if _, ok := w.visited[hash]; ok {
continue
}
commit, err := GetCommit(store, hash)
if err != nil {
return err
}
w.queue = append(w.queue, commit)
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_ctime.go
================================================
package object
import (
"io"
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
type commitIteratorByCTime struct {
seenExternal map[plumbing.Hash]bool
seen map[plumbing.Hash]bool
heap *binaryheap.Heap
}
// NewCommitIterCTime returns a CommitIter that walks the commit history,
// starting at the given commit and visiting its parents while preserving Committer Time order.
// this appears to be the closest order to `git log`
// The given callback will be called for each visited commit. Each commit will
// be visited only once. If the callback returns an error, walking will stop
// and will return the error. Other errors might be returned if the history
// cannot be traversed (e.g. missing objects). Ignore allows to skip some
// commits from being iterated.
func NewCommitIterCTime(
c *Commit,
seenExternal map[plumbing.Hash]bool,
ignore []plumbing.Hash,
) CommitIter {
seen := make(map[plumbing.Hash]bool)
for _, h := range ignore {
seen[h] = true
}
heap := binaryheap.NewWith(func(a, b interface{}) int {
if a.(*Commit).Committer.When.Before(b.(*Commit).Committer.When) {
return 1
}
return -1
})
heap.Push(c)
return &commitIteratorByCTime{
seenExternal: seenExternal,
seen: seen,
heap: heap,
}
}
func (w *commitIteratorByCTime) Next() (*Commit, error) {
var c *Commit
for {
cIn, ok := w.heap.Pop()
if !ok {
return nil, io.EOF
}
c = cIn.(*Commit)
if w.seen[c.Hash] || w.seenExternal[c.Hash] {
continue
}
w.seen[c.Hash] = true
for _, h := range c.ParentHashes {
if w.seen[h] || w.seenExternal[h] {
continue
}
pc, err := GetCommit(c.s, h)
if err != nil {
return nil, err
}
w.heap.Push(pc)
}
return c, nil
}
}
func (w *commitIteratorByCTime) ForEach(cb func(*Commit) error) error {
for {
c, err := w.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
err = cb(c)
if err == storer.ErrStop {
break
}
if err != nil {
return err
}
}
return nil
}
func (w *commitIteratorByCTime) Close() {}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_limit.go
================================================
package object
import (
"io"
"time"
"github.com/go-git/go-git/v5/plumbing/storer"
)
type commitLimitIter struct {
sourceIter CommitIter
limitOptions LogLimitOptions
}
type LogLimitOptions struct {
Since *time.Time
Until *time.Time
}
func NewCommitLimitIterFromIter(commitIter CommitIter, limitOptions LogLimitOptions) CommitIter {
iterator := new(commitLimitIter)
iterator.sourceIter = commitIter
iterator.limitOptions = limitOptions
return iterator
}
func (c *commitLimitIter) Next() (*Commit, error) {
for {
commit, err := c.sourceIter.Next()
if err != nil {
return nil, err
}
if c.limitOptions.Since != nil && commit.Committer.When.Before(*c.limitOptions.Since) {
continue
}
if c.limitOptions.Until != nil && commit.Committer.When.After(*c.limitOptions.Until) {
continue
}
return commit, nil
}
}
func (c *commitLimitIter) ForEach(cb func(*Commit) error) error {
for {
commit, nextErr := c.Next()
if nextErr == io.EOF {
break
}
if nextErr != nil {
return nextErr
}
err := cb(commit)
if err == storer.ErrStop {
return nil
} else if err != nil {
return err
}
}
return nil
}
func (c *commitLimitIter) Close() {
c.sourceIter.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/commit_walker_path.go
================================================
package object
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
type commitPathIter struct {
pathFilter func(string) bool
sourceIter CommitIter
currentCommit *Commit
checkParent bool
}
// NewCommitPathIterFromIter returns a commit iterator which performs diffTree between
// successive trees returned from the commit iterator from the argument. The purpose of this is
// to find the commits that explain how the files that match the path came to be.
// If checkParent is true then the function double checks if potential parent (next commit in a path)
// is one of the parents in the tree (it's used by `git log --all`).
// pathFilter is a function that takes path of file as argument and returns true if we want it
func NewCommitPathIterFromIter(pathFilter func(string) bool, commitIter CommitIter, checkParent bool) CommitIter {
iterator := new(commitPathIter)
iterator.sourceIter = commitIter
iterator.pathFilter = pathFilter
iterator.checkParent = checkParent
return iterator
}
// NewCommitFileIterFromIter is kept for compatibility, can be replaced with NewCommitPathIterFromIter
func NewCommitFileIterFromIter(fileName string, commitIter CommitIter, checkParent bool) CommitIter {
return NewCommitPathIterFromIter(
func(path string) bool {
return path == fileName
},
commitIter,
checkParent,
)
}
func (c *commitPathIter) Next() (*Commit, error) {
if c.currentCommit == nil {
var err error
c.currentCommit, err = c.sourceIter.Next()
if err != nil {
return nil, err
}
}
commit, commitErr := c.getNextFileCommit()
// Setting current-commit to nil to prevent unwanted states when errors are raised
if commitErr != nil {
c.currentCommit = nil
}
return commit, commitErr
}
func (c *commitPathIter) getNextFileCommit() (*Commit, error) {
var parentTree, currentTree *Tree
for {
// Parent-commit can be nil if the current-commit is the initial commit
parentCommit, parentCommitErr := c.sourceIter.Next()
if parentCommitErr != nil {
// If the parent-commit is beyond the initial commit, keep it nil
if parentCommitErr != io.EOF {
return nil, parentCommitErr
}
parentCommit = nil
}
if parentTree == nil {
var currTreeErr error
currentTree, currTreeErr = c.currentCommit.Tree()
if currTreeErr != nil {
return nil, currTreeErr
}
} else {
currentTree = parentTree
parentTree = nil
}
if parentCommit != nil {
var parentTreeErr error
parentTree, parentTreeErr = parentCommit.Tree()
if parentTreeErr != nil {
return nil, parentTreeErr
}
}
// Find diff between current and parent trees
changes, diffErr := DiffTree(currentTree, parentTree)
if diffErr != nil {
return nil, diffErr
}
found := c.hasFileChange(changes, parentCommit)
// Storing the current-commit in-case a change is found, and
// Updating the current-commit for the next-iteration
prevCommit := c.currentCommit
c.currentCommit = parentCommit
if found {
return prevCommit, nil
}
// If not matches found and if parent-commit is beyond the initial commit, then return with EOF
if parentCommit == nil {
return nil, io.EOF
}
}
}
func (c *commitPathIter) hasFileChange(changes Changes, parent *Commit) bool {
for _, change := range changes {
if !c.pathFilter(change.name()) {
continue
}
// filename matches, now check if source iterator contains all commits (from all refs)
if c.checkParent {
// Check if parent is beyond the initial commit
if parent == nil || isParentHash(parent.Hash, c.currentCommit) {
return true
}
continue
}
return true
}
return false
}
func isParentHash(hash plumbing.Hash, commit *Commit) bool {
for _, h := range commit.ParentHashes {
if h == hash {
return true
}
}
return false
}
func (c *commitPathIter) ForEach(cb func(*Commit) error) error {
for {
commit, nextErr := c.Next()
if nextErr == io.EOF {
break
}
if nextErr != nil {
return nextErr
}
err := cb(commit)
if err == storer.ErrStop {
return nil
} else if err != nil {
return err
}
}
return nil
}
func (c *commitPathIter) Close() {
c.sourceIter.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/difftree.go
================================================
package object
import (
"bytes"
"context"
"github.com/go-git/go-git/v5/utils/merkletrie"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// DiffTree compares the content and mode of the blobs found via two
// tree objects.
// DiffTree does not perform rename detection, use DiffTreeWithOptions
// instead to detect renames.
func DiffTree(a, b *Tree) (Changes, error) {
return DiffTreeContext(context.Background(), a, b)
}
// DiffTreeContext compares the content and mode of the blobs found via two
// tree objects. Provided context must be non-nil.
// An error will be returned if context expires.
func DiffTreeContext(ctx context.Context, a, b *Tree) (Changes, error) {
return DiffTreeWithOptions(ctx, a, b, nil)
}
// DiffTreeOptions are the configurable options when performing a diff tree.
type DiffTreeOptions struct {
// DetectRenames is whether the diff tree will use rename detection.
DetectRenames bool
// RenameScore is the threshold to of similarity between files to consider
// that a pair of delete and insert are a rename. The number must be
// exactly between 0 and 100.
RenameScore uint
// RenameLimit is the maximum amount of files that can be compared when
// detecting renames. The number of comparisons that have to be performed
// is equal to the number of deleted files * the number of added files.
// That means, that if 100 files were deleted and 50 files were added, 5000
// file comparisons may be needed. So, if the rename limit is 50, the number
// of both deleted and added needs to be equal or less than 50.
// A value of 0 means no limit.
RenameLimit uint
// OnlyExactRenames performs only detection of exact renames and will not perform
// any detection of renames based on file similarity.
OnlyExactRenames bool
}
// DefaultDiffTreeOptions are the default and recommended options for the
// diff tree.
var DefaultDiffTreeOptions = &DiffTreeOptions{
DetectRenames: true,
RenameScore: 60,
RenameLimit: 0,
OnlyExactRenames: false,
}
// DiffTreeWithOptions compares the content and mode of the blobs found
// via two tree objects with the given options. The provided context
// must be non-nil.
// If no options are passed, no rename detection will be performed. The
// recommended options are DefaultDiffTreeOptions.
// An error will be returned if the context expires.
// This function will be deprecated and removed in v6 so the default
// behaviour of DiffTree is to detect renames.
func DiffTreeWithOptions(
ctx context.Context,
a, b *Tree,
opts *DiffTreeOptions,
) (Changes, error) {
from := NewTreeRootNode(a)
to := NewTreeRootNode(b)
hashEqual := func(a, b noder.Hasher) bool {
return bytes.Equal(a.Hash(), b.Hash())
}
merkletrieChanges, err := merkletrie.DiffTreeContext(ctx, from, to, hashEqual)
if err != nil {
if err == merkletrie.ErrCanceled {
return nil, ErrCanceled
}
return nil, err
}
changes, err := newChanges(merkletrieChanges)
if err != nil {
return nil, err
}
if opts == nil {
opts = new(DiffTreeOptions)
}
if opts.DetectRenames {
return DetectRenames(changes, opts)
}
return changes, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/file.go
================================================
package object
import (
"bytes"
"io"
"strings"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/binary"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// File represents git file objects.
type File struct {
// Name is the path of the file. It might be relative to a tree,
// depending of the function that generates it.
Name string
// Mode is the file mode.
Mode filemode.FileMode
// Blob with the contents of the file.
Blob
}
// NewFile returns a File based on the given blob object
func NewFile(name string, m filemode.FileMode, b *Blob) *File {
return &File{Name: name, Mode: m, Blob: *b}
}
// Contents returns the contents of a file as a string.
func (f *File) Contents() (content string, err error) {
reader, err := f.Reader()
if err != nil {
return "", err
}
defer ioutil.CheckClose(reader, &err)
buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(reader); err != nil {
return "", err
}
return buf.String(), nil
}
// IsBinary returns if the file is binary or not
func (f *File) IsBinary() (bin bool, err error) {
reader, err := f.Reader()
if err != nil {
return false, err
}
defer ioutil.CheckClose(reader, &err)
return binary.IsBinary(reader)
}
// Lines returns a slice of lines from the contents of a file, stripping
// all end of line characters. If the last line is empty (does not end
// in an end of line), it is also stripped.
func (f *File) Lines() ([]string, error) {
content, err := f.Contents()
if err != nil {
return nil, err
}
splits := strings.Split(content, "\n")
// remove the last line if it is empty
if splits[len(splits)-1] == "" {
return splits[:len(splits)-1], nil
}
return splits, nil
}
// FileIter provides an iterator for the files in a tree.
type FileIter struct {
s storer.EncodedObjectStorer
w TreeWalker
}
// NewFileIter takes a storer.EncodedObjectStorer and a Tree and returns a
// *FileIter that iterates over all files contained in the tree, recursively.
func NewFileIter(s storer.EncodedObjectStorer, t *Tree) *FileIter {
return &FileIter{s: s, w: *NewTreeWalker(t, true, nil)}
}
// Next moves the iterator to the next file and returns a pointer to it. If
// there are no more files, it returns io.EOF.
func (iter *FileIter) Next() (*File, error) {
for {
name, entry, err := iter.w.Next()
if err != nil {
return nil, err
}
if entry.Mode == filemode.Dir || entry.Mode == filemode.Submodule {
continue
}
blob, err := GetBlob(iter.s, entry.Hash)
if err != nil {
return nil, err
}
return NewFile(name, entry.Mode, blob), nil
}
}
// ForEach call the cb function for each file contained in this iter until
// an error happens or the end of the iter is reached. If plumbing.ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *FileIter) ForEach(cb func(*File) error) error {
defer iter.Close()
for {
f, err := iter.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if err := cb(f); err != nil {
if err == storer.ErrStop {
return nil
}
return err
}
}
}
func (iter *FileIter) Close() {
iter.w.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/merge_base.go
================================================
package object
import (
"fmt"
"sort"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// errIsReachable is thrown when first commit is an ancestor of the second
var errIsReachable = fmt.Errorf("first is reachable from second")
// MergeBase mimics the behavior of `git merge-base actual other`, returning the
// best common ancestor between the actual and the passed one.
// The best common ancestors can not be reached from other common ancestors.
func (c *Commit) MergeBase(other *Commit) ([]*Commit, error) {
// use sortedByCommitDateDesc strategy
sorted := sortByCommitDateDesc(c, other)
newer := sorted[0]
older := sorted[1]
newerHistory, err := ancestorsIndex(older, newer)
if err == errIsReachable {
return []*Commit{older}, nil
}
if err != nil {
return nil, err
}
var res []*Commit
inNewerHistory := isInIndexCommitFilter(newerHistory)
resIter := NewFilterCommitIter(older, &inNewerHistory, &inNewerHistory)
_ = resIter.ForEach(func(commit *Commit) error {
res = append(res, commit)
return nil
})
return Independents(res)
}
// IsAncestor returns true if the actual commit is ancestor of the passed one.
// It returns an error if the history is not transversable
// It mimics the behavior of `git merge --is-ancestor actual other`
func (c *Commit) IsAncestor(other *Commit) (bool, error) {
found := false
iter := NewCommitPreorderIter(other, nil, nil)
err := iter.ForEach(func(comm *Commit) error {
if comm.Hash != c.Hash {
return nil
}
found = true
return storer.ErrStop
})
return found, err
}
// ancestorsIndex returns a map with the ancestors of the starting commit if the
// excluded one is not one of them. It returns errIsReachable if the excluded commit
// is ancestor of the starting, or another error if the history is not traversable.
func ancestorsIndex(excluded, starting *Commit) (map[plumbing.Hash]struct{}, error) {
if excluded.Hash.String() == starting.Hash.String() {
return nil, errIsReachable
}
startingHistory := map[plumbing.Hash]struct{}{}
startingIter := NewCommitIterBSF(starting, nil, nil)
err := startingIter.ForEach(func(commit *Commit) error {
if commit.Hash == excluded.Hash {
return errIsReachable
}
startingHistory[commit.Hash] = struct{}{}
return nil
})
if err != nil {
return nil, err
}
return startingHistory, nil
}
// Independents returns a subset of the passed commits, that are not reachable the others
// It mimics the behavior of `git merge-base --independent commit...`.
func Independents(commits []*Commit) ([]*Commit, error) {
// use sortedByCommitDateDesc strategy
candidates := sortByCommitDateDesc(commits...)
candidates = removeDuplicated(candidates)
seen := map[plumbing.Hash]struct{}{}
var isLimit CommitFilter = func(commit *Commit) bool {
_, ok := seen[commit.Hash]
return ok
}
if len(candidates) < 2 {
return candidates, nil
}
pos := 0
for {
from := candidates[pos]
others := remove(candidates, from)
fromHistoryIter := NewFilterCommitIter(from, nil, &isLimit)
err := fromHistoryIter.ForEach(func(fromAncestor *Commit) error {
for _, other := range others {
if fromAncestor.Hash == other.Hash {
candidates = remove(candidates, other)
others = remove(others, other)
}
}
if len(candidates) == 1 {
return storer.ErrStop
}
seen[fromAncestor.Hash] = struct{}{}
return nil
})
if err != nil {
return nil, err
}
nextPos := indexOf(candidates, from) + 1
if nextPos >= len(candidates) {
break
}
pos = nextPos
}
return candidates, nil
}
// sortByCommitDateDesc returns the passed commits, sorted by `committer.When desc`
//
// Following this strategy, it is tried to reduce the time needed when walking
// the history from one commit to reach the others. It is assumed that ancestors
// use to be committed before its descendant;
// That way `Independents(A^, A)` will be processed as being `Independents(A, A^)`;
// so starting by `A` it will be reached `A^` way sooner than walking from `A^`
// to the initial commit, and then from `A` to `A^`.
func sortByCommitDateDesc(commits ...*Commit) []*Commit {
sorted := make([]*Commit, len(commits))
copy(sorted, commits)
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].Committer.When.After(sorted[j].Committer.When)
})
return sorted
}
// indexOf returns the first position where target was found in the passed commits
func indexOf(commits []*Commit, target *Commit) int {
for i, commit := range commits {
if target.Hash == commit.Hash {
return i
}
}
return -1
}
// remove returns the passed commits excluding the commit toDelete
func remove(commits []*Commit, toDelete *Commit) []*Commit {
res := make([]*Commit, len(commits))
j := 0
for _, commit := range commits {
if commit.Hash == toDelete.Hash {
continue
}
res[j] = commit
j++
}
return res[:j]
}
// removeDuplicated removes duplicated commits from the passed slice of commits
func removeDuplicated(commits []*Commit) []*Commit {
seen := make(map[plumbing.Hash]struct{}, len(commits))
res := make([]*Commit, len(commits))
j := 0
for _, commit := range commits {
if _, ok := seen[commit.Hash]; ok {
continue
}
seen[commit.Hash] = struct{}{}
res[j] = commit
j++
}
return res[:j]
}
// isInIndexCommitFilter returns a commitFilter that returns true
// if the commit is in the passed index.
func isInIndexCommitFilter(index map[plumbing.Hash]struct{}) CommitFilter {
return func(c *Commit) bool {
_, ok := index[c.Hash]
return ok
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/object.go
================================================
// Package object contains implementations of all Git objects and utility
// functions to work with them.
package object
import (
"bytes"
"errors"
"fmt"
"io"
"strconv"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// ErrUnsupportedObject trigger when a non-supported object is being decoded.
var ErrUnsupportedObject = errors.New("unsupported object type")
// Object is a generic representation of any git object. It is implemented by
// Commit, Tree, Blob, and Tag, and includes the functions that are common to
// them.
//
// Object is returned when an object can be of any type. It is frequently used
// with a type cast to acquire the specific type of object:
//
// func process(obj Object) {
// switch o := obj.(type) {
// case *Commit:
// // o is a Commit
// case *Tree:
// // o is a Tree
// case *Blob:
// // o is a Blob
// case *Tag:
// // o is a Tag
// }
// }
//
// This interface is intentionally different from plumbing.EncodedObject, which
// is a lower level interface used by storage implementations to read and write
// objects in its encoded form.
type Object interface {
ID() plumbing.Hash
Type() plumbing.ObjectType
Decode(plumbing.EncodedObject) error
Encode(plumbing.EncodedObject) error
}
// GetObject gets an object from an object storer and decodes it.
func GetObject(s storer.EncodedObjectStorer, h plumbing.Hash) (Object, error) {
o, err := s.EncodedObject(plumbing.AnyObject, h)
if err != nil {
return nil, err
}
return DecodeObject(s, o)
}
// DecodeObject decodes an encoded object into an Object and associates it to
// the given object storer.
func DecodeObject(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (Object, error) {
switch o.Type() {
case plumbing.CommitObject:
return DecodeCommit(s, o)
case plumbing.TreeObject:
return DecodeTree(s, o)
case plumbing.BlobObject:
return DecodeBlob(o)
case plumbing.TagObject:
return DecodeTag(s, o)
default:
return nil, plumbing.ErrInvalidType
}
}
// DateFormat is the format being used in the original git implementation
const DateFormat = "Mon Jan 02 15:04:05 2006 -0700"
// Signature is used to identify who and when created a commit or tag.
type Signature struct {
// Name represents a person name. It is an arbitrary string.
Name string
// Email is an email, but it cannot be assumed to be well-formed.
Email string
// When is the timestamp of the signature.
When time.Time
}
// Decode decodes a byte slice into a signature
func (s *Signature) Decode(b []byte) {
open := bytes.LastIndexByte(b, '<')
close := bytes.LastIndexByte(b, '>')
if open == -1 || close == -1 {
return
}
if close < open {
return
}
s.Name = string(bytes.Trim(b[:open], " "))
s.Email = string(b[open+1 : close])
hasTime := close+2 < len(b)
if hasTime {
s.decodeTimeAndTimeZone(b[close+2:])
}
}
// Encode encodes a Signature into a writer.
func (s *Signature) Encode(w io.Writer) error {
if _, err := fmt.Fprintf(w, "%s <%s> ", s.Name, s.Email); err != nil {
return err
}
if err := s.encodeTimeAndTimeZone(w); err != nil {
return err
}
return nil
}
var timeZoneLength = 5
func (s *Signature) decodeTimeAndTimeZone(b []byte) {
space := bytes.IndexByte(b, ' ')
if space == -1 {
space = len(b)
}
ts, err := strconv.ParseInt(string(b[:space]), 10, 64)
if err != nil {
return
}
s.When = time.Unix(ts, 0).In(time.UTC)
var tzStart = space + 1
if tzStart >= len(b) || tzStart+timeZoneLength > len(b) {
return
}
timezone := string(b[tzStart : tzStart+timeZoneLength])
tzhours, err1 := strconv.ParseInt(timezone[0:3], 10, 64)
tzmins, err2 := strconv.ParseInt(timezone[3:], 10, 64)
if err1 != nil || err2 != nil {
return
}
if tzhours < 0 {
tzmins *= -1
}
tz := time.FixedZone("", int(tzhours*60*60+tzmins*60))
s.When = s.When.In(tz)
}
func (s *Signature) encodeTimeAndTimeZone(w io.Writer) error {
u := s.When.Unix()
if u < 0 {
u = 0
}
_, err := fmt.Fprintf(w, "%d %s", u, s.When.Format("-0700"))
return err
}
func (s *Signature) String() string {
return fmt.Sprintf("%s <%s>", s.Name, s.Email)
}
// ObjectIter provides an iterator for a set of objects.
type ObjectIter struct {
storer.EncodedObjectIter
s storer.EncodedObjectStorer
}
// NewObjectIter takes a storer.EncodedObjectStorer and a
// storer.EncodedObjectIter and returns an *ObjectIter that iterates over all
// objects contained in the storer.EncodedObjectIter.
func NewObjectIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *ObjectIter {
return &ObjectIter{iter, s}
}
// Next moves the iterator to the next object and returns a pointer to it. If
// there are no more objects, it returns io.EOF.
func (iter *ObjectIter) Next() (Object, error) {
for {
obj, err := iter.EncodedObjectIter.Next()
if err != nil {
return nil, err
}
o, err := iter.toObject(obj)
if err == plumbing.ErrInvalidType {
continue
}
if err != nil {
return nil, err
}
return o, nil
}
}
// ForEach call the cb function for each object contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *ObjectIter) ForEach(cb func(Object) error) error {
return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
o, err := iter.toObject(obj)
if err == plumbing.ErrInvalidType {
return nil
}
if err != nil {
return err
}
return cb(o)
})
}
func (iter *ObjectIter) toObject(obj plumbing.EncodedObject) (Object, error) {
switch obj.Type() {
case plumbing.BlobObject:
blob := &Blob{}
return blob, blob.Decode(obj)
case plumbing.TreeObject:
tree := &Tree{s: iter.s}
return tree, tree.Decode(obj)
case plumbing.CommitObject:
commit := &Commit{}
return commit, commit.Decode(obj)
case plumbing.TagObject:
tag := &Tag{}
return tag, tag.Decode(obj)
default:
return nil, plumbing.ErrInvalidType
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/patch.go
================================================
package object
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"strconv"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
fdiff "github.com/go-git/go-git/v5/plumbing/format/diff"
"github.com/go-git/go-git/v5/utils/diff"
dmp "github.com/sergi/go-diff/diffmatchpatch"
)
var (
ErrCanceled = errors.New("operation canceled")
)
func getPatch(message string, changes ...*Change) (*Patch, error) {
ctx := context.Background()
return getPatchContext(ctx, message, changes...)
}
func getPatchContext(ctx context.Context, message string, changes ...*Change) (*Patch, error) {
var filePatches []fdiff.FilePatch
for _, c := range changes {
select {
case <-ctx.Done():
return nil, ErrCanceled
default:
}
fp, err := filePatchWithContext(ctx, c)
if err != nil {
return nil, err
}
filePatches = append(filePatches, fp)
}
return &Patch{message, filePatches}, nil
}
func filePatchWithContext(ctx context.Context, c *Change) (fdiff.FilePatch, error) {
from, to, err := c.Files()
if err != nil {
return nil, err
}
fromContent, fIsBinary, err := fileContent(from)
if err != nil {
return nil, err
}
toContent, tIsBinary, err := fileContent(to)
if err != nil {
return nil, err
}
if fIsBinary || tIsBinary {
return &textFilePatch{from: c.From, to: c.To}, nil
}
diffs := diff.Do(fromContent, toContent)
var chunks []fdiff.Chunk
for _, d := range diffs {
select {
case <-ctx.Done():
return nil, ErrCanceled
default:
}
var op fdiff.Operation
switch d.Type {
case dmp.DiffEqual:
op = fdiff.Equal
case dmp.DiffDelete:
op = fdiff.Delete
case dmp.DiffInsert:
op = fdiff.Add
}
chunks = append(chunks, &textChunk{d.Text, op})
}
return &textFilePatch{
chunks: chunks,
from: c.From,
to: c.To,
}, nil
}
func fileContent(f *File) (content string, isBinary bool, err error) {
if f == nil {
return
}
isBinary, err = f.IsBinary()
if err != nil || isBinary {
return
}
content, err = f.Contents()
return
}
// Patch is an implementation of fdiff.Patch interface
type Patch struct {
message string
filePatches []fdiff.FilePatch
}
func (p *Patch) FilePatches() []fdiff.FilePatch {
return p.filePatches
}
func (p *Patch) Message() string {
return p.message
}
func (p *Patch) Encode(w io.Writer) error {
ue := fdiff.NewUnifiedEncoder(w, fdiff.DefaultContextLines)
return ue.Encode(p)
}
func (p *Patch) Stats() FileStats {
return getFileStatsFromFilePatches(p.FilePatches())
}
func (p *Patch) String() string {
buf := bytes.NewBuffer(nil)
err := p.Encode(buf)
if err != nil {
return fmt.Sprintf("malformed patch: %s", err.Error())
}
return buf.String()
}
// changeEntryWrapper is an implementation of fdiff.File interface
type changeEntryWrapper struct {
ce ChangeEntry
}
func (f *changeEntryWrapper) Hash() plumbing.Hash {
if !f.ce.TreeEntry.Mode.IsFile() {
return plumbing.ZeroHash
}
return f.ce.TreeEntry.Hash
}
func (f *changeEntryWrapper) Mode() filemode.FileMode {
return f.ce.TreeEntry.Mode
}
func (f *changeEntryWrapper) Path() string {
if !f.ce.TreeEntry.Mode.IsFile() {
return ""
}
return f.ce.Name
}
func (f *changeEntryWrapper) Empty() bool {
return !f.ce.TreeEntry.Mode.IsFile()
}
// textFilePatch is an implementation of fdiff.FilePatch interface
type textFilePatch struct {
chunks []fdiff.Chunk
from, to ChangeEntry
}
func (tf *textFilePatch) Files() (from fdiff.File, to fdiff.File) {
f := &changeEntryWrapper{tf.from}
t := &changeEntryWrapper{tf.to}
if !f.Empty() {
from = f
}
if !t.Empty() {
to = t
}
return
}
func (tf *textFilePatch) IsBinary() bool {
return len(tf.chunks) == 0
}
func (tf *textFilePatch) Chunks() []fdiff.Chunk {
return tf.chunks
}
// textChunk is an implementation of fdiff.Chunk interface
type textChunk struct {
content string
op fdiff.Operation
}
func (t *textChunk) Content() string {
return t.content
}
func (t *textChunk) Type() fdiff.Operation {
return t.op
}
// FileStat stores the status of changes in content of a file.
type FileStat struct {
Name string
Addition int
Deletion int
}
func (fs FileStat) String() string {
return printStat([]FileStat{fs})
}
// FileStats is a collection of FileStat.
type FileStats []FileStat
func (fileStats FileStats) String() string {
return printStat(fileStats)
}
// printStat prints the stats of changes in content of files.
// Original implementation: https://github.com/git/git/blob/1a87c842ece327d03d08096395969aca5e0a6996/diff.c#L2615
// Parts of the output:
// |<+++/--->
// example: " main.go | 10 +++++++--- "
func printStat(fileStats []FileStat) string {
maxGraphWidth := uint(53)
maxNameLen := 0
maxChangeLen := 0
scaleLinear := func(it, width, max uint) uint {
if it == 0 || max == 0 {
return 0
}
return 1 + (it * (width - 1) / max)
}
for _, fs := range fileStats {
if len(fs.Name) > maxNameLen {
maxNameLen = len(fs.Name)
}
changes := strconv.Itoa(fs.Addition + fs.Deletion)
if len(changes) > maxChangeLen {
maxChangeLen = len(changes)
}
}
result := ""
for _, fs := range fileStats {
add := uint(fs.Addition)
del := uint(fs.Deletion)
np := maxNameLen - len(fs.Name)
cp := maxChangeLen - len(strconv.Itoa(fs.Addition+fs.Deletion))
total := add + del
if total > maxGraphWidth {
add = scaleLinear(add, maxGraphWidth, total)
del = scaleLinear(del, maxGraphWidth, total)
}
adds := strings.Repeat("+", int(add))
dels := strings.Repeat("-", int(del))
namePad := strings.Repeat(" ", np)
changePad := strings.Repeat(" ", cp)
result += fmt.Sprintf(" %s%s | %s%d %s%s\n", fs.Name, namePad, changePad, total, adds, dels)
}
return result
}
func getFileStatsFromFilePatches(filePatches []fdiff.FilePatch) FileStats {
var fileStats FileStats
for _, fp := range filePatches {
// ignore empty patches (binary files, submodule refs updates)
if len(fp.Chunks()) == 0 {
continue
}
cs := FileStat{}
from, to := fp.Files()
if from == nil {
// New File is created.
cs.Name = to.Path()
} else if to == nil {
// File is deleted.
cs.Name = from.Path()
} else if from.Path() != to.Path() {
// File is renamed.
cs.Name = fmt.Sprintf("%s => %s", from.Path(), to.Path())
} else {
cs.Name = from.Path()
}
for _, chunk := range fp.Chunks() {
s := chunk.Content()
if len(s) == 0 {
continue
}
switch chunk.Type() {
case fdiff.Add:
cs.Addition += strings.Count(s, "\n")
if s[len(s)-1] != '\n' {
cs.Addition++
}
case fdiff.Delete:
cs.Deletion += strings.Count(s, "\n")
if s[len(s)-1] != '\n' {
cs.Deletion++
}
}
}
fileStats = append(fileStats, cs)
}
return fileStats
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/rename.go
================================================
package object
import (
"errors"
"io"
"sort"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/merkletrie"
)
// DetectRenames detects the renames in the given changes on two trees with
// the given options. It will return the given changes grouping additions and
// deletions into modifications when possible.
// If options is nil, the default diff tree options will be used.
func DetectRenames(
changes Changes,
opts *DiffTreeOptions,
) (Changes, error) {
if opts == nil {
opts = DefaultDiffTreeOptions
}
detector := &renameDetector{
renameScore: int(opts.RenameScore),
renameLimit: int(opts.RenameLimit),
onlyExact: opts.OnlyExactRenames,
}
for _, c := range changes {
action, err := c.Action()
if err != nil {
return nil, err
}
switch action {
case merkletrie.Insert:
detector.added = append(detector.added, c)
case merkletrie.Delete:
detector.deleted = append(detector.deleted, c)
default:
detector.modified = append(detector.modified, c)
}
}
return detector.detect()
}
// renameDetector will detect and resolve renames in a set of changes.
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/RenameDetector.java
type renameDetector struct {
added []*Change
deleted []*Change
modified []*Change
renameScore int
renameLimit int
onlyExact bool
}
// detectExactRenames detects matches files that were deleted with files that
// were added where the hash is the same on both. If there are multiple targets
// the one with the most similar path will be chosen as the rename and the
// rest as either deletions or additions.
func (d *renameDetector) detectExactRenames() {
added := groupChangesByHash(d.added)
deletes := groupChangesByHash(d.deleted)
var uniqueAdds []*Change
var nonUniqueAdds [][]*Change
var addedLeft []*Change
for _, cs := range added {
if len(cs) == 1 {
uniqueAdds = append(uniqueAdds, cs[0])
} else {
nonUniqueAdds = append(nonUniqueAdds, cs)
}
}
for _, c := range uniqueAdds {
hash := changeHash(c)
deleted := deletes[hash]
if len(deleted) == 1 {
if sameMode(c, deleted[0]) {
d.modified = append(d.modified, &Change{From: deleted[0].From, To: c.To})
delete(deletes, hash)
} else {
addedLeft = append(addedLeft, c)
}
} else if len(deleted) > 1 {
bestMatch := bestNameMatch(c, deleted)
if bestMatch != nil && sameMode(c, bestMatch) {
d.modified = append(d.modified, &Change{From: bestMatch.From, To: c.To})
delete(deletes, hash)
var newDeletes = make([]*Change, 0, len(deleted)-1)
for _, d := range deleted {
if d != bestMatch {
newDeletes = append(newDeletes, d)
}
}
deletes[hash] = newDeletes
}
} else {
addedLeft = append(addedLeft, c)
}
}
for _, added := range nonUniqueAdds {
hash := changeHash(added[0])
deleted := deletes[hash]
if len(deleted) == 1 {
deleted := deleted[0]
bestMatch := bestNameMatch(deleted, added)
if bestMatch != nil && sameMode(deleted, bestMatch) {
d.modified = append(d.modified, &Change{From: deleted.From, To: bestMatch.To})
delete(deletes, hash)
for _, c := range added {
if c != bestMatch {
addedLeft = append(addedLeft, c)
}
}
} else {
addedLeft = append(addedLeft, added...)
}
} else if len(deleted) > 1 {
maxSize := len(deleted) * len(added)
if d.renameLimit > 0 && d.renameLimit < maxSize {
maxSize = d.renameLimit
}
matrix := make(similarityMatrix, 0, maxSize)
for delIdx, del := range deleted {
deletedName := changeName(del)
for addIdx, add := range added {
addedName := changeName(add)
score := nameSimilarityScore(addedName, deletedName)
matrix = append(matrix, similarityPair{added: addIdx, deleted: delIdx, score: score})
if len(matrix) >= maxSize {
break
}
}
if len(matrix) >= maxSize {
break
}
}
sort.Stable(matrix)
usedAdds := make(map[*Change]struct{})
usedDeletes := make(map[*Change]struct{})
for i := len(matrix) - 1; i >= 0; i-- {
del := deleted[matrix[i].deleted]
add := added[matrix[i].added]
if add == nil || del == nil {
// it was already matched
continue
}
usedAdds[add] = struct{}{}
usedDeletes[del] = struct{}{}
d.modified = append(d.modified, &Change{From: del.From, To: add.To})
added[matrix[i].added] = nil
deleted[matrix[i].deleted] = nil
}
for _, c := range added {
if _, ok := usedAdds[c]; !ok && c != nil {
addedLeft = append(addedLeft, c)
}
}
var newDeletes = make([]*Change, 0, len(deleted)-len(usedDeletes))
for _, c := range deleted {
if _, ok := usedDeletes[c]; !ok && c != nil {
newDeletes = append(newDeletes, c)
}
}
deletes[hash] = newDeletes
} else {
addedLeft = append(addedLeft, added...)
}
}
d.added = addedLeft
d.deleted = nil
for _, dels := range deletes {
d.deleted = append(d.deleted, dels...)
}
}
// detectContentRenames detects renames based on the similarity of the content
// in the files by building a matrix of pairs between sources and destinations
// and matching by the highest score.
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityRenameDetector.java
func (d *renameDetector) detectContentRenames() error {
cnt := max(len(d.added), len(d.deleted))
if d.renameLimit > 0 && cnt > d.renameLimit {
return nil
}
srcs, dsts := d.deleted, d.added
matrix, err := buildSimilarityMatrix(srcs, dsts, d.renameScore)
if err != nil {
return err
}
renames := make([]*Change, 0, min(len(matrix), len(dsts)))
// Match rename pairs on a first come, first serve basis until
// we have looked at everything that is above the minimum score.
for i := len(matrix) - 1; i >= 0; i-- {
pair := matrix[i]
src := srcs[pair.deleted]
dst := dsts[pair.added]
if dst == nil || src == nil {
// It was already matched before
continue
}
renames = append(renames, &Change{From: src.From, To: dst.To})
// Claim destination and source as matched
dsts[pair.added] = nil
srcs[pair.deleted] = nil
}
d.modified = append(d.modified, renames...)
d.added = compactChanges(dsts)
d.deleted = compactChanges(srcs)
return nil
}
func (d *renameDetector) detect() (Changes, error) {
if len(d.added) > 0 && len(d.deleted) > 0 {
d.detectExactRenames()
if !d.onlyExact {
if err := d.detectContentRenames(); err != nil {
return nil, err
}
}
}
result := make(Changes, 0, len(d.added)+len(d.deleted)+len(d.modified))
result = append(result, d.added...)
result = append(result, d.deleted...)
result = append(result, d.modified...)
sort.Stable(result)
return result, nil
}
func bestNameMatch(change *Change, changes []*Change) *Change {
var best *Change
var bestScore int
cname := changeName(change)
for _, c := range changes {
score := nameSimilarityScore(cname, changeName(c))
if score > bestScore {
bestScore = score
best = c
}
}
return best
}
func nameSimilarityScore(a, b string) int {
aDirLen := strings.LastIndexByte(a, '/') + 1
bDirLen := strings.LastIndexByte(b, '/') + 1
dirMin := min(aDirLen, bDirLen)
dirMax := max(aDirLen, bDirLen)
var dirScoreLtr, dirScoreRtl int
if dirMax == 0 {
dirScoreLtr = 100
dirScoreRtl = 100
} else {
var dirSim int
for ; dirSim < dirMin; dirSim++ {
if a[dirSim] != b[dirSim] {
break
}
}
dirScoreLtr = dirSim * 100 / dirMax
if dirScoreLtr == 100 {
dirScoreRtl = 100
} else {
for dirSim = 0; dirSim < dirMin; dirSim++ {
if a[aDirLen-1-dirSim] != b[bDirLen-1-dirSim] {
break
}
}
dirScoreRtl = dirSim * 100 / dirMax
}
}
fileMin := min(len(a)-aDirLen, len(b)-bDirLen)
fileMax := max(len(a)-aDirLen, len(b)-bDirLen)
fileSim := 0
for ; fileSim < fileMin; fileSim++ {
if a[len(a)-1-fileSim] != b[len(b)-1-fileSim] {
break
}
}
fileScore := fileSim * 100 / fileMax
return (((dirScoreLtr + dirScoreRtl) * 25) + (fileScore * 50)) / 100
}
func changeName(c *Change) string {
if c.To != empty {
return c.To.Name
}
return c.From.Name
}
func changeHash(c *Change) plumbing.Hash {
if c.To != empty {
return c.To.TreeEntry.Hash
}
return c.From.TreeEntry.Hash
}
func changeMode(c *Change) filemode.FileMode {
if c.To != empty {
return c.To.TreeEntry.Mode
}
return c.From.TreeEntry.Mode
}
func sameMode(a, b *Change) bool {
return changeMode(a) == changeMode(b)
}
func groupChangesByHash(changes []*Change) map[plumbing.Hash][]*Change {
var result = make(map[plumbing.Hash][]*Change)
for _, c := range changes {
hash := changeHash(c)
result[hash] = append(result[hash], c)
}
return result
}
type similarityMatrix []similarityPair
func (m similarityMatrix) Len() int { return len(m) }
func (m similarityMatrix) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m similarityMatrix) Less(i, j int) bool {
if m[i].score == m[j].score {
if m[i].added == m[j].added {
return m[i].deleted < m[j].deleted
}
return m[i].added < m[j].added
}
return m[i].score < m[j].score
}
type similarityPair struct {
// index of the added file
added int
// index of the deleted file
deleted int
// similarity score
score int
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
const maxMatrixSize = 10000
func buildSimilarityMatrix(srcs, dsts []*Change, renameScore int) (similarityMatrix, error) {
// Allocate for the worst-case scenario where every pair has a score
// that we need to consider. We might not need that many.
matrixSize := len(srcs) * len(dsts)
if matrixSize > maxMatrixSize {
matrixSize = maxMatrixSize
}
matrix := make(similarityMatrix, 0, matrixSize)
srcSizes := make([]int64, len(srcs))
dstSizes := make([]int64, len(dsts))
dstTooLarge := make(map[int]bool)
// Consider each pair of files, if the score is above the minimum
// threshold we need to record that scoring in the matrix so we can
// later find the best matches.
outerLoop:
for srcIdx, src := range srcs {
if changeMode(src) != filemode.Regular {
continue
}
// Declare the from file and the similarity index here to be able to
// reuse it inside the inner loop. The reason to not initialize them
// here is so we can skip the initialization in case they happen to
// not be needed later. They will be initialized inside the inner
// loop if and only if they're needed and reused in subsequent passes.
var from *File
var s *similarityIndex
var err error
for dstIdx, dst := range dsts {
if changeMode(dst) != filemode.Regular {
continue
}
if dstTooLarge[dstIdx] {
continue
}
var to *File
srcSize := srcSizes[srcIdx]
if srcSize == 0 {
from, _, err = src.Files()
if err != nil {
return nil, err
}
srcSize = from.Size + 1
srcSizes[srcIdx] = srcSize
}
dstSize := dstSizes[dstIdx]
if dstSize == 0 {
_, to, err = dst.Files()
if err != nil {
return nil, err
}
dstSize = to.Size + 1
dstSizes[dstIdx] = dstSize
}
min, max := srcSize, dstSize
if dstSize < srcSize {
min = dstSize
max = srcSize
}
if int(min*100/max) < renameScore {
// File sizes are too different to be a match
continue
}
if s == nil {
s, err = fileSimilarityIndex(from)
if err != nil {
if err == errIndexFull {
continue outerLoop
}
return nil, err
}
}
if to == nil {
_, to, err = dst.Files()
if err != nil {
return nil, err
}
}
di, err := fileSimilarityIndex(to)
if err != nil {
if err == errIndexFull {
dstTooLarge[dstIdx] = true
}
return nil, err
}
contentScore := s.score(di, 10000)
// The name score returns a value between 0 and 100, so we need to
// convert it to the same range as the content score.
nameScore := nameSimilarityScore(src.From.Name, dst.To.Name) * 100
score := (contentScore*99 + nameScore*1) / 10000
if score < renameScore {
continue
}
matrix = append(matrix, similarityPair{added: dstIdx, deleted: srcIdx, score: score})
}
}
sort.Stable(matrix)
return matrix, nil
}
func compactChanges(changes []*Change) []*Change {
var result []*Change
for _, c := range changes {
if c != nil {
result = append(result, c)
}
}
return result
}
const (
keyShift = 32
maxCountValue = (1 << keyShift) - 1
)
var errIndexFull = errors.New("index is full")
// similarityIndex is an index structure of lines/blocks in one file.
// This structure can be used to compute an approximation of the similarity
// between two files.
// To save space in memory, this index uses a space efficient encoding which
// will not exceed 1MiB per instance. The index starts out at a smaller size
// (closer to 2KiB), but may grow as more distinct blocks within the scanned
// file are discovered.
// see: https://github.com/eclipse/jgit/blob/master/org.eclipse.jgit/src/org/eclipse/jgit/diff/SimilarityIndex.java
type similarityIndex struct {
hashed uint64
// number of non-zero entries in hashes
numHashes int
growAt int
hashes []keyCountPair
hashBits int
}
func fileSimilarityIndex(f *File) (*similarityIndex, error) {
idx := newSimilarityIndex()
if err := idx.hash(f); err != nil {
return nil, err
}
sort.Stable(keyCountPairs(idx.hashes))
return idx, nil
}
func newSimilarityIndex() *similarityIndex {
return &similarityIndex{
hashBits: 8,
hashes: make([]keyCountPair, 1<<8),
growAt: shouldGrowAt(8),
}
}
func (i *similarityIndex) hash(f *File) error {
isBin, err := f.IsBinary()
if err != nil {
return err
}
r, err := f.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(r, &err)
return i.hashContent(r, f.Size, isBin)
}
func (i *similarityIndex) hashContent(r io.Reader, size int64, isBin bool) error {
var buf = make([]byte, 4096)
var ptr, cnt int
remaining := size
for 0 < remaining {
hash := 5381
var blockHashedCnt uint64
// Hash one line or block, whatever happens first
n := int64(0)
for {
if ptr == cnt {
ptr = 0
var err error
cnt, err = io.ReadFull(r, buf)
if err != nil && err != io.ErrUnexpectedEOF {
return err
}
if cnt == 0 {
return io.EOF
}
}
n++
c := buf[ptr] & 0xff
ptr++
// Ignore CR in CRLF sequence if it's text
if !isBin && c == '\r' && ptr < cnt && buf[ptr] == '\n' {
continue
}
blockHashedCnt++
if c == '\n' {
break
}
hash = (hash << 5) + hash + int(c)
if n >= 64 || n >= remaining {
break
}
}
i.hashed += blockHashedCnt
if err := i.add(hash, blockHashedCnt); err != nil {
return err
}
remaining -= n
}
return nil
}
// score computes the similarity score between this index and another one.
// A region of a file is defined as a line in a text file or a fixed-size
// block in a binary file. To prepare an index, each region in the file is
// hashed; the values and counts of hashes are retained in a sorted table.
// Define the similarity fraction F as the count of matching regions between
// the two files divided between the maximum count of regions in either file.
// The similarity score is F multiplied by the maxScore constant, yielding a
// range [0, maxScore]. It is defined as maxScore for the degenerate case of
// two empty files.
// The similarity score is symmetrical; i.e. a.score(b) == b.score(a).
func (i *similarityIndex) score(other *similarityIndex, maxScore int) int {
var maxHashed = i.hashed
if maxHashed < other.hashed {
maxHashed = other.hashed
}
if maxHashed == 0 {
return maxScore
}
return int(i.common(other) * uint64(maxScore) / maxHashed)
}
func (i *similarityIndex) common(dst *similarityIndex) uint64 {
srcIdx, dstIdx := 0, 0
if i.numHashes == 0 || dst.numHashes == 0 {
return 0
}
var common uint64
srcKey, dstKey := i.hashes[srcIdx].key(), dst.hashes[dstIdx].key()
for {
if srcKey == dstKey {
srcCnt, dstCnt := i.hashes[srcIdx].count(), dst.hashes[dstIdx].count()
if srcCnt < dstCnt {
common += srcCnt
} else {
common += dstCnt
}
srcIdx++
if srcIdx == len(i.hashes) {
break
}
srcKey = i.hashes[srcIdx].key()
dstIdx++
if dstIdx == len(dst.hashes) {
break
}
dstKey = dst.hashes[dstIdx].key()
} else if srcKey < dstKey {
// Region of src that is not in dst
srcIdx++
if srcIdx == len(i.hashes) {
break
}
srcKey = i.hashes[srcIdx].key()
} else {
// Region of dst that is not in src
dstIdx++
if dstIdx == len(dst.hashes) {
break
}
dstKey = dst.hashes[dstIdx].key()
}
}
return common
}
func (i *similarityIndex) add(key int, cnt uint64) error {
key = int(uint32(key) * 0x9e370001 >> 1)
j := i.slot(key)
for {
v := i.hashes[j]
if v == 0 {
// It's an empty slot, so we can store it here.
if i.growAt <= i.numHashes {
if err := i.grow(); err != nil {
return err
}
j = i.slot(key)
continue
}
var err error
i.hashes[j], err = newKeyCountPair(key, cnt)
if err != nil {
return err
}
i.numHashes++
return nil
} else if v.key() == key {
// It's the same key, so increment the counter.
var err error
i.hashes[j], err = newKeyCountPair(key, v.count()+cnt)
return err
} else if j+1 >= len(i.hashes) {
j = 0
} else {
j++
}
}
}
type keyCountPair uint64
func newKeyCountPair(key int, cnt uint64) (keyCountPair, error) {
if cnt > maxCountValue {
return 0, errIndexFull
}
return keyCountPair((uint64(key) << keyShift) | cnt), nil
}
func (p keyCountPair) key() int {
return int(p >> keyShift)
}
func (p keyCountPair) count() uint64 {
return uint64(p) & maxCountValue
}
func (i *similarityIndex) slot(key int) int {
// We use 31 - hashBits because the upper bit was already forced
// to be 0 and we want the remaining high bits to be used as the
// table slot.
return int(uint32(key) >> uint(31-i.hashBits))
}
func shouldGrowAt(hashBits int) int {
return (1 << uint(hashBits)) * (hashBits - 3) / hashBits
}
func (i *similarityIndex) grow() error {
if i.hashBits == 30 {
return errIndexFull
}
old := i.hashes
i.hashBits++
i.growAt = shouldGrowAt(i.hashBits)
// TODO(erizocosmico): find a way to check if it will OOM and return
// errIndexFull instead.
i.hashes = make([]keyCountPair, 1<= len(i.hashes) {
j = 0
}
}
i.hashes[j] = v
}
}
return nil
}
type keyCountPairs []keyCountPair
func (p keyCountPairs) Len() int { return len(p) }
func (p keyCountPairs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p keyCountPairs) Less(i, j int) bool { return p[i] < p[j] }
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/signature.go
================================================
package object
import "bytes"
const (
signatureTypeUnknown signatureType = iota
signatureTypeOpenPGP
signatureTypeX509
signatureTypeSSH
)
var (
// openPGPSignatureFormat is the format of an OpenPGP signature.
openPGPSignatureFormat = signatureFormat{
[]byte("-----BEGIN PGP SIGNATURE-----"),
[]byte("-----BEGIN PGP MESSAGE-----"),
}
// x509SignatureFormat is the format of an X509 signature, which is
// a PKCS#7 (S/MIME) signature.
x509SignatureFormat = signatureFormat{
[]byte("-----BEGIN CERTIFICATE-----"),
[]byte("-----BEGIN SIGNED MESSAGE-----"),
}
// sshSignatureFormat is the format of an SSH signature.
sshSignatureFormat = signatureFormat{
[]byte("-----BEGIN SSH SIGNATURE-----"),
}
)
var (
// knownSignatureFormats is a map of known signature formats, indexed by
// their signatureType.
knownSignatureFormats = map[signatureType]signatureFormat{
signatureTypeOpenPGP: openPGPSignatureFormat,
signatureTypeX509: x509SignatureFormat,
signatureTypeSSH: sshSignatureFormat,
}
)
// signatureType represents the type of the signature.
type signatureType int8
// signatureFormat represents the beginning of a signature.
type signatureFormat [][]byte
// typeForSignature returns the type of the signature based on its format.
func typeForSignature(b []byte) signatureType {
for t, i := range knownSignatureFormats {
for _, begin := range i {
if bytes.HasPrefix(b, begin) {
return t
}
}
}
return signatureTypeUnknown
}
// parseSignedBytes returns the position of the last signature block found in
// the given bytes. If no signature block is found, it returns -1.
//
// When multiple signature blocks are found, the position of the last one is
// returned. Any tailing bytes after this signature block start should be
// considered part of the signature.
//
// Given this, it would be safe to use the returned position to split the bytes
// into two parts: the first part containing the message, the second part
// containing the signature.
//
// Example:
//
// message := []byte(`Message with signature
//
// -----BEGIN SSH SIGNATURE-----
// ...`)
//
// var signature string
// if pos, _ := parseSignedBytes(message); pos != -1 {
// signature = string(message[pos:])
// message = message[:pos]
// }
//
// This logic is on par with git's gpg-interface.c:parse_signed_buffer().
// https://github.com/git/git/blob/7c2ef319c52c4997256f5807564523dfd4acdfc7/gpg-interface.c#L668
func parseSignedBytes(b []byte) (int, signatureType) {
var n, match = 0, -1
var t signatureType
for n < len(b) {
var i = b[n:]
if st := typeForSignature(i); st != signatureTypeUnknown {
match = n
t = st
}
if eol := bytes.IndexByte(i, '\n'); eol >= 0 {
n += eol + 1
continue
}
// If we reach this point, we've reached the end.
break
}
return match, t
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/tag.go
================================================
package object
import (
"bytes"
"fmt"
"io"
"strings"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
// Tag represents an annotated tag object. It points to a single git object of
// any type, but tags typically are applied to commit or blob objects. It
// provides a reference that associates the target with a tag name. It also
// contains meta-information about the tag, including the tagger, tag date and
// message.
//
// Note that this is not used for lightweight tags.
//
// https://git-scm.com/book/en/v2/Git-Internals-Git-References#Tags
type Tag struct {
// Hash of the tag.
Hash plumbing.Hash
// Name of the tag.
Name string
// Tagger is the one who created the tag.
Tagger Signature
// Message is an arbitrary text message.
Message string
// PGPSignature is the PGP signature of the tag.
PGPSignature string
// TargetType is the object type of the target.
TargetType plumbing.ObjectType
// Target is the hash of the target object.
Target plumbing.Hash
s storer.EncodedObjectStorer
}
// GetTag gets a tag from an object storer and decodes it.
func GetTag(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tag, error) {
o, err := s.EncodedObject(plumbing.TagObject, h)
if err != nil {
return nil, err
}
return DecodeTag(s, o)
}
// DecodeTag decodes an encoded object into a *Commit and associates it to the
// given object storer.
func DecodeTag(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tag, error) {
t := &Tag{s: s}
if err := t.Decode(o); err != nil {
return nil, err
}
return t, nil
}
// ID returns the object ID of the tag, not the object that the tag references.
// The returned value will always match the current value of Tag.Hash.
//
// ID is present to fulfill the Object interface.
func (t *Tag) ID() plumbing.Hash {
return t.Hash
}
// Type returns the type of object. It always returns plumbing.TagObject.
//
// Type is present to fulfill the Object interface.
func (t *Tag) Type() plumbing.ObjectType {
return plumbing.TagObject
}
// Decode transforms a plumbing.EncodedObject into a Tag struct.
func (t *Tag) Decode(o plumbing.EncodedObject) (err error) {
if o.Type() != plumbing.TagObject {
return ErrUnsupportedObject
}
t.Hash = o.Hash()
reader, err := o.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(reader, &err)
r := sync.GetBufioReader(reader)
defer sync.PutBufioReader(r)
for {
var line []byte
line, err = r.ReadBytes('\n')
if err != nil && err != io.EOF {
return err
}
line = bytes.TrimSpace(line)
if len(line) == 0 {
break // Start of message
}
split := bytes.SplitN(line, []byte{' '}, 2)
switch string(split[0]) {
case "object":
t.Target = plumbing.NewHash(string(split[1]))
case "type":
t.TargetType, err = plumbing.ParseObjectType(string(split[1]))
if err != nil {
return err
}
case "tag":
t.Name = string(split[1])
case "tagger":
t.Tagger.Decode(split[1])
}
if err == io.EOF {
return nil
}
}
data, err := io.ReadAll(r)
if err != nil {
return err
}
if sm, _ := parseSignedBytes(data); sm >= 0 {
t.PGPSignature = string(data[sm:])
data = data[:sm]
}
t.Message = string(data)
return nil
}
// Encode transforms a Tag into a plumbing.EncodedObject.
func (t *Tag) Encode(o plumbing.EncodedObject) error {
return t.encode(o, true)
}
// EncodeWithoutSignature export a Tag into a plumbing.EncodedObject without the signature (correspond to the payload of the PGP signature).
func (t *Tag) EncodeWithoutSignature(o plumbing.EncodedObject) error {
return t.encode(o, false)
}
func (t *Tag) encode(o plumbing.EncodedObject, includeSig bool) (err error) {
o.SetType(plumbing.TagObject)
w, err := o.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
if _, err = fmt.Fprintf(w,
"object %s\ntype %s\ntag %s\ntagger ",
t.Target.String(), t.TargetType.Bytes(), t.Name); err != nil {
return err
}
if err = t.Tagger.Encode(w); err != nil {
return err
}
if _, err = fmt.Fprint(w, "\n\n"); err != nil {
return err
}
if _, err = fmt.Fprint(w, t.Message); err != nil {
return err
}
// Note that this is highly sensitive to what it sent along in the message.
// Message *always* needs to end with a newline, or else the message and the
// signature will be concatenated into a corrupt object. Since this is a
// lower-level method, we assume you know what you are doing and have already
// done the needful on the message in the caller.
if includeSig {
if _, err = fmt.Fprint(w, t.PGPSignature); err != nil {
return err
}
}
return err
}
// Commit returns the commit pointed to by the tag. If the tag points to a
// different type of object ErrUnsupportedObject will be returned.
func (t *Tag) Commit() (*Commit, error) {
if t.TargetType != plumbing.CommitObject {
return nil, ErrUnsupportedObject
}
o, err := t.s.EncodedObject(plumbing.CommitObject, t.Target)
if err != nil {
return nil, err
}
return DecodeCommit(t.s, o)
}
// Tree returns the tree pointed to by the tag. If the tag points to a commit
// object the tree of that commit will be returned. If the tag does not point
// to a commit or tree object ErrUnsupportedObject will be returned.
func (t *Tag) Tree() (*Tree, error) {
switch t.TargetType {
case plumbing.CommitObject:
c, err := t.Commit()
if err != nil {
return nil, err
}
return c.Tree()
case plumbing.TreeObject:
return GetTree(t.s, t.Target)
default:
return nil, ErrUnsupportedObject
}
}
// Blob returns the blob pointed to by the tag. If the tag points to a
// different type of object ErrUnsupportedObject will be returned.
func (t *Tag) Blob() (*Blob, error) {
if t.TargetType != plumbing.BlobObject {
return nil, ErrUnsupportedObject
}
return GetBlob(t.s, t.Target)
}
// Object returns the object pointed to by the tag.
func (t *Tag) Object() (Object, error) {
o, err := t.s.EncodedObject(t.TargetType, t.Target)
if err != nil {
return nil, err
}
return DecodeObject(t.s, o)
}
// String returns the meta information contained in the tag as a formatted
// string.
func (t *Tag) String() string {
obj, _ := t.Object()
return fmt.Sprintf(
"%s %s\nTagger: %s\nDate: %s\n\n%s\n%s",
plumbing.TagObject, t.Name, t.Tagger.String(), t.Tagger.When.Format(DateFormat),
t.Message, objectAsString(obj),
)
}
// Verify performs PGP verification of the tag with a provided armored
// keyring and returns openpgp.Entity associated with verifying key on success.
func (t *Tag) Verify(armoredKeyRing string) (*openpgp.Entity, error) {
keyRingReader := strings.NewReader(armoredKeyRing)
keyring, err := openpgp.ReadArmoredKeyRing(keyRingReader)
if err != nil {
return nil, err
}
// Extract signature.
signature := strings.NewReader(t.PGPSignature)
encoded := &plumbing.MemoryObject{}
// Encode tag components, excluding signature and get a reader object.
if err := t.EncodeWithoutSignature(encoded); err != nil {
return nil, err
}
er, err := encoded.Reader()
if err != nil {
return nil, err
}
return openpgp.CheckArmoredDetachedSignature(keyring, er, signature, nil)
}
// TagIter provides an iterator for a set of tags.
type TagIter struct {
storer.EncodedObjectIter
s storer.EncodedObjectStorer
}
// NewTagIter takes a storer.EncodedObjectStorer and a
// storer.EncodedObjectIter and returns a *TagIter that iterates over all
// tags contained in the storer.EncodedObjectIter.
//
// Any non-tag object returned by the storer.EncodedObjectIter is skipped.
func NewTagIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TagIter {
return &TagIter{iter, s}
}
// Next moves the iterator to the next tag and returns a pointer to it. If
// there are no more tags, it returns io.EOF.
func (iter *TagIter) Next() (*Tag, error) {
obj, err := iter.EncodedObjectIter.Next()
if err != nil {
return nil, err
}
return DecodeTag(iter.s, obj)
}
// ForEach call the cb function for each tag contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *TagIter) ForEach(cb func(*Tag) error) error {
return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
t, err := DecodeTag(iter.s, obj)
if err != nil {
return err
}
return cb(t)
})
}
func objectAsString(obj Object) string {
switch o := obj.(type) {
case *Commit:
return o.String()
default:
return ""
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/tree.go
================================================
package object
import (
"context"
"errors"
"fmt"
"io"
"path"
"path/filepath"
"sort"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/sync"
)
const (
maxTreeDepth = 1024
startingStackSize = 8
)
// New errors defined by this package.
var (
ErrMaxTreeDepth = errors.New("maximum tree depth exceeded")
ErrFileNotFound = errors.New("file not found")
ErrDirectoryNotFound = errors.New("directory not found")
ErrEntryNotFound = errors.New("entry not found")
ErrEntriesNotSorted = errors.New("entries in tree are not sorted")
)
// Tree is basically like a directory - it references a bunch of other trees
// and/or blobs (i.e. files and sub-directories)
type Tree struct {
Entries []TreeEntry
Hash plumbing.Hash
s storer.EncodedObjectStorer
m map[string]*TreeEntry
t map[string]*Tree // tree path cache
}
// GetTree gets a tree from an object storer and decodes it.
func GetTree(s storer.EncodedObjectStorer, h plumbing.Hash) (*Tree, error) {
o, err := s.EncodedObject(plumbing.TreeObject, h)
if err != nil {
return nil, err
}
return DecodeTree(s, o)
}
// DecodeTree decodes an encoded object into a *Tree and associates it to the
// given object storer.
func DecodeTree(s storer.EncodedObjectStorer, o plumbing.EncodedObject) (*Tree, error) {
t := &Tree{s: s}
if err := t.Decode(o); err != nil {
return nil, err
}
return t, nil
}
// TreeEntry represents a file
type TreeEntry struct {
Name string
Mode filemode.FileMode
Hash plumbing.Hash
}
// File returns the hash of the file identified by the `path` argument.
// The path is interpreted as relative to the tree receiver.
func (t *Tree) File(path string) (*File, error) {
e, err := t.FindEntry(path)
if err != nil {
return nil, ErrFileNotFound
}
blob, err := GetBlob(t.s, e.Hash)
if err != nil {
if err == plumbing.ErrObjectNotFound {
return nil, ErrFileNotFound
}
return nil, err
}
return NewFile(path, e.Mode, blob), nil
}
// Size returns the plaintext size of an object, without reading it
// into memory.
func (t *Tree) Size(path string) (int64, error) {
e, err := t.FindEntry(path)
if err != nil {
return 0, ErrEntryNotFound
}
return t.s.EncodedObjectSize(e.Hash)
}
// Tree returns the tree identified by the `path` argument.
// The path is interpreted as relative to the tree receiver.
func (t *Tree) Tree(path string) (*Tree, error) {
e, err := t.FindEntry(path)
if err != nil {
return nil, ErrDirectoryNotFound
}
tree, err := GetTree(t.s, e.Hash)
if err == plumbing.ErrObjectNotFound {
return nil, ErrDirectoryNotFound
}
return tree, err
}
// TreeEntryFile returns the *File for a given *TreeEntry.
func (t *Tree) TreeEntryFile(e *TreeEntry) (*File, error) {
blob, err := GetBlob(t.s, e.Hash)
if err != nil {
return nil, err
}
return NewFile(e.Name, e.Mode, blob), nil
}
// FindEntry search a TreeEntry in this tree or any subtree.
func (t *Tree) FindEntry(path string) (*TreeEntry, error) {
if t.t == nil {
t.t = make(map[string]*Tree)
}
pathParts := strings.Split(path, "/")
startingTree := t
pathCurrent := ""
// search for the longest path in the tree path cache
for i := len(pathParts) - 1; i > 1; i-- {
path := filepath.Join(pathParts[:i]...)
tree, ok := t.t[path]
if ok {
startingTree = tree
pathParts = pathParts[i:]
pathCurrent = path
break
}
}
var tree *Tree
var err error
for tree = startingTree; len(pathParts) > 1; pathParts = pathParts[1:] {
if tree, err = tree.dir(pathParts[0]); err != nil {
return nil, err
}
pathCurrent = filepath.Join(pathCurrent, pathParts[0])
t.t[pathCurrent] = tree
}
return tree.entry(pathParts[0])
}
func (t *Tree) dir(baseName string) (*Tree, error) {
entry, err := t.entry(baseName)
if err != nil {
return nil, ErrDirectoryNotFound
}
obj, err := t.s.EncodedObject(plumbing.TreeObject, entry.Hash)
if err != nil {
return nil, err
}
tree := &Tree{s: t.s}
err = tree.Decode(obj)
return tree, err
}
func (t *Tree) entry(baseName string) (*TreeEntry, error) {
if t.m == nil {
t.buildMap()
}
entry, ok := t.m[baseName]
if !ok {
return nil, ErrEntryNotFound
}
return entry, nil
}
// Files returns a FileIter allowing to iterate over the Tree
func (t *Tree) Files() *FileIter {
return NewFileIter(t.s, t)
}
// ID returns the object ID of the tree. The returned value will always match
// the current value of Tree.Hash.
//
// ID is present to fulfill the Object interface.
func (t *Tree) ID() plumbing.Hash {
return t.Hash
}
// Type returns the type of object. It always returns plumbing.TreeObject.
func (t *Tree) Type() plumbing.ObjectType {
return plumbing.TreeObject
}
// Decode transform an plumbing.EncodedObject into a Tree struct
func (t *Tree) Decode(o plumbing.EncodedObject) (err error) {
if o.Type() != plumbing.TreeObject {
return ErrUnsupportedObject
}
t.Hash = o.Hash()
if o.Size() == 0 {
return nil
}
t.Entries = nil
t.m = nil
reader, err := o.Reader()
if err != nil {
return err
}
defer ioutil.CheckClose(reader, &err)
r := sync.GetBufioReader(reader)
defer sync.PutBufioReader(r)
for {
str, err := r.ReadString(' ')
if err != nil {
if err == io.EOF {
break
}
return err
}
str = str[:len(str)-1] // strip last byte (' ')
mode, err := filemode.New(str)
if err != nil {
return err
}
name, err := r.ReadString(0)
if err != nil && err != io.EOF {
return err
}
var hash plumbing.Hash
if _, err = io.ReadFull(r, hash[:]); err != nil {
return err
}
baseName := name[:len(name)-1]
t.Entries = append(t.Entries, TreeEntry{
Hash: hash,
Mode: mode,
Name: baseName,
})
}
return nil
}
type TreeEntrySorter []TreeEntry
func (s TreeEntrySorter) Len() int {
return len(s)
}
func (s TreeEntrySorter) Less(i, j int) bool {
name1 := s[i].Name
name2 := s[j].Name
if s[i].Mode == filemode.Dir {
name1 += "/"
}
if s[j].Mode == filemode.Dir {
name2 += "/"
}
return name1 < name2
}
func (s TreeEntrySorter) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// Encode transforms a Tree into a plumbing.EncodedObject.
// The tree entries must be sorted by name.
func (t *Tree) Encode(o plumbing.EncodedObject) (err error) {
o.SetType(plumbing.TreeObject)
w, err := o.Writer()
if err != nil {
return err
}
defer ioutil.CheckClose(w, &err)
if !sort.IsSorted(TreeEntrySorter(t.Entries)) {
return ErrEntriesNotSorted
}
for _, entry := range t.Entries {
if strings.IndexByte(entry.Name, 0) != -1 {
return fmt.Errorf("malformed filename %q", entry.Name)
}
if _, err = fmt.Fprintf(w, "%o %s", entry.Mode, entry.Name); err != nil {
return err
}
if _, err = w.Write([]byte{0x00}); err != nil {
return err
}
if _, err = w.Write(entry.Hash[:]); err != nil {
return err
}
}
return err
}
func (t *Tree) buildMap() {
t.m = make(map[string]*TreeEntry)
for i := 0; i < len(t.Entries); i++ {
t.m[t.Entries[i].Name] = &t.Entries[i]
}
}
// Diff returns a list of changes between this tree and the provided one
func (t *Tree) Diff(to *Tree) (Changes, error) {
return t.DiffContext(context.Background(), to)
}
// DiffContext returns a list of changes between this tree and the provided one
// Error will be returned if context expires. Provided context must be non nil.
//
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
// used are the recommended options DefaultDiffTreeOptions.
func (t *Tree) DiffContext(ctx context.Context, to *Tree) (Changes, error) {
return DiffTreeWithOptions(ctx, t, to, DefaultDiffTreeOptions)
}
// Patch returns a slice of Patch objects with all the changes between trees
// in chunks. This representation can be used to create several diff outputs.
func (t *Tree) Patch(to *Tree) (*Patch, error) {
return t.PatchContext(context.Background(), to)
}
// PatchContext returns a slice of Patch objects with all the changes between
// trees in chunks. This representation can be used to create several diff
// outputs. If context expires, an error will be returned. Provided context must
// be non-nil.
//
// NOTE: Since version 5.1.0 the renames are correctly handled, the settings
// used are the recommended options DefaultDiffTreeOptions.
func (t *Tree) PatchContext(ctx context.Context, to *Tree) (*Patch, error) {
changes, err := t.DiffContext(ctx, to)
if err != nil {
return nil, err
}
return changes.PatchContext(ctx)
}
// treeEntryIter facilitates iterating through the TreeEntry objects in a Tree.
type treeEntryIter struct {
t *Tree
pos int
}
func (iter *treeEntryIter) Next() (TreeEntry, error) {
if iter.pos >= len(iter.t.Entries) {
return TreeEntry{}, io.EOF
}
iter.pos++
return iter.t.Entries[iter.pos-1], nil
}
// TreeWalker provides a means of walking through all of the entries in a Tree.
type TreeWalker struct {
stack []*treeEntryIter
base string
recursive bool
seen map[plumbing.Hash]bool
s storer.EncodedObjectStorer
t *Tree
}
// NewTreeWalker returns a new TreeWalker for the given tree.
//
// It is the caller's responsibility to call Close() when finished with the
// tree walker.
func NewTreeWalker(t *Tree, recursive bool, seen map[plumbing.Hash]bool) *TreeWalker {
stack := make([]*treeEntryIter, 0, startingStackSize)
stack = append(stack, &treeEntryIter{t, 0})
return &TreeWalker{
stack: stack,
recursive: recursive,
seen: seen,
s: t.s,
t: t,
}
}
// Next returns the next object from the tree. Objects are returned in order
// and subtrees are included. After the last object has been returned further
// calls to Next() will return io.EOF.
//
// In the current implementation any objects which cannot be found in the
// underlying repository will be skipped automatically. It is possible that this
// may change in future versions.
func (w *TreeWalker) Next() (name string, entry TreeEntry, err error) {
var obj *Tree
for {
current := len(w.stack) - 1
if current < 0 {
// Nothing left on the stack so we're finished
err = io.EOF
return
}
if current > maxTreeDepth {
// We're probably following bad data or some self-referencing tree
err = ErrMaxTreeDepth
return
}
entry, err = w.stack[current].Next()
if err == io.EOF {
// Finished with the current tree, move back up to the parent
w.stack = w.stack[:current]
w.base, _ = path.Split(w.base)
w.base = strings.TrimSuffix(w.base, "/")
continue
}
if err != nil {
return
}
if w.seen[entry.Hash] {
continue
}
if entry.Mode == filemode.Dir {
obj, err = GetTree(w.s, entry.Hash)
}
name = simpleJoin(w.base, entry.Name)
if err != nil {
err = io.EOF
return
}
break
}
if !w.recursive {
return
}
if obj != nil {
w.stack = append(w.stack, &treeEntryIter{obj, 0})
w.base = simpleJoin(w.base, entry.Name)
}
return
}
// Tree returns the tree that the tree walker most recently operated on.
func (w *TreeWalker) Tree() *Tree {
current := len(w.stack) - 1
if w.stack[current].pos == 0 {
current--
}
if current < 0 {
return nil
}
return w.stack[current].t
}
// Close releases any resources used by the TreeWalker.
func (w *TreeWalker) Close() {
w.stack = nil
}
// TreeIter provides an iterator for a set of trees.
type TreeIter struct {
storer.EncodedObjectIter
s storer.EncodedObjectStorer
}
// NewTreeIter takes a storer.EncodedObjectStorer and a
// storer.EncodedObjectIter and returns a *TreeIter that iterates over all
// tree contained in the storer.EncodedObjectIter.
//
// Any non-tree object returned by the storer.EncodedObjectIter is skipped.
func NewTreeIter(s storer.EncodedObjectStorer, iter storer.EncodedObjectIter) *TreeIter {
return &TreeIter{iter, s}
}
// Next moves the iterator to the next tree and returns a pointer to it. If
// there are no more trees, it returns io.EOF.
func (iter *TreeIter) Next() (*Tree, error) {
for {
obj, err := iter.EncodedObjectIter.Next()
if err != nil {
return nil, err
}
if obj.Type() != plumbing.TreeObject {
continue
}
return DecodeTree(iter.s, obj)
}
}
// ForEach call the cb function for each tree contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *TreeIter) ForEach(cb func(*Tree) error) error {
return iter.EncodedObjectIter.ForEach(func(obj plumbing.EncodedObject) error {
if obj.Type() != plumbing.TreeObject {
return nil
}
t, err := DecodeTree(iter.s, obj)
if err != nil {
return err
}
return cb(t)
})
}
func simpleJoin(parent, child string) string {
if len(parent) > 0 {
return parent + "/" + child
}
return child
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object/treenoder.go
================================================
package object
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// A treenoder is a helper type that wraps git trees into merkletrie
// noders.
//
// As a merkletrie noder doesn't understand the concept of modes (e.g.
// file permissions), the treenoder includes the mode of the git tree in
// the hash, so changes in the modes will be detected as modifications
// to the file contents by the merkletrie difftree algorithm. This is
// consistent with how the "git diff-tree" command works.
type treeNoder struct {
parent *Tree // the root node is its own parent
name string // empty string for the root node
mode filemode.FileMode
hash plumbing.Hash
children []noder.Noder // memoized
}
// NewTreeRootNode returns the root node of a Tree
func NewTreeRootNode(t *Tree) noder.Noder {
if t == nil {
return &treeNoder{}
}
return &treeNoder{
parent: t,
name: "",
mode: filemode.Dir,
hash: t.Hash,
}
}
func (t *treeNoder) Skip() bool {
return false
}
func (t *treeNoder) isRoot() bool {
return t.name == ""
}
func (t *treeNoder) String() string {
return "treeNoder <" + t.name + ">"
}
func (t *treeNoder) Hash() []byte {
if t.mode == filemode.Deprecated {
return append(t.hash[:], filemode.Regular.Bytes()...)
}
return append(t.hash[:], t.mode.Bytes()...)
}
func (t *treeNoder) Name() string {
return t.name
}
func (t *treeNoder) IsDir() bool {
return t.mode == filemode.Dir
}
// Children will return the children of a treenoder as treenoders,
// building them from the children of the wrapped git tree.
func (t *treeNoder) Children() ([]noder.Noder, error) {
if t.mode != filemode.Dir {
return noder.NoChildren, nil
}
// children are memoized for efficiency
if t.children != nil {
return t.children, nil
}
// the parent of the returned children will be ourself as a tree if
// we are a not the root treenoder. The root is special as it
// is is own parent.
parent := t.parent
if !t.isRoot() {
var err error
if parent, err = t.parent.Tree(t.name); err != nil {
return nil, err
}
}
var err error
t.children, err = transformChildren(parent)
return t.children, err
}
// Returns the children of a tree as treenoders.
// Efficiency is key here.
func transformChildren(t *Tree) ([]noder.Noder, error) {
var err error
var e TreeEntry
// there will be more tree entries than children in the tree,
// due to submodules and empty directories, but I think it is still
// worth it to pre-allocate the whole array now, even if sometimes
// is bigger than needed.
ret := make([]noder.Noder, 0, len(t.Entries))
walker := NewTreeWalker(t, false, nil) // don't recurse
// don't defer walker.Close() for efficiency reasons.
for {
_, e, err = walker.Next()
if err == io.EOF {
break
}
if err != nil {
walker.Close()
return nil, err
}
ret = append(ret, &treeNoder{
parent: t,
name: e.Name,
mode: e.Mode,
hash: e.Hash,
})
}
walker.Close()
return ret, nil
}
// len(t.tree.Entries) != the number of elements walked by treewalker
// for some reason because of empty directories, submodules, etc, so we
// have to walk here.
func (t *treeNoder) NumChildren() (int, error) {
children, err := t.Children()
if err != nil {
return 0, err
}
return len(children), nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/object.go
================================================
// package plumbing implement the core interfaces and structs used by go-git
package plumbing
import (
"errors"
"io"
)
var (
ErrObjectNotFound = errors.New("object not found")
// ErrInvalidType is returned when an invalid object type is provided.
ErrInvalidType = errors.New("invalid object type")
)
// Object is a generic representation of any git object
type EncodedObject interface {
Hash() Hash
Type() ObjectType
SetType(ObjectType)
Size() int64
SetSize(int64)
Reader() (io.ReadCloser, error)
Writer() (io.WriteCloser, error)
}
// DeltaObject is an EncodedObject representing a delta.
type DeltaObject interface {
EncodedObject
// BaseHash returns the hash of the object used as base for this delta.
BaseHash() Hash
// ActualHash returns the hash of the object after applying the delta.
ActualHash() Hash
// Size returns the size of the object after applying the delta.
ActualSize() int64
}
// ObjectType internal object type
// Integer values from 0 to 7 map to those exposed by git.
// AnyObject is used to represent any from 0 to 7.
type ObjectType int8
const (
InvalidObject ObjectType = 0
CommitObject ObjectType = 1
TreeObject ObjectType = 2
BlobObject ObjectType = 3
TagObject ObjectType = 4
// 5 reserved for future expansion
OFSDeltaObject ObjectType = 6
REFDeltaObject ObjectType = 7
AnyObject ObjectType = -127
)
func (t ObjectType) String() string {
switch t {
case CommitObject:
return "commit"
case TreeObject:
return "tree"
case BlobObject:
return "blob"
case TagObject:
return "tag"
case OFSDeltaObject:
return "ofs-delta"
case REFDeltaObject:
return "ref-delta"
case AnyObject:
return "any"
default:
return "unknown"
}
}
func (t ObjectType) Bytes() []byte {
return []byte(t.String())
}
// Valid returns true if t is a valid ObjectType.
func (t ObjectType) Valid() bool {
return t >= CommitObject && t <= REFDeltaObject
}
// IsDelta returns true for any ObjectType that represents a delta (i.e.
// REFDeltaObject or OFSDeltaObject).
func (t ObjectType) IsDelta() bool {
return t == REFDeltaObject || t == OFSDeltaObject
}
// ParseObjectType parses a string representation of ObjectType. It returns an
// error on parse failure.
func ParseObjectType(value string) (typ ObjectType, err error) {
switch value {
case "commit":
typ = CommitObject
case "tree":
typ = TreeObject
case "blob":
typ = BlobObject
case "tag":
typ = TagObject
case "ofs-delta":
typ = OFSDeltaObject
case "ref-delta":
typ = REFDeltaObject
default:
err = ErrInvalidType
}
return
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs.go
================================================
package packp
import (
"fmt"
"sort"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage/memory"
)
// AdvRefs values represent the information transmitted on an
// advertised-refs message. Values from this type are not zero-value
// safe, use the New function instead.
type AdvRefs struct {
// Prefix stores prefix payloads.
//
// When using this message over (smart) HTTP, you have to add a pktline
// before the whole thing with the following payload:
//
// '# service=$servicename" LF
//
// Moreover, some (all) git HTTP smart servers will send a flush-pkt
// just after the first pkt-line.
//
// To accommodate both situations, the Prefix field allow you to store
// any data you want to send before the actual pktlines. It will also
// be filled up with whatever is found on the line.
Prefix [][]byte
// Head stores the resolved HEAD reference if present.
// This can be present with git-upload-pack, not with git-receive-pack.
Head *plumbing.Hash
// Capabilities are the capabilities.
Capabilities *capability.List
// References are the hash references.
References map[string]plumbing.Hash
// Peeled are the peeled hash references.
Peeled map[string]plumbing.Hash
// Shallows are the shallow object ids.
Shallows []plumbing.Hash
}
// NewAdvRefs returns a pointer to a new AdvRefs value, ready to be used.
func NewAdvRefs() *AdvRefs {
return &AdvRefs{
Prefix: [][]byte{},
Capabilities: capability.NewList(),
References: make(map[string]plumbing.Hash),
Peeled: make(map[string]plumbing.Hash),
Shallows: []plumbing.Hash{},
}
}
func (a *AdvRefs) AddReference(r *plumbing.Reference) error {
switch r.Type() {
case plumbing.SymbolicReference:
v := fmt.Sprintf("%s:%s", r.Name().String(), r.Target().String())
return a.Capabilities.Add(capability.SymRef, v)
case plumbing.HashReference:
a.References[r.Name().String()] = r.Hash()
default:
return plumbing.ErrInvalidType
}
return nil
}
func (a *AdvRefs) AllReferences() (memory.ReferenceStorage, error) {
s := memory.ReferenceStorage{}
if err := a.addRefs(s); err != nil {
return s, plumbing.NewUnexpectedError(err)
}
return s, nil
}
func (a *AdvRefs) addRefs(s storer.ReferenceStorer) error {
for name, hash := range a.References {
ref := plumbing.NewReferenceFromStrings(name, hash.String())
if err := s.SetReference(ref); err != nil {
return err
}
}
if a.supportSymrefs() {
return a.addSymbolicRefs(s)
}
return a.resolveHead(s)
}
// If the server does not support symrefs capability,
// we need to guess the reference where HEAD is pointing to.
//
// Git versions prior to 1.8.4.3 has an special procedure to get
// the reference where is pointing to HEAD:
// - Check if a reference called master exists. If exists and it
// has the same hash as HEAD hash, we can say that HEAD is pointing to master
// - If master does not exists or does not have the same hash as HEAD,
// order references and check in that order if that reference has the same
// hash than HEAD. If yes, set HEAD pointing to that branch hash
// - If no reference is found, throw an error
func (a *AdvRefs) resolveHead(s storer.ReferenceStorer) error {
if a.Head == nil {
return nil
}
ref, err := s.Reference(plumbing.Master)
// check first if HEAD is pointing to master
if err == nil {
ok, err := a.createHeadIfCorrectReference(ref, s)
if err != nil {
return err
}
if ok {
return nil
}
}
if err != nil && err != plumbing.ErrReferenceNotFound {
return err
}
// From here we are trying to guess the branch that HEAD is pointing
refIter, err := s.IterReferences()
if err != nil {
return err
}
var refNames []string
err = refIter.ForEach(func(r *plumbing.Reference) error {
refNames = append(refNames, string(r.Name()))
return nil
})
if err != nil {
return err
}
sort.Strings(refNames)
var headSet bool
for _, refName := range refNames {
ref, err := s.Reference(plumbing.ReferenceName(refName))
if err != nil {
return err
}
ok, err := a.createHeadIfCorrectReference(ref, s)
if err != nil {
return err
}
if ok {
headSet = true
break
}
}
if !headSet {
return plumbing.ErrReferenceNotFound
}
return nil
}
func (a *AdvRefs) createHeadIfCorrectReference(
reference *plumbing.Reference,
s storer.ReferenceStorer) (bool, error) {
if reference.Hash() == *a.Head {
headRef := plumbing.NewSymbolicReference(plumbing.HEAD, reference.Name())
if err := s.SetReference(headRef); err != nil {
return false, err
}
return true, nil
}
return false, nil
}
func (a *AdvRefs) addSymbolicRefs(s storer.ReferenceStorer) error {
for _, symref := range a.Capabilities.Get(capability.SymRef) {
chunks := strings.Split(symref, ":")
if len(chunks) != 2 {
err := fmt.Errorf("bad number of `:` in symref value (%q)", symref)
return plumbing.NewUnexpectedError(err)
}
name := plumbing.ReferenceName(chunks[0])
target := plumbing.ReferenceName(chunks[1])
ref := plumbing.NewSymbolicReference(name, target)
if err := s.SetReference(ref); err != nil {
return nil
}
}
return nil
}
func (a *AdvRefs) supportSymrefs() bool {
return a.Capabilities.Supports(capability.SymRef)
}
// IsEmpty returns true if doesn't contain any reference.
func (a *AdvRefs) IsEmpty() bool {
return a.Head == nil &&
len(a.References) == 0 &&
len(a.Peeled) == 0 &&
len(a.Shallows) == 0
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_decode.go
================================================
package packp
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
// Decode reads the next advertised-refs message form its input and
// stores it in the AdvRefs.
func (a *AdvRefs) Decode(r io.Reader) error {
d := newAdvRefsDecoder(r)
return d.Decode(a)
}
type advRefsDecoder struct {
s *pktline.Scanner // a pkt-line scanner from the input stream
line []byte // current pkt-line contents, use parser.nextLine() to make it advance
nLine int // current pkt-line number for debugging, begins at 1
hash plumbing.Hash // last hash read
err error // sticky error, use the parser.error() method to fill this out
data *AdvRefs // parsed data is stored here
}
var (
// ErrEmptyAdvRefs is returned by Decode if it gets an empty advertised
// references message.
ErrEmptyAdvRefs = errors.New("empty advertised-ref message")
// ErrEmptyInput is returned by Decode if the input is empty.
ErrEmptyInput = errors.New("empty input")
)
func newAdvRefsDecoder(r io.Reader) *advRefsDecoder {
return &advRefsDecoder{
s: pktline.NewScanner(r),
}
}
func (d *advRefsDecoder) Decode(v *AdvRefs) error {
d.data = v
for state := decodePrefix; state != nil; {
state = state(d)
}
return d.err
}
type decoderStateFn func(*advRefsDecoder) decoderStateFn
// fills out the parser sticky error
func (d *advRefsDecoder) error(format string, a ...interface{}) {
msg := fmt.Sprintf(
"pkt-line %d: %s", d.nLine,
fmt.Sprintf(format, a...),
)
d.err = NewErrUnexpectedData(msg, d.line)
}
// Reads a new pkt-line from the scanner, makes its payload available as
// p.line and increments p.nLine. A successful invocation returns true,
// otherwise, false is returned and the sticky error is filled out
// accordingly. Trims eols at the end of the payloads.
func (d *advRefsDecoder) nextLine() bool {
d.nLine++
if !d.s.Scan() {
if d.err = d.s.Err(); d.err != nil {
return false
}
if d.nLine == 1 {
d.err = ErrEmptyInput
return false
}
d.error("EOF")
return false
}
d.line = d.s.Bytes()
d.line = bytes.TrimSuffix(d.line, eol)
return true
}
// The HTTP smart prefix is often followed by a flush-pkt.
func decodePrefix(d *advRefsDecoder) decoderStateFn {
if ok := d.nextLine(); !ok {
return nil
}
if !isPrefix(d.line) {
return decodeFirstHash
}
tmp := make([]byte, len(d.line))
copy(tmp, d.line)
d.data.Prefix = append(d.data.Prefix, tmp)
if ok := d.nextLine(); !ok {
return nil
}
if !isFlush(d.line) {
return decodeFirstHash
}
d.data.Prefix = append(d.data.Prefix, pktline.Flush)
if ok := d.nextLine(); !ok {
return nil
}
return decodeFirstHash
}
func isPrefix(payload []byte) bool {
return len(payload) > 0 && payload[0] == '#'
}
// If the first hash is zero, then a no-refs is coming. Otherwise, a
// list-of-refs is coming, and the hash will be followed by the first
// advertised ref.
func decodeFirstHash(p *advRefsDecoder) decoderStateFn {
// If the repository is empty, we receive a flush here (HTTP).
if isFlush(p.line) {
p.err = ErrEmptyAdvRefs
return nil
}
// TODO: Use object-format (when available) for hash size. Git 2.41+
if len(p.line) < hashSize {
p.error("cannot read hash, pkt-line too short")
return nil
}
if _, err := hex.Decode(p.hash[:], p.line[:hashSize]); err != nil {
p.error("invalid hash text: %s", err)
return nil
}
p.line = p.line[hashSize:]
if p.hash.IsZero() {
return decodeSkipNoRefs
}
return decodeFirstRef
}
// Skips SP "capabilities^{}" NUL
func decodeSkipNoRefs(p *advRefsDecoder) decoderStateFn {
if len(p.line) < len(noHeadMark) {
p.error("too short zero-id ref")
return nil
}
if !bytes.HasPrefix(p.line, noHeadMark) {
p.error("malformed zero-id ref")
return nil
}
p.line = p.line[len(noHeadMark):]
return decodeCaps
}
// decode the refname, expects SP refname NULL
func decodeFirstRef(l *advRefsDecoder) decoderStateFn {
if len(l.line) < 3 {
l.error("line too short after hash")
return nil
}
if !bytes.HasPrefix(l.line, sp) {
l.error("no space after hash")
return nil
}
l.line = l.line[1:]
chunks := bytes.SplitN(l.line, null, 2)
if len(chunks) < 2 {
l.error("NULL not found")
return nil
}
ref := chunks[0]
l.line = chunks[1]
if bytes.Equal(ref, []byte(head)) {
l.data.Head = &l.hash
} else {
l.data.References[string(ref)] = l.hash
}
return decodeCaps
}
func decodeCaps(p *advRefsDecoder) decoderStateFn {
if err := p.data.Capabilities.Decode(p.line); err != nil {
p.error("invalid capabilities: %s", err)
return nil
}
return decodeOtherRefs
}
// The refs are either tips (obj-id SP refname) or a peeled (obj-id SP refname^{}).
// If there are no refs, then there might be a shallow or flush-ptk.
func decodeOtherRefs(p *advRefsDecoder) decoderStateFn {
if ok := p.nextLine(); !ok {
return nil
}
if bytes.HasPrefix(p.line, shallow) {
return decodeShallow
}
if len(p.line) == 0 {
return nil
}
saveTo := p.data.References
if bytes.HasSuffix(p.line, peeled) {
p.line = bytes.TrimSuffix(p.line, peeled)
saveTo = p.data.Peeled
}
ref, hash, err := readRef(p.line)
if err != nil {
p.error("%s", err)
return nil
}
saveTo[ref] = hash
return decodeOtherRefs
}
// Reads a ref-name
func readRef(data []byte) (string, plumbing.Hash, error) {
chunks := bytes.Split(data, sp)
switch {
case len(chunks) == 1:
return "", plumbing.ZeroHash, fmt.Errorf("malformed ref data: no space was found")
case len(chunks) > 2:
return "", plumbing.ZeroHash, fmt.Errorf("malformed ref data: more than one space found")
default:
return string(chunks[1]), plumbing.NewHash(string(chunks[0])), nil
}
}
// Keeps reading shallows until a flush-pkt is found
func decodeShallow(p *advRefsDecoder) decoderStateFn {
if !bytes.HasPrefix(p.line, shallow) {
p.error("malformed shallow prefix, found %q... instead", p.line[:len(shallow)])
return nil
}
p.line = bytes.TrimPrefix(p.line, shallow)
if len(p.line) != hashSize {
p.error(fmt.Sprintf(
"malformed shallow hash: wrong length, expected 40 bytes, read %d bytes",
len(p.line)))
return nil
}
text := p.line[:hashSize]
var h plumbing.Hash
if _, err := hex.Decode(h[:], text); err != nil {
p.error("invalid hash text: %s", err)
return nil
}
p.data.Shallows = append(p.data.Shallows, h)
if ok := p.nextLine(); !ok {
return nil
}
if len(p.line) == 0 {
return nil // successful parse of the advertised-refs message
}
return decodeShallow
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/advrefs_encode.go
================================================
package packp
import (
"bytes"
"fmt"
"io"
"sort"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
)
// Encode writes the AdvRefs encoding to a writer.
//
// All the payloads will end with a newline character. Capabilities,
// references and shallows are written in alphabetical order, except for
// peeled references that always follow their corresponding references.
func (a *AdvRefs) Encode(w io.Writer) error {
e := newAdvRefsEncoder(w)
return e.Encode(a)
}
type advRefsEncoder struct {
data *AdvRefs // data to encode
pe *pktline.Encoder // where to write the encoded data
firstRefName string // reference name to encode in the first pkt-line (HEAD if present)
firstRefHash plumbing.Hash // hash referenced to encode in the first pkt-line (HEAD if present)
sortedRefs []string // hash references to encode ordered by increasing order
err error // sticky error
}
func newAdvRefsEncoder(w io.Writer) *advRefsEncoder {
return &advRefsEncoder{
pe: pktline.NewEncoder(w),
}
}
func (e *advRefsEncoder) Encode(v *AdvRefs) error {
e.data = v
e.sortRefs()
e.setFirstRef()
for state := encodePrefix; state != nil; {
state = state(e)
}
return e.err
}
func (e *advRefsEncoder) sortRefs() {
if len(e.data.References) > 0 {
refs := make([]string, 0, len(e.data.References))
for refName := range e.data.References {
refs = append(refs, refName)
}
sort.Strings(refs)
e.sortedRefs = refs
}
}
func (e *advRefsEncoder) setFirstRef() {
if e.data.Head != nil {
e.firstRefName = head
e.firstRefHash = *e.data.Head
return
}
if len(e.sortedRefs) > 0 {
refName := e.sortedRefs[0]
e.firstRefName = refName
e.firstRefHash = e.data.References[refName]
}
}
type encoderStateFn func(*advRefsEncoder) encoderStateFn
func encodePrefix(e *advRefsEncoder) encoderStateFn {
for _, p := range e.data.Prefix {
if bytes.Equal(p, pktline.Flush) {
if e.err = e.pe.Flush(); e.err != nil {
return nil
}
continue
}
if e.err = e.pe.Encodef("%s\n", string(p)); e.err != nil {
return nil
}
}
return encodeFirstLine
}
// Adds the first pkt-line payload: head hash, head ref and capabilities.
// If HEAD ref is not found, the first reference ordered in increasing order will be used.
// If there aren't HEAD neither refs, the first line will be "PKT-LINE(zero-id SP "capabilities^{}" NUL capability-list)".
// See: https://github.com/git/git/blob/master/Documentation/technical/pack-protocol.txt
// See: https://github.com/git/git/blob/master/Documentation/technical/protocol-common.txt
func encodeFirstLine(e *advRefsEncoder) encoderStateFn {
const formatFirstLine = "%s %s\x00%s\n"
var firstLine string
capabilities := formatCaps(e.data.Capabilities)
if e.firstRefName == "" {
firstLine = fmt.Sprintf(formatFirstLine, plumbing.ZeroHash.String(), "capabilities^{}", capabilities)
} else {
firstLine = fmt.Sprintf(formatFirstLine, e.firstRefHash.String(), e.firstRefName, capabilities)
}
if e.err = e.pe.EncodeString(firstLine); e.err != nil {
return nil
}
return encodeRefs
}
func formatCaps(c *capability.List) string {
if c == nil {
return ""
}
return c.String()
}
// Adds the (sorted) refs: hash SP refname EOL
// and their peeled refs if any.
func encodeRefs(e *advRefsEncoder) encoderStateFn {
for _, r := range e.sortedRefs {
if r == e.firstRefName {
continue
}
hash := e.data.References[r]
if e.err = e.pe.Encodef("%s %s\n", hash.String(), r); e.err != nil {
return nil
}
if hash, ok := e.data.Peeled[r]; ok {
if e.err = e.pe.Encodef("%s %s^{}\n", hash.String(), r); e.err != nil {
return nil
}
}
}
return encodeShallow
}
// Adds the (sorted) shallows: "shallow" SP hash EOL
func encodeShallow(e *advRefsEncoder) encoderStateFn {
sorted := sortShallows(e.data.Shallows)
for _, hash := range sorted {
if e.err = e.pe.Encodef("shallow %s\n", hash); e.err != nil {
return nil
}
}
return encodeFlush
}
func sortShallows(c []plumbing.Hash) []string {
ret := []string{}
for _, h := range c {
ret = append(ret, h.String())
}
sort.Strings(ret)
return ret
}
func encodeFlush(e *advRefsEncoder) encoderStateFn {
e.err = e.pe.Flush()
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/capability.go
================================================
// Package capability defines the server and client capabilities.
package capability
import (
"fmt"
"os"
)
// Capability describes a server or client capability.
type Capability string
func (n Capability) String() string {
return string(n)
}
const (
// MultiACK capability allows the server to return "ACK obj-id continue" as
// soon as it finds a commit that it can use as a common base, between the
// client's wants and the client's have set.
//
// By sending this early, the server can potentially head off the client
// from walking any further down that particular branch of the client's
// repository history. The client may still need to walk down other
// branches, sending have lines for those, until the server has a
// complete cut across the DAG, or the client has said "done".
//
// Without multi_ack, a client sends have lines in --date-order until
// the server has found a common base. That means the client will send
// have lines that are already known by the server to be common, because
// they overlap in time with another branch that the server hasn't found
// a common base on yet.
//
// For example suppose the client has commits in caps that the server
// doesn't and the server has commits in lower case that the client
// doesn't, as in the following diagram:
//
// +---- u ---------------------- x
// / +----- y
// / /
// a -- b -- c -- d -- E -- F
// \
// +--- Q -- R -- S
//
// If the client wants x,y and starts out by saying have F,S, the server
// doesn't know what F,S is. Eventually the client says "have d" and
// the server sends "ACK d continue" to let the client know to stop
// walking down that line (so don't send c-b-a), but it's not done yet,
// it needs a base for x. The client keeps going with S-R-Q, until a
// gets reached, at which point the server has a clear base and it all
// ends.
//
// Without multi_ack the client would have sent that c-b-a chain anyway,
// interleaved with S-R-Q.
MultiACK Capability = "multi_ack"
// MultiACKDetailed is an extension of multi_ack that permits client to
// better understand the server's in-memory state.
MultiACKDetailed Capability = "multi_ack_detailed"
// NoDone should only be used with the smart HTTP protocol. If
// multi_ack_detailed and no-done are both present, then the sender is
// free to immediately send a pack following its first "ACK obj-id ready"
// message.
//
// Without no-done in the smart HTTP protocol, the server session would
// end and the client has to make another trip to send "done" before
// the server can send the pack. no-done removes the last round and
// thus slightly reduces latency.
NoDone Capability = "no-done"
// ThinPack is one with deltas which reference base objects not
// contained within the pack (but are known to exist at the receiving
// end). This can reduce the network traffic significantly, but it
// requires the receiving end to know how to "thicken" these packs by
// adding the missing bases to the pack.
//
// The upload-pack server advertises 'thin-pack' when it can generate
// and send a thin pack. A client requests the 'thin-pack' capability
// when it understands how to "thicken" it, notifying the server that
// it can receive such a pack. A client MUST NOT request the
// 'thin-pack' capability if it cannot turn a thin pack into a
// self-contained pack.
//
// Receive-pack, on the other hand, is assumed by default to be able to
// handle thin packs, but can ask the client not to use the feature by
// advertising the 'no-thin' capability. A client MUST NOT send a thin
// pack if the server advertises the 'no-thin' capability.
//
// The reasons for this asymmetry are historical. The receive-pack
// program did not exist until after the invention of thin packs, so
// historically the reference implementation of receive-pack always
// understood thin packs. Adding 'no-thin' later allowed receive-pack
// to disable the feature in a backwards-compatible manner.
ThinPack Capability = "thin-pack"
// Sideband means that server can send, and client understand multiplexed
// progress reports and error info interleaved with the packfile itself.
//
// These two options are mutually exclusive. A modern client always
// favors Sideband64k.
//
// Either mode indicates that the packfile data will be streamed broken
// up into packets of up to either 1000 bytes in the case of 'side_band',
// or 65520 bytes in the case of 'side_band_64k'. Each packet is made up
// of a leading 4-byte pkt-line length of how much data is in the packet,
// followed by a 1-byte stream code, followed by the actual data.
//
// The stream code can be one of:
//
// 1 - pack data
// 2 - progress messages
// 3 - fatal error message just before stream aborts
//
// The "side-band-64k" capability came about as a way for newer clients
// that can handle much larger packets to request packets that are
// actually crammed nearly full, while maintaining backward compatibility
// for the older clients.
//
// Further, with side-band and its up to 1000-byte messages, it's actually
// 999 bytes of payload and 1 byte for the stream code. With side-band-64k,
// same deal, you have up to 65519 bytes of data and 1 byte for the stream
// code.
//
// The client MUST send only maximum of one of "side-band" and "side-
// band-64k". Server MUST diagnose it as an error if client requests
// both.
Sideband Capability = "side-band"
Sideband64k Capability = "side-band-64k"
// OFSDelta server can send, and client understand PACKv2 with delta
// referring to its base by position in pack rather than by an obj-id. That
// is, they can send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
OFSDelta Capability = "ofs-delta"
// Agent the server may optionally send this capability to notify the client
// that the server is running version `X`. The client may optionally return
// its own agent string by responding with an `agent=Y` capability (but it
// MUST NOT do so if the server did not mention the agent capability). The
// `X` and `Y` strings may contain any printable ASCII characters except
// space (i.e., the byte range 32 < x < 127), and are typically of the form
// "package/version" (e.g., "git/1.8.3.1"). The agent strings are purely
// informative for statistics and debugging purposes, and MUST NOT be used
// to programmatically assume the presence or absence of particular features.
Agent Capability = "agent"
// Shallow capability adds "deepen", "shallow" and "unshallow" commands to
// the fetch-pack/upload-pack protocol so clients can request shallow
// clones.
Shallow Capability = "shallow"
// DeepenSince adds "deepen-since" command to fetch-pack/upload-pack
// protocol so the client can request shallow clones that are cut at a
// specific time, instead of depth. Internally it's equivalent of doing
// "rev-list --max-age=" on the server side. "deepen-since"
// cannot be used with "deepen".
DeepenSince Capability = "deepen-since"
// DeepenNot adds "deepen-not" command to fetch-pack/upload-pack
// protocol so the client can request shallow clones that are cut at a
// specific revision, instead of depth. Internally it's equivalent of
// doing "rev-list --not " on the server side. "deepen-not"
// cannot be used with "deepen", but can be used with "deepen-since".
DeepenNot Capability = "deepen-not"
// DeepenRelative if this capability is requested by the client, the
// semantics of "deepen" command is changed. The "depth" argument is the
// depth from the current shallow boundary, instead of the depth from
// remote refs.
DeepenRelative Capability = "deepen-relative"
// NoProgress the client was started with "git clone -q" or something, and
// doesn't want that side band 2. Basically the client just says "I do not
// wish to receive stream 2 on sideband, so do not send it to me, and if
// you did, I will drop it on the floor anyway". However, the sideband
// channel 3 is still used for error responses.
NoProgress Capability = "no-progress"
// IncludeTag capability is about sending annotated tags if we are
// sending objects they point to. If we pack an object to the client, and
// a tag object points exactly at that object, we pack the tag object too.
// In general this allows a client to get all new annotated tags when it
// fetches a branch, in a single network connection.
//
// Clients MAY always send include-tag, hardcoding it into a request when
// the server advertises this capability. The decision for a client to
// request include-tag only has to do with the client's desires for tag
// data, whether or not a server had advertised objects in the
// refs/tags/* namespace.
//
// Servers MUST pack the tags if their referrant is packed and the client
// has requested include-tags.
//
// Clients MUST be prepared for the case where a server has ignored
// include-tag and has not actually sent tags in the pack. In such
// cases the client SHOULD issue a subsequent fetch to acquire the tags
// that include-tag would have otherwise given the client.
//
// The server SHOULD send include-tag, if it supports it, regardless
// of whether or not there are tags available.
IncludeTag Capability = "include-tag"
// ReportStatus the receive-pack process can receive a 'report-status'
// capability, which tells it that the client wants a report of what
// happened after a packfile upload and reference update. If the pushing
// client requests this capability, after unpacking and updating references
// the server will respond with whether the packfile unpacked successfully
// and if each reference was updated successfully. If any of those were not
// successful, it will send back an error message. See pack-protocol.txt
// for example messages.
ReportStatus Capability = "report-status"
// DeleteRefs If the server sends back this capability, it means that
// it is capable of accepting a zero-id value as the target
// value of a reference update. It is not sent back by the client, it
// simply informs the client that it can be sent zero-id values
// to delete references
DeleteRefs Capability = "delete-refs"
// Quiet If the receive-pack server advertises this capability, it is
// capable of silencing human-readable progress output which otherwise may
// be shown when processing the received pack. A send-pack client should
// respond with the 'quiet' capability to suppress server-side progress
// reporting if the local progress reporting is also being suppressed
// (e.g., via `push -q`, or if stderr does not go to a tty).
Quiet Capability = "quiet"
// Atomic If the server sends this capability it is capable of accepting
// atomic pushes. If the pushing client requests this capability, the server
// will update the refs in one atomic transaction. Either all refs are
// updated or none.
Atomic Capability = "atomic"
// PushOptions If the server sends this capability it is able to accept
// push options after the update commands have been sent, but before the
// packfile is streamed. If the pushing client requests this capability,
// the server will pass the options to the pre- and post- receive hooks
// that process this push request.
PushOptions Capability = "push-options"
// AllowTipSHA1InWant if the upload-pack server advertises this capability,
// fetch-pack may send "want" lines with SHA-1s that exist at the server but
// are not advertised by upload-pack.
AllowTipSHA1InWant Capability = "allow-tip-sha1-in-want"
// AllowReachableSHA1InWant if the upload-pack server advertises this
// capability, fetch-pack may send "want" lines with SHA-1s that exist at
// the server but are not advertised by upload-pack.
AllowReachableSHA1InWant Capability = "allow-reachable-sha1-in-want"
// PushCert the receive-pack server that advertises this capability is
// willing to accept a signed push certificate, and asks the to be
// included in the push certificate. A send-pack client MUST NOT
// send a push-cert packet unless the receive-pack server advertises
// this capability.
PushCert Capability = "push-cert"
// SymRef symbolic reference support for better negotiation.
SymRef Capability = "symref"
// ObjectFormat takes a hash algorithm as an argument, indicates that the
// server supports the given hash algorithms.
ObjectFormat Capability = "object-format"
// Filter if present, fetch-pack may send "filter" commands to request a
// partial clone or partial fetch and request that the server omit various objects from the packfile
Filter Capability = "filter"
)
const userAgent = "go-git/5.x"
// DefaultAgent provides the user agent string.
func DefaultAgent() string {
if envUserAgent, ok := os.LookupEnv("GO_GIT_USER_AGENT_EXTRA"); ok {
return fmt.Sprintf("%s %s", userAgent, envUserAgent)
}
return userAgent
}
var known = map[Capability]bool{
MultiACK: true, MultiACKDetailed: true, NoDone: true, ThinPack: true,
Sideband: true, Sideband64k: true, OFSDelta: true, Agent: true,
Shallow: true, DeepenSince: true, DeepenNot: true, DeepenRelative: true,
NoProgress: true, IncludeTag: true, ReportStatus: true, DeleteRefs: true,
Quiet: true, Atomic: true, PushOptions: true, AllowTipSHA1InWant: true,
AllowReachableSHA1InWant: true, PushCert: true, SymRef: true,
ObjectFormat: true, Filter: true,
}
var requiresArgument = map[Capability]bool{
Agent: true, PushCert: true, SymRef: true, ObjectFormat: true,
}
var multipleArgument = map[Capability]bool{
SymRef: true,
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/capability/list.go
================================================
package capability
import (
"bytes"
"errors"
"fmt"
"strings"
)
var (
// ErrArgumentsRequired is returned if no arguments are giving with a
// capability that requires arguments
ErrArgumentsRequired = errors.New("arguments required")
// ErrArguments is returned if arguments are given with a capabilities that
// not supports arguments
ErrArguments = errors.New("arguments not allowed")
// ErrEmptyArgument is returned when an empty value is given
ErrEmptyArgument = errors.New("empty argument")
// ErrMultipleArguments multiple argument given to a capabilities that not
// support it
ErrMultipleArguments = errors.New("multiple arguments not allowed")
)
// List represents a list of capabilities
type List struct {
m map[Capability]*entry
sort []string
}
type entry struct {
Name Capability
Values []string
}
// NewList returns a new List of capabilities
func NewList() *List {
return &List{
m: make(map[Capability]*entry),
}
}
// IsEmpty returns true if the List is empty
func (l *List) IsEmpty() bool {
return len(l.sort) == 0
}
// Decode decodes list of capabilities from raw into the list
func (l *List) Decode(raw []byte) error {
// git 1.x receive pack used to send a leading space on its
// git-receive-pack capabilities announcement. We just trim space to be
// tolerant to space changes in different versions.
raw = bytes.TrimSpace(raw)
if len(raw) == 0 {
return nil
}
for _, data := range bytes.Split(raw, []byte{' '}) {
pair := bytes.SplitN(data, []byte{'='}, 2)
c := Capability(pair[0])
if len(pair) == 1 {
if err := l.Add(c); err != nil {
return err
}
continue
}
if err := l.Add(c, string(pair[1])); err != nil {
return err
}
}
return nil
}
// Get returns the values for a capability
func (l *List) Get(capability Capability) []string {
if _, ok := l.m[capability]; !ok {
return nil
}
return l.m[capability].Values
}
// Set sets a capability removing the previous values
func (l *List) Set(capability Capability, values ...string) error {
if _, ok := l.m[capability]; ok {
l.m[capability].Values = l.m[capability].Values[:0]
}
return l.Add(capability, values...)
}
// Add adds a capability, values are optional
func (l *List) Add(c Capability, values ...string) error {
if err := l.validate(c, values); err != nil {
return err
}
if !l.Supports(c) {
l.m[c] = &entry{Name: c}
l.sort = append(l.sort, c.String())
}
if len(values) == 0 {
return nil
}
if known[c] && !multipleArgument[c] && len(l.m[c].Values) > 0 {
return ErrMultipleArguments
}
l.m[c].Values = append(l.m[c].Values, values...)
return nil
}
func (l *List) validateNoEmptyArgs(values []string) error {
for _, v := range values {
if v == "" {
return ErrEmptyArgument
}
}
return nil
}
func (l *List) validate(c Capability, values []string) error {
if !known[c] {
return l.validateNoEmptyArgs(values)
}
if requiresArgument[c] && len(values) == 0 {
return ErrArgumentsRequired
}
if !requiresArgument[c] && len(values) != 0 {
return ErrArguments
}
if !multipleArgument[c] && len(values) > 1 {
return ErrMultipleArguments
}
return l.validateNoEmptyArgs(values)
}
// Supports returns true if capability is present
func (l *List) Supports(capability Capability) bool {
_, ok := l.m[capability]
return ok
}
// Delete deletes a capability from the List
func (l *List) Delete(capability Capability) {
if !l.Supports(capability) {
return
}
delete(l.m, capability)
for i, c := range l.sort {
if c != string(capability) {
continue
}
l.sort = append(l.sort[:i], l.sort[i+1:]...)
return
}
}
// All returns a slice with all defined capabilities.
func (l *List) All() []Capability {
var cs []Capability
for _, key := range l.sort {
cs = append(cs, Capability(key))
}
return cs
}
// String generates the capabilities strings, the capabilities are sorted in
// insertion order
func (l *List) String() string {
var o []string
for _, key := range l.sort {
cap := l.m[Capability(key)]
if len(cap.Values) == 0 {
o = append(o, key)
continue
}
for _, value := range cap.Values {
o = append(o, fmt.Sprintf("%s=%s", key, value))
}
}
return strings.Join(o, " ")
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/common.go
================================================
package packp
import (
"fmt"
)
type stateFn func() stateFn
const (
// common
hashSize = 40
// advrefs
head = "HEAD"
noHead = "capabilities^{}"
)
var (
// common
sp = []byte(" ")
eol = []byte("\n")
// advertised-refs
null = []byte("\x00")
peeled = []byte("^{}")
noHeadMark = []byte(" capabilities^{}\x00")
// upload-request
want = []byte("want ")
shallow = []byte("shallow ")
deepen = []byte("deepen")
deepenCommits = []byte("deepen ")
deepenSince = []byte("deepen-since ")
deepenReference = []byte("deepen-not ")
// shallow-update
unshallow = []byte("unshallow ")
// server-response
ack = []byte("ACK")
nak = []byte("NAK")
// updreq
shallowNoSp = []byte("shallow")
)
func isFlush(payload []byte) bool {
return len(payload) == 0
}
var (
// ErrNilWriter is returned when a nil writer is passed to the encoder.
ErrNilWriter = fmt.Errorf("nil writer")
)
// ErrUnexpectedData represents an unexpected data decoding a message
type ErrUnexpectedData struct {
Msg string
Data []byte
}
// NewErrUnexpectedData returns a new ErrUnexpectedData containing the data and
// the message given
func NewErrUnexpectedData(msg string, data []byte) error {
return &ErrUnexpectedData{Msg: msg, Data: data}
}
func (err *ErrUnexpectedData) Error() string {
if len(err.Data) == 0 {
return err.Msg
}
return fmt.Sprintf("%s (%s)", err.Msg, err.Data)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/doc.go
================================================
package packp
/*
A nice way to trace the real data transmitted and received by git, use:
GIT_TRACE_PACKET=true git ls-remote http://github.com/src-d/go-git
GIT_TRACE_PACKET=true git clone http://github.com/src-d/go-git
Here follows a copy of the current protocol specification at the time of
this writing.
(Please notice that most http git servers will add a flush-pkt after the
first pkt-line when using HTTP smart.)
Documentation Common to Pack and Http Protocols
===============================================
ABNF Notation
-------------
ABNF notation as described by RFC 5234 is used within the protocol documents,
except the following replacement core rules are used:
----
HEXDIG = DIGIT / "a" / "b" / "c" / "d" / "e" / "f"
----
We also define the following common rules:
----
NUL = %x00
zero-id = 40*"0"
obj-id = 40*(HEXDIGIT)
refname = "HEAD"
refname /= "refs/"
----
A refname is a hierarchical octet string beginning with "refs/" and
not violating the 'git-check-ref-format' command's validation rules.
More specifically, they:
. They can include slash `/` for hierarchical (directory)
grouping, but no slash-separated component can begin with a
dot `.`.
. They must contain at least one `/`. This enforces the presence of a
category like `heads/`, `tags/` etc. but the actual names are not
restricted.
. They cannot have two consecutive dots `..` anywhere.
. They cannot have ASCII control characters (i.e. bytes whose
values are lower than \040, or \177 `DEL`), space, tilde `~`,
caret `^`, colon `:`, question-mark `?`, asterisk `*`,
or open bracket `[` anywhere.
. They cannot end with a slash `/` or a dot `.`.
. They cannot end with the sequence `.lock`.
. They cannot contain a sequence `@{`.
. They cannot contain a `\\`.
pkt-line Format
---------------
Much (but not all) of the payload is described around pkt-lines.
A pkt-line is a variable length binary string. The first four bytes
of the line, the pkt-len, indicates the total length of the line,
in hexadecimal. The pkt-len includes the 4 bytes used to contain
the length's hexadecimal representation.
A pkt-line MAY contain binary data, so implementors MUST ensure
pkt-line parsing/formatting routines are 8-bit clean.
A non-binary line SHOULD BE terminated by an LF, which if present
MUST be included in the total length. Receivers MUST treat pkt-lines
with non-binary data the same whether or not they contain the trailing
LF (stripping the LF if present, and not complaining when it is
missing).
The maximum length of a pkt-line's data component is 65516 bytes.
Implementations MUST NOT send pkt-line whose length exceeds 65520
(65516 bytes of payload + 4 bytes of length data).
Implementations SHOULD NOT send an empty pkt-line ("0004").
A pkt-line with a length field of 0 ("0000"), called a flush-pkt,
is a special case and MUST be handled differently than an empty
pkt-line ("0004").
----
pkt-line = data-pkt / flush-pkt
data-pkt = pkt-len pkt-payload
pkt-len = 4*(HEXDIG)
pkt-payload = (pkt-len - 4)*(OCTET)
flush-pkt = "0000"
----
Examples (as C-style strings):
----
pkt-line actual value
---------------------------------
"0006a\n" "a\n"
"0005a" "a"
"000bfoobar\n" "foobar\n"
"0004" ""
----
Packfile transfer protocols
===========================
Git supports transferring data in packfiles over the ssh://, git://, http:// and
file:// transports. There exist two sets of protocols, one for pushing
data from a client to a server and another for fetching data from a
server to a client. The three transports (ssh, git, file) use the same
protocol to transfer data. http is documented in http-protocol.txt.
The processes invoked in the canonical Git implementation are 'upload-pack'
on the server side and 'fetch-pack' on the client side for fetching data;
then 'receive-pack' on the server and 'send-pack' on the client for pushing
data. The protocol functions to have a server tell a client what is
currently on the server, then for the two to negotiate the smallest amount
of data to send in order to fully update one or the other.
pkt-line Format
---------------
The descriptions below build on the pkt-line format described in
protocol-common.txt. When the grammar indicate `PKT-LINE(...)`, unless
otherwise noted the usual pkt-line LF rules apply: the sender SHOULD
include a LF, but the receiver MUST NOT complain if it is not present.
Transports
----------
There are three transports over which the packfile protocol is
initiated. The Git transport is a simple, unauthenticated server that
takes the command (almost always 'upload-pack', though Git
servers can be configured to be globally writable, in which 'receive-
pack' initiation is also allowed) with which the client wishes to
communicate and executes it and connects it to the requesting
process.
In the SSH transport, the client just runs the 'upload-pack'
or 'receive-pack' process on the server over the SSH protocol and then
communicates with that invoked process over the SSH connection.
The file:// transport runs the 'upload-pack' or 'receive-pack'
process locally and communicates with it over a pipe.
Git Transport
-------------
The Git transport starts off by sending the command and repository
on the wire using the pkt-line format, followed by a NUL byte and a
hostname parameter, terminated by a NUL byte.
0032git-upload-pack /project.git\0host=myserver.com\0
--
git-proto-request = request-command SP pathname NUL [ host-parameter NUL ]
request-command = "git-upload-pack" / "git-receive-pack" /
"git-upload-archive" ; case sensitive
pathname = *( %x01-ff ) ; exclude NUL
host-parameter = "host=" hostname [ ":" port ]
--
Only host-parameter is allowed in the git-proto-request. Clients
MUST NOT attempt to send additional parameters. It is used for the
git-daemon name based virtual hosting. See --interpolated-path
option to git daemon, with the %H/%CH format characters.
Basically what the Git client is doing to connect to an 'upload-pack'
process on the server side over the Git protocol is this:
$ echo -e -n \
"0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" |
nc -v example.com 9418
If the server refuses the request for some reasons, it could abort
gracefully with an error message.
----
error-line = PKT-LINE("ERR" SP explanation-text)
----
SSH Transport
-------------
Initiating the upload-pack or receive-pack processes over SSH is
executing the binary on the server via SSH remote execution.
It is basically equivalent to running this:
$ ssh git.example.com "git-upload-pack '/project.git'"
For a server to support Git pushing and pulling for a given user over
SSH, that user needs to be able to execute one or both of those
commands via the SSH shell that they are provided on login. On some
systems, that shell access is limited to only being able to run those
two commands, or even just one of them.
In an ssh:// format URI, it's absolute in the URI, so the '/' after
the host name (or port number) is sent as an argument, which is then
read by the remote git-upload-pack exactly as is, so it's effectively
an absolute path in the remote filesystem.
git clone ssh://user@example.com/project.git
|
v
ssh user@example.com "git-upload-pack '/project.git'"
In a "user@host:path" format URI, its relative to the user's home
directory, because the Git client will run:
git clone user@example.com:project.git
|
v
ssh user@example.com "git-upload-pack 'project.git'"
The exception is if a '~' is used, in which case
we execute it without the leading '/'.
ssh://user@example.com/~alice/project.git,
|
v
ssh user@example.com "git-upload-pack '~alice/project.git'"
A few things to remember here:
- The "command name" is spelled with dash (e.g. git-upload-pack), but
this can be overridden by the client;
- The repository path is always quoted with single quotes.
Fetching Data From a Server
---------------------------
When one Git repository wants to get data that a second repository
has, the first can 'fetch' from the second. This operation determines
what data the server has that the client does not then streams that
data down to the client in packfile format.
Reference Discovery
-------------------
When the client initially connects the server will immediately respond
with a listing of each reference it has (all branches and tags) along
with the object name that each reference currently points to.
$ echo -e -n "0039git-upload-pack /schacon/gitbook.git\0host=example.com\0" |
nc -v example.com 9418
00887217a7c7e582c46cec22a130adf4b9d7d950fba0 HEAD\0multi_ack thin-pack
side-band side-band-64k ofs-delta shallow no-progress include-tag
00441d3fcd5ced445d1abc402225c0b8a1299641f497 refs/heads/integration
003f7217a7c7e582c46cec22a130adf4b9d7d950fba0 refs/heads/master
003cb88d2441cac0977faf98efc80305012112238d9d refs/tags/v0.9
003c525128480b96c89e6418b1e40909bf6c5b2d580f refs/tags/v1.0
003fe92df48743b7bc7d26bcaabfddde0a1e20cae47c refs/tags/v1.0^{}
0000
The returned response is a pkt-line stream describing each ref and
its current value. The stream MUST be sorted by name according to
the C locale ordering.
If HEAD is a valid ref, HEAD MUST appear as the first advertised
ref. If HEAD is not a valid ref, HEAD MUST NOT appear in the
advertisement list at all, but other refs may still appear.
The stream MUST include capability declarations behind a NUL on the
first ref. The peeled value of a ref (that is "ref^{}") MUST be
immediately after the ref itself, if presented. A conforming server
MUST peel the ref if it's an annotated tag.
----
advertised-refs = (no-refs / list-of-refs)
*shallow
flush-pkt
no-refs = PKT-LINE(zero-id SP "capabilities^{}"
NUL capability-list)
list-of-refs = first-ref *other-ref
first-ref = PKT-LINE(obj-id SP refname
NUL capability-list)
other-ref = PKT-LINE(other-tip / other-peeled)
other-tip = obj-id SP refname
other-peeled = obj-id SP refname "^{}"
shallow = PKT-LINE("shallow" SP obj-id)
capability-list = capability *(SP capability)
capability = 1*(LC_ALPHA / DIGIT / "-" / "_")
LC_ALPHA = %x61-7A
----
Server and client MUST use lowercase for obj-id, both MUST treat obj-id
as case-insensitive.
See protocol-capabilities.txt for a list of allowed server capabilities
and descriptions.
Packfile Negotiation
--------------------
After reference and capabilities discovery, the client can decide to
terminate the connection by sending a flush-pkt, telling the server it can
now gracefully terminate, and disconnect, when it does not need any pack
data. This can happen with the ls-remote command, and also can happen when
the client already is up-to-date.
Otherwise, it enters the negotiation phase, where the client and
server determine what the minimal packfile necessary for transport is,
by telling the server what objects it wants, its shallow objects
(if any), and the maximum commit depth it wants (if any). The client
will also send a list of the capabilities it wants to be in effect,
out of what the server said it could do with the first 'want' line.
----
upload-request = want-list
*shallow-line
*1depth-request
flush-pkt
want-list = first-want
*additional-want
shallow-line = PKT-LINE("shallow" SP obj-id)
depth-request = PKT-LINE("deepen" SP depth) /
PKT-LINE("deepen-since" SP timestamp) /
PKT-LINE("deepen-not" SP ref)
first-want = PKT-LINE("want" SP obj-id SP capability-list)
additional-want = PKT-LINE("want" SP obj-id)
depth = 1*DIGIT
----
Clients MUST send all the obj-ids it wants from the reference
discovery phase as 'want' lines. Clients MUST send at least one
'want' command in the request body. Clients MUST NOT mention an
obj-id in a 'want' command which did not appear in the response
obtained through ref discovery.
The client MUST write all obj-ids which it only has shallow copies
of (meaning that it does not have the parents of a commit) as
'shallow' lines so that the server is aware of the limitations of
the client's history.
The client now sends the maximum commit history depth it wants for
this transaction, which is the number of commits it wants from the
tip of the history, if any, as a 'deepen' line. A depth of 0 is the
same as not making a depth request. The client does not want to receive
any commits beyond this depth, nor does it want objects needed only to
complete those commits. Commits whose parents are not received as a
result are defined as shallow and marked as such in the server. This
information is sent back to the client in the next step.
Once all the 'want's and 'shallow's (and optional 'deepen') are
transferred, clients MUST send a flush-pkt, to tell the server side
that it is done sending the list.
Otherwise, if the client sent a positive depth request, the server
will determine which commits will and will not be shallow and
send this information to the client. If the client did not request
a positive depth, this step is skipped.
----
shallow-update = *shallow-line
*unshallow-line
flush-pkt
shallow-line = PKT-LINE("shallow" SP obj-id)
unshallow-line = PKT-LINE("unshallow" SP obj-id)
----
If the client has requested a positive depth, the server will compute
the set of commits which are no deeper than the desired depth. The set
of commits start at the client's wants.
The server writes 'shallow' lines for each
commit whose parents will not be sent as a result. The server writes
an 'unshallow' line for each commit which the client has indicated is
shallow, but is no longer shallow at the currently requested depth
(that is, its parents will now be sent). The server MUST NOT mark
as unshallow anything which the client has not indicated was shallow.
Now the client will send a list of the obj-ids it has using 'have'
lines, so the server can make a packfile that only contains the objects
that the client needs. In multi_ack mode, the canonical implementation
will send up to 32 of these at a time, then will send a flush-pkt. The
canonical implementation will skip ahead and send the next 32 immediately,
so that there is always a block of 32 "in-flight on the wire" at a time.
----
upload-haves = have-list
compute-end
have-list = *have-line
have-line = PKT-LINE("have" SP obj-id)
compute-end = flush-pkt / PKT-LINE("done")
----
If the server reads 'have' lines, it then will respond by ACKing any
of the obj-ids the client said it had that the server also has. The
server will ACK obj-ids differently depending on which ack mode is
chosen by the client.
In multi_ack mode:
* the server will respond with 'ACK obj-id continue' for any common
commits.
* once the server has found an acceptable common base commit and is
ready to make a packfile, it will blindly ACK all 'have' obj-ids
back to the client.
* the server will then send a 'NAK' and then wait for another response
from the client - either a 'done' or another list of 'have' lines.
In multi_ack_detailed mode:
* the server will differentiate the ACKs where it is signaling
that it is ready to send data with 'ACK obj-id ready' lines, and
signals the identified common commits with 'ACK obj-id common' lines.
Without either multi_ack or multi_ack_detailed:
* upload-pack sends "ACK obj-id" on the first common object it finds.
After that it says nothing until the client gives it a "done".
* upload-pack sends "NAK" on a flush-pkt if no common object
has been found yet. If one has been found, and thus an ACK
was already sent, it's silent on the flush-pkt.
After the client has gotten enough ACK responses that it can determine
that the server has enough information to send an efficient packfile
(in the canonical implementation, this is determined when it has received
enough ACKs that it can color everything left in the --date-order queue
as common with the server, or the --date-order queue is empty), or the
client determines that it wants to give up (in the canonical implementation,
this is determined when the client sends 256 'have' lines without getting
any of them ACKed by the server - meaning there is nothing in common and
the server should just send all of its objects), then the client will send
a 'done' command. The 'done' command signals to the server that the client
is ready to receive its packfile data.
However, the 256 limit *only* turns on in the canonical client
implementation if we have received at least one "ACK %s continue"
during a prior round. This helps to ensure that at least one common
ancestor is found before we give up entirely.
Once the 'done' line is read from the client, the server will either
send a final 'ACK obj-id' or it will send a 'NAK'. 'obj-id' is the object
name of the last commit determined to be common. The server only sends
ACK after 'done' if there is at least one common base and multi_ack or
multi_ack_detailed is enabled. The server always sends NAK after 'done'
if there is no common base found.
Then the server will start sending its packfile data.
----
server-response = *ack_multi ack / nak
ack_multi = PKT-LINE("ACK" SP obj-id ack_status)
ack_status = "continue" / "common" / "ready"
ack = PKT-LINE("ACK" SP obj-id)
nak = PKT-LINE("NAK")
----
A simple clone may look like this (with no 'have' lines):
----
C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d multi_ack \
side-band-64k ofs-delta\n
C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n
C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n
C: 0032want 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n
C: 0032want 74730d410fcb6603ace96f1dc55ea6196122532d\n
C: 0000
C: 0009done\n
S: 0008NAK\n
S: [PACKFILE]
----
An incremental update (fetch) response might look like this:
----
C: 0054want 74730d410fcb6603ace96f1dc55ea6196122532d multi_ack \
side-band-64k ofs-delta\n
C: 0032want 7d1665144a3a975c05f1f43902ddaf084e784dbe\n
C: 0032want 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a\n
C: 0000
C: 0032have 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01\n
C: [30 more have lines]
C: 0032have 74730d410fcb6603ace96f1dc55ea6196122532d\n
C: 0000
S: 003aACK 7e47fe2bd8d01d481f44d7af0531bd93d3b21c01 continue\n
S: 003aACK 74730d410fcb6603ace96f1dc55ea6196122532d continue\n
S: 0008NAK\n
C: 0009done\n
S: 0031ACK 74730d410fcb6603ace96f1dc55ea6196122532d\n
S: [PACKFILE]
----
Packfile Data
-------------
Now that the client and server have finished negotiation about what
the minimal amount of data that needs to be sent to the client is, the server
will construct and send the required data in packfile format.
See pack-format.txt for what the packfile itself actually looks like.
If 'side-band' or 'side-band-64k' capabilities have been specified by
the client, the server will send the packfile data multiplexed.
Each packet starting with the packet-line length of the amount of data
that follows, followed by a single byte specifying the sideband the
following data is coming in on.
In 'side-band' mode, it will send up to 999 data bytes plus 1 control
code, for a total of up to 1000 bytes in a pkt-line. In 'side-band-64k'
mode it will send up to 65519 data bytes plus 1 control code, for a
total of up to 65520 bytes in a pkt-line.
The sideband byte will be a '1', '2' or a '3'. Sideband '1' will contain
packfile data, sideband '2' will be used for progress information that the
client will generally print to stderr and sideband '3' is used for error
information.
If no 'side-band' capability was specified, the server will stream the
entire packfile without multiplexing.
Pushing Data To a Server
------------------------
Pushing data to a server will invoke the 'receive-pack' process on the
server, which will allow the client to tell it which references it should
update and then send all the data the server will need for those new
references to be complete. Once all the data is received and validated,
the server will then update its references to what the client specified.
Authentication
--------------
The protocol itself contains no authentication mechanisms. That is to be
handled by the transport, such as SSH, before the 'receive-pack' process is
invoked. If 'receive-pack' is configured over the Git transport, those
repositories will be writable by anyone who can access that port (9418) as
that transport is unauthenticated.
Reference Discovery
-------------------
The reference discovery phase is done nearly the same way as it is in the
fetching protocol. Each reference obj-id and name on the server is sent
in packet-line format to the client, followed by a flush-pkt. The only
real difference is that the capability listing is different - the only
possible values are 'report-status', 'delete-refs', 'ofs-delta' and
'push-options'.
Reference Update Request and Packfile Transfer
----------------------------------------------
Once the client knows what references the server is at, it can send a
list of reference update requests. For each reference on the server
that it wants to update, it sends a line listing the obj-id currently on
the server, the obj-id the client would like to update it to and the name
of the reference.
This list is followed by a flush-pkt. Then the push options are transmitted
one per packet followed by another flush-pkt. After that the packfile that
should contain all the objects that the server will need to complete the new
references will be sent.
----
update-request = *shallow ( command-list | push-cert ) [packfile]
shallow = PKT-LINE("shallow" SP obj-id)
command-list = PKT-LINE(command NUL capability-list)
*PKT-LINE(command)
flush-pkt
command = create / delete / update
create = zero-id SP new-id SP name
delete = old-id SP zero-id SP name
update = old-id SP new-id SP name
old-id = obj-id
new-id = obj-id
push-cert = PKT-LINE("push-cert" NUL capability-list LF)
PKT-LINE("certificate version 0.1" LF)
PKT-LINE("pusher" SP ident LF)
PKT-LINE("pushee" SP url LF)
PKT-LINE("nonce" SP nonce LF)
PKT-LINE(LF)
*PKT-LINE(command LF)
*PKT-LINE(gpg-signature-lines LF)
PKT-LINE("push-cert-end" LF)
packfile = "PACK" 28*(OCTET)
----
If the receiving end does not support delete-refs, the sending end MUST
NOT ask for delete command.
If the receiving end does not support push-cert, the sending end
MUST NOT send a push-cert command. When a push-cert command is
sent, command-list MUST NOT be sent; the commands recorded in the
push certificate is used instead.
The packfile MUST NOT be sent if the only command used is 'delete'.
A packfile MUST be sent if either create or update command is used,
even if the server already has all the necessary objects. In this
case the client MUST send an empty packfile. The only time this
is likely to happen is if the client is creating
a new branch or a tag that points to an existing obj-id.
The server will receive the packfile, unpack it, then validate each
reference that is being updated that it hasn't changed while the request
was being processed (the obj-id is still the same as the old-id), and
it will run any update hooks to make sure that the update is acceptable.
If all of that is fine, the server will then update the references.
Push Certificate
----------------
A push certificate begins with a set of header lines. After the
header and an empty line, the protocol commands follow, one per
line. Note that the trailing LF in push-cert PKT-LINEs is _not_
optional; it must be present.
Currently, the following header fields are defined:
`pusher` ident::
Identify the GPG key in "Human Readable Name "
format.
`pushee` url::
The repository URL (anonymized, if the URL contains
authentication material) the user who ran `git push`
intended to push into.
`nonce` nonce::
The 'nonce' string the receiving repository asked the
pushing user to include in the certificate, to prevent
replay attacks.
The GPG signature lines are a detached signature for the contents
recorded in the push certificate before the signature block begins.
The detached signature is used to certify that the commands were
given by the pusher, who must be the signer.
Report Status
-------------
After receiving the pack data from the sender, the receiver sends a
report if 'report-status' capability is in effect.
It is a short listing of what happened in that update. It will first
list the status of the packfile unpacking as either 'unpack ok' or
'unpack [error]'. Then it will list the status for each of the references
that it tried to update. Each line is either 'ok [refname]' if the
update was successful, or 'ng [refname] [error]' if the update was not.
----
report-status = unpack-status
1*(command-status)
flush-pkt
unpack-status = PKT-LINE("unpack" SP unpack-result)
unpack-result = "ok" / error-msg
command-status = command-ok / command-fail
command-ok = PKT-LINE("ok" SP refname)
command-fail = PKT-LINE("ng" SP refname SP error-msg)
error-msg = 1*(OCTECT) ; where not "ok"
----
Updates can be unsuccessful for a number of reasons. The reference can have
changed since the reference discovery phase was originally sent, meaning
someone pushed in the meantime. The reference being pushed could be a
non-fast-forward reference and the update hooks or configuration could be
set to not allow that, etc. Also, some references can be updated while others
can be rejected.
An example client/server communication might look like this:
----
S: 007c74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/local\0report-status delete-refs ofs-delta\n
S: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe refs/heads/debug\n
S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/master\n
S: 003f74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/team\n
S: 0000
C: 003e7d1665144a3a975c05f1f43902ddaf084e784dbe 74730d410fcb6603ace96f1dc55ea6196122532d refs/heads/debug\n
C: 003e74730d410fcb6603ace96f1dc55ea6196122532d 5a3f6be755bbb7deae50065988cbfa1ffa9ab68a refs/heads/master\n
C: 0000
C: [PACKDATA]
S: 000eunpack ok\n
S: 0018ok refs/heads/debug\n
S: 002ang refs/heads/master non-fast-forward\n
----
*/
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/filter.go
================================================
package packp
import (
"errors"
"fmt"
"github.com/go-git/go-git/v5/plumbing"
"net/url"
"strings"
)
var ErrUnsupportedObjectFilterType = errors.New("unsupported object filter type")
// Filter values enable the partial clone capability which causes
// the server to omit objects that match the filter.
//
// See [Git's documentation] for more details.
//
// [Git's documentation]: https://github.com/git/git/blob/e02ecfcc534e2021aae29077a958dd11c3897e4c/Documentation/rev-list-options.txt#L948
type Filter string
type BlobLimitPrefix string
const (
BlobLimitPrefixNone BlobLimitPrefix = ""
BlobLimitPrefixKibi BlobLimitPrefix = "k"
BlobLimitPrefixMebi BlobLimitPrefix = "m"
BlobLimitPrefixGibi BlobLimitPrefix = "g"
)
// FilterBlobNone omits all blobs.
func FilterBlobNone() Filter {
return "blob:none"
}
// FilterBlobLimit omits blobs of size at least n bytes (when prefix is
// BlobLimitPrefixNone), n kibibytes (when prefix is BlobLimitPrefixKibi),
// n mebibytes (when prefix is BlobLimitPrefixMebi) or n gibibytes (when
// prefix is BlobLimitPrefixGibi). n can be zero, in which case all blobs
// will be omitted.
func FilterBlobLimit(n uint64, prefix BlobLimitPrefix) Filter {
return Filter(fmt.Sprintf("blob:limit=%d%s", n, prefix))
}
// FilterTreeDepth omits all blobs and trees whose depth from the root tree
// is larger or equal to depth.
func FilterTreeDepth(depth uint64) Filter {
return Filter(fmt.Sprintf("tree:%d", depth))
}
// FilterObjectType omits all objects which are not of the requested type t.
// Supported types are TagObject, CommitObject, TreeObject and BlobObject.
func FilterObjectType(t plumbing.ObjectType) (Filter, error) {
switch t {
case plumbing.TagObject:
fallthrough
case plumbing.CommitObject:
fallthrough
case plumbing.TreeObject:
fallthrough
case plumbing.BlobObject:
return Filter(fmt.Sprintf("object:type=%s", t.String())), nil
default:
return "", fmt.Errorf("%w: %s", ErrUnsupportedObjectFilterType, t.String())
}
}
// FilterCombine combines multiple Filter values together.
func FilterCombine(filters ...Filter) Filter {
var escapedFilters []string
for _, filter := range filters {
escapedFilters = append(escapedFilters, url.QueryEscape(string(filter)))
}
return Filter(fmt.Sprintf("combine:%s", strings.Join(escapedFilters, "+")))
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/gitproto.go
================================================
package packp
import (
"fmt"
"io"
"strings"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
var (
// ErrInvalidGitProtoRequest is returned by Decode if the input is not a
// valid git protocol request.
ErrInvalidGitProtoRequest = fmt.Errorf("invalid git protocol request")
)
// GitProtoRequest is a command request for the git protocol.
// It is used to send the command, endpoint, and extra parameters to the
// remote.
// See https://git-scm.com/docs/pack-protocol#_git_transport
type GitProtoRequest struct {
RequestCommand string
Pathname string
// Optional
Host string
// Optional
ExtraParams []string
}
// validate validates the request.
func (g *GitProtoRequest) validate() error {
if g.RequestCommand == "" {
return fmt.Errorf("%w: empty request command", ErrInvalidGitProtoRequest)
}
if g.Pathname == "" {
return fmt.Errorf("%w: empty pathname", ErrInvalidGitProtoRequest)
}
return nil
}
// Encode encodes the request into the writer.
func (g *GitProtoRequest) Encode(w io.Writer) error {
if w == nil {
return ErrNilWriter
}
if err := g.validate(); err != nil {
return err
}
p := pktline.NewEncoder(w)
req := fmt.Sprintf("%s %s\x00", g.RequestCommand, g.Pathname)
if host := g.Host; host != "" {
req += fmt.Sprintf("host=%s\x00", host)
}
if len(g.ExtraParams) > 0 {
req += "\x00"
for _, param := range g.ExtraParams {
req += param + "\x00"
}
}
if err := p.Encode([]byte(req)); err != nil {
return err
}
return nil
}
// Decode decodes the request from the reader.
func (g *GitProtoRequest) Decode(r io.Reader) error {
s := pktline.NewScanner(r)
if !s.Scan() {
err := s.Err()
if err == nil {
return ErrInvalidGitProtoRequest
}
return err
}
line := string(s.Bytes())
if len(line) == 0 {
return io.EOF
}
if line[len(line)-1] != 0 {
return fmt.Errorf("%w: missing null terminator", ErrInvalidGitProtoRequest)
}
parts := strings.SplitN(line, " ", 2)
if len(parts) != 2 {
return fmt.Errorf("%w: short request", ErrInvalidGitProtoRequest)
}
g.RequestCommand = parts[0]
params := strings.Split(parts[1], string(null))
if len(params) < 1 {
return fmt.Errorf("%w: missing pathname", ErrInvalidGitProtoRequest)
}
g.Pathname = params[0]
if len(params) > 1 {
g.Host = strings.TrimPrefix(params[1], "host=")
}
if len(params) > 2 {
for _, param := range params[2:] {
if param != "" {
g.ExtraParams = append(g.ExtraParams, param)
}
}
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/report_status.go
================================================
package packp
import (
"bytes"
"fmt"
"io"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
const (
ok = "ok"
)
// ReportStatus is a report status message, as used in the git-receive-pack
// process whenever the 'report-status' capability is negotiated.
type ReportStatus struct {
UnpackStatus string
CommandStatuses []*CommandStatus
}
// NewReportStatus creates a new ReportStatus message.
func NewReportStatus() *ReportStatus {
return &ReportStatus{}
}
// Error returns the first error if any.
func (s *ReportStatus) Error() error {
if s.UnpackStatus != ok {
return fmt.Errorf("unpack error: %s", s.UnpackStatus)
}
for _, s := range s.CommandStatuses {
if err := s.Error(); err != nil {
return err
}
}
return nil
}
// Encode writes the report status to a writer.
func (s *ReportStatus) Encode(w io.Writer) error {
e := pktline.NewEncoder(w)
if err := e.Encodef("unpack %s\n", s.UnpackStatus); err != nil {
return err
}
for _, cs := range s.CommandStatuses {
if err := cs.encode(w); err != nil {
return err
}
}
return e.Flush()
}
// Decode reads from the given reader and decodes a report-status message. It
// does not read more input than what is needed to fill the report status.
func (s *ReportStatus) Decode(r io.Reader) error {
scan := pktline.NewScanner(r)
if err := s.scanFirstLine(scan); err != nil {
return err
}
if err := s.decodeReportStatus(scan.Bytes()); err != nil {
return err
}
flushed := false
for scan.Scan() {
b := scan.Bytes()
if isFlush(b) {
flushed = true
break
}
if err := s.decodeCommandStatus(b); err != nil {
return err
}
}
if !flushed {
return fmt.Errorf("missing flush")
}
return scan.Err()
}
func (s *ReportStatus) scanFirstLine(scan *pktline.Scanner) error {
if scan.Scan() {
return nil
}
if scan.Err() != nil {
return scan.Err()
}
return io.ErrUnexpectedEOF
}
func (s *ReportStatus) decodeReportStatus(b []byte) error {
if isFlush(b) {
return fmt.Errorf("premature flush")
}
b = bytes.TrimSuffix(b, eol)
line := string(b)
fields := strings.SplitN(line, " ", 2)
if len(fields) != 2 || fields[0] != "unpack" {
return fmt.Errorf("malformed unpack status: %s", line)
}
s.UnpackStatus = fields[1]
return nil
}
func (s *ReportStatus) decodeCommandStatus(b []byte) error {
b = bytes.TrimSuffix(b, eol)
line := string(b)
fields := strings.SplitN(line, " ", 3)
status := ok
if len(fields) == 3 && fields[0] == "ng" {
status = fields[2]
} else if len(fields) != 2 || fields[0] != "ok" {
return fmt.Errorf("malformed command status: %s", line)
}
cs := &CommandStatus{
ReferenceName: plumbing.ReferenceName(fields[1]),
Status: status,
}
s.CommandStatuses = append(s.CommandStatuses, cs)
return nil
}
// CommandStatus is the status of a reference in a report status.
// See ReportStatus struct.
type CommandStatus struct {
ReferenceName plumbing.ReferenceName
Status string
}
// Error returns the error, if any.
func (s *CommandStatus) Error() error {
if s.Status == ok {
return nil
}
return fmt.Errorf("command error on %s: %s",
s.ReferenceName.String(), s.Status)
}
func (s *CommandStatus) encode(w io.Writer) error {
e := pktline.NewEncoder(w)
if s.Error() == nil {
return e.Encodef("ok %s\n", s.ReferenceName.String())
}
return e.Encodef("ng %s %s\n", s.ReferenceName.String(), s.Status)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/shallowupd.go
================================================
package packp
import (
"bytes"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
const (
shallowLineLen = 48
unshallowLineLen = 50
)
type ShallowUpdate struct {
Shallows []plumbing.Hash
Unshallows []plumbing.Hash
}
func (r *ShallowUpdate) Decode(reader io.Reader) error {
s := pktline.NewScanner(reader)
for s.Scan() {
line := s.Bytes()
line = bytes.TrimSpace(line)
var err error
switch {
case bytes.HasPrefix(line, shallow):
err = r.decodeShallowLine(line)
case bytes.HasPrefix(line, unshallow):
err = r.decodeUnshallowLine(line)
case bytes.Equal(line, pktline.Flush):
return nil
}
if err != nil {
return err
}
}
return s.Err()
}
func (r *ShallowUpdate) decodeShallowLine(line []byte) error {
hash, err := r.decodeLine(line, shallow, shallowLineLen)
if err != nil {
return err
}
r.Shallows = append(r.Shallows, hash)
return nil
}
func (r *ShallowUpdate) decodeUnshallowLine(line []byte) error {
hash, err := r.decodeLine(line, unshallow, unshallowLineLen)
if err != nil {
return err
}
r.Unshallows = append(r.Unshallows, hash)
return nil
}
func (r *ShallowUpdate) decodeLine(line, prefix []byte, expLen int) (plumbing.Hash, error) {
if len(line) != expLen {
return plumbing.ZeroHash, fmt.Errorf("malformed %s%q", prefix, line)
}
raw := string(line[expLen-40 : expLen])
return plumbing.NewHash(raw), nil
}
func (r *ShallowUpdate) Encode(w io.Writer) error {
e := pktline.NewEncoder(w)
for _, h := range r.Shallows {
if err := e.Encodef("%s%s\n", shallow, h.String()); err != nil {
return err
}
}
for _, h := range r.Unshallows {
if err := e.Encodef("%s%s\n", unshallow, h.String()); err != nil {
return err
}
}
return e.Flush()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/common.go
================================================
package sideband
// Type sideband type "side-band" or "side-band-64k"
type Type int8
const (
// Sideband legacy sideband type up to 1000-byte messages
Sideband Type = iota
// Sideband64k sideband type up to 65519-byte messages
Sideband64k Type = iota
// MaxPackedSize for Sideband type
MaxPackedSize = 1000
// MaxPackedSize64k for Sideband64k type
MaxPackedSize64k = 65520
)
// Channel sideband channel
type Channel byte
// WithPayload encode the payload as a message
func (ch Channel) WithPayload(payload []byte) []byte {
return append([]byte{byte(ch)}, payload...)
}
const (
// PackData packfile content
PackData Channel = 1
// ProgressMessage progress messages
ProgressMessage Channel = 2
// ErrorMessage fatal error message just before stream aborts
ErrorMessage Channel = 3
)
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/demux.go
================================================
package sideband
import (
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
// ErrMaxPackedExceeded returned by Read, if the maximum packed size is exceeded
var ErrMaxPackedExceeded = errors.New("max. packed size exceeded")
// Progress where the progress information is stored
type Progress interface {
io.Writer
}
// Demuxer demultiplexes the progress reports and error info interleaved with the
// packfile itself.
//
// A sideband has three different channels the main one, called PackData, contains
// the packfile data; the ErrorMessage channel, that contains server errors; and
// the last one, ProgressMessage channel, containing information about the ongoing
// task happening in the server (optional, can be suppressed sending NoProgress
// or Quiet capabilities to the server)
//
// In order to demultiplex the data stream, method `Read` should be called to
// retrieve the PackData channel, the incoming data from the ProgressMessage is
// written at `Progress` (if any), if any message is retrieved from the
// ErrorMessage channel an error is returned and we can assume that the
// connection has been closed.
type Demuxer struct {
t Type
r io.Reader
s *pktline.Scanner
max int
pending []byte
// Progress is where the progress messages are stored
Progress Progress
}
// NewDemuxer returns a new Demuxer for the given t and read from r
func NewDemuxer(t Type, r io.Reader) *Demuxer {
max := MaxPackedSize64k
if t == Sideband {
max = MaxPackedSize
}
return &Demuxer{
t: t,
r: r,
max: max,
s: pktline.NewScanner(r),
}
}
// Read reads up to len(p) bytes from the PackData channel into p, an error can
// be return if an error happens when reading or if a message is sent in the
// ErrorMessage channel.
//
// When a ProgressMessage is read, is not copy to b, instead of this is written
// to the Progress
func (d *Demuxer) Read(b []byte) (n int, err error) {
var read, req int
req = len(b)
for read < req {
n, err := d.doRead(b[read:req])
read += n
if err != nil {
return read, err
}
}
return read, nil
}
func (d *Demuxer) doRead(b []byte) (int, error) {
read, err := d.nextPackData()
size := len(read)
wanted := len(b)
if size > wanted {
d.pending = read[wanted:]
}
if wanted > size {
wanted = size
}
size = copy(b, read[:wanted])
return size, err
}
func (d *Demuxer) nextPackData() ([]byte, error) {
content := d.getPending()
if len(content) != 0 {
return content, nil
}
if !d.s.Scan() {
if err := d.s.Err(); err != nil {
return nil, err
}
return nil, io.EOF
}
content = d.s.Bytes()
size := len(content)
if size == 0 {
return nil, io.EOF
} else if size > d.max {
return nil, ErrMaxPackedExceeded
}
switch Channel(content[0]) {
case PackData:
return content[1:], nil
case ProgressMessage:
if d.Progress != nil {
_, err := d.Progress.Write(content[1:])
return nil, err
}
case ErrorMessage:
return nil, fmt.Errorf("unexpected error: %s", content[1:])
default:
return nil, fmt.Errorf("unknown channel %s", content)
}
return nil, nil
}
func (d *Demuxer) getPending() (b []byte) {
if len(d.pending) == 0 {
return nil
}
content := d.pending
d.pending = nil
return content
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/doc.go
================================================
// Package sideband implements a sideband mutiplex/demultiplexer
package sideband
// If 'side-band' or 'side-band-64k' capabilities have been specified by
// the client, the server will send the packfile data multiplexed.
//
// Either mode indicates that the packfile data will be streamed broken
// up into packets of up to either 1000 bytes in the case of 'side_band',
// or 65520 bytes in the case of 'side_band_64k'. Each packet is made up
// of a leading 4-byte pkt-line length of how much data is in the packet,
// followed by a 1-byte stream code, followed by the actual data.
//
// The stream code can be one of:
//
// 1 - pack data
// 2 - progress messages
// 3 - fatal error message just before stream aborts
//
// The "side-band-64k" capability came about as a way for newer clients
// that can handle much larger packets to request packets that are
// actually crammed nearly full, while maintaining backward compatibility
// for the older clients.
//
// Further, with side-band and its up to 1000-byte messages, it's actually
// 999 bytes of payload and 1 byte for the stream code. With side-band-64k,
// same deal, you have up to 65519 bytes of data and 1 byte for the stream
// code.
//
// The client MUST send only maximum of one of "side-band" and "side-
// band-64k". Server MUST diagnose it as an error if client requests
// both.
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband/muxer.go
================================================
package sideband
import (
"io"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
// Muxer multiplex the packfile along with the progress messages and the error
// information. The multiplex is perform using pktline format.
type Muxer struct {
max int
e *pktline.Encoder
}
const chLen = 1
// NewMuxer returns a new Muxer for the given t that writes on w.
//
// If t is equal to `Sideband` the max pack size is set to MaxPackedSize, in any
// other value is given, max pack is set to MaxPackedSize64k, that is the
// maximum length of a line in pktline format.
func NewMuxer(t Type, w io.Writer) *Muxer {
max := MaxPackedSize64k
if t == Sideband {
max = MaxPackedSize
}
return &Muxer{
max: max - chLen,
e: pktline.NewEncoder(w),
}
}
// Write writes p in the PackData channel
func (m *Muxer) Write(p []byte) (int, error) {
return m.WriteChannel(PackData, p)
}
// WriteChannel writes p in the given channel. This method can be used with any
// channel, but is recommend use it only for the ProgressMessage and
// ErrorMessage channels and use Write for the PackData channel
func (m *Muxer) WriteChannel(t Channel, p []byte) (int, error) {
wrote := 0
size := len(p)
for wrote < size {
n, err := m.doWrite(t, p[wrote:])
wrote += n
if err != nil {
return wrote, err
}
}
return wrote, nil
}
func (m *Muxer) doWrite(ch Channel, p []byte) (int, error) {
sz := len(p)
if sz > m.max {
sz = m.max
}
return sz, m.e.Encode(ch.WithPayload(p[:sz]))
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/srvresp.go
================================================
package packp
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
const ackLineLen = 44
// ServerResponse object acknowledgement from upload-pack service
type ServerResponse struct {
ACKs []plumbing.Hash
}
// Decode decodes the response into the struct, isMultiACK should be true, if
// the request was done with multi_ack or multi_ack_detailed capabilities.
func (r *ServerResponse) Decode(reader *bufio.Reader, isMultiACK bool) error {
s := pktline.NewScanner(reader)
for s.Scan() {
line := s.Bytes()
if err := r.decodeLine(line); err != nil {
return err
}
// we need to detect when the end of a response header and the beginning
// of a packfile header happened, some requests to the git daemon
// produces a duplicate ACK header even when multi_ack is not supported.
stop, err := r.stopReading(reader)
if err != nil {
return err
}
if stop {
break
}
}
// isMultiACK is true when the remote server advertises the related
// capabilities when they are not in transport.UnsupportedCapabilities.
//
// Users may decide to remove multi_ack and multi_ack_detailed from the
// unsupported capabilities list, which allows them to do initial clones
// from Azure DevOps.
//
// Follow-up fetches may error, therefore errors are wrapped with additional
// information highlighting that this capabilities are not supported by go-git.
//
// TODO: Implement support for multi_ack or multi_ack_detailed responses.
err := s.Err()
if err != nil && isMultiACK {
return fmt.Errorf("multi_ack and multi_ack_detailed are not supported: %w", err)
}
return err
}
// stopReading detects when a valid command such as ACK or NAK is found to be
// read in the buffer without moving the read pointer.
func (r *ServerResponse) stopReading(reader *bufio.Reader) (bool, error) {
ahead, err := reader.Peek(7)
if err == io.EOF {
return true, nil
}
if err != nil {
return false, err
}
if len(ahead) > 4 && r.isValidCommand(ahead[0:3]) {
return false, nil
}
if len(ahead) == 7 && r.isValidCommand(ahead[4:]) {
return false, nil
}
return true, nil
}
func (r *ServerResponse) isValidCommand(b []byte) bool {
commands := [][]byte{ack, nak}
for _, c := range commands {
if bytes.Equal(b, c) {
return true
}
}
return false
}
func (r *ServerResponse) decodeLine(line []byte) error {
if len(line) == 0 {
return fmt.Errorf("unexpected flush")
}
if len(line) >= 3 {
if bytes.Equal(line[0:3], ack) {
return r.decodeACKLine(line)
}
if bytes.Equal(line[0:3], nak) {
return nil
}
}
return fmt.Errorf("unexpected content %q", string(line))
}
func (r *ServerResponse) decodeACKLine(line []byte) error {
if len(line) < ackLineLen {
return fmt.Errorf("malformed ACK %q", line)
}
sp := bytes.Index(line, []byte(" "))
if sp+41 > len(line) {
return fmt.Errorf("malformed ACK %q", line)
}
h := plumbing.NewHash(string(line[sp+1 : sp+41]))
r.ACKs = append(r.ACKs, h)
return nil
}
// Encode encodes the ServerResponse into a writer.
func (r *ServerResponse) Encode(w io.Writer, isMultiACK bool) error {
if len(r.ACKs) > 1 && !isMultiACK {
// For further information, refer to comments in the Decode func above.
return errors.New("multi_ack and multi_ack_detailed are not supported")
}
e := pktline.NewEncoder(w)
if len(r.ACKs) == 0 {
return e.Encodef("%s\n", nak)
}
return e.Encodef("%s %s\n", ack, r.ACKs[0].String())
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq.go
================================================
package packp
import (
"fmt"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
)
// UploadRequest values represent the information transmitted on a
// upload-request message. Values from this type are not zero-value
// safe, use the New function instead.
// This is a low level type, use UploadPackRequest instead.
type UploadRequest struct {
Capabilities *capability.List
Wants []plumbing.Hash
Shallows []plumbing.Hash
Depth Depth
Filter Filter
}
// Depth values stores the desired depth of the requested packfile: see
// DepthCommit, DepthSince and DepthReference.
type Depth interface {
isDepth()
IsZero() bool
}
// DepthCommits values stores the maximum number of requested commits in
// the packfile. Zero means infinite. A negative value will have
// undefined consequences.
type DepthCommits int
func (d DepthCommits) isDepth() {}
func (d DepthCommits) IsZero() bool {
return d == 0
}
// DepthSince values requests only commits newer than the specified time.
type DepthSince time.Time
func (d DepthSince) isDepth() {}
func (d DepthSince) IsZero() bool {
return time.Time(d).IsZero()
}
// DepthReference requests only commits not to found in the specified reference.
type DepthReference string
func (d DepthReference) isDepth() {}
func (d DepthReference) IsZero() bool {
return string(d) == ""
}
// NewUploadRequest returns a pointer to a new UploadRequest value, ready to be
// used. It has no capabilities, wants or shallows and an infinite depth. Please
// note that to encode an upload-request it has to have at least one wanted hash.
func NewUploadRequest() *UploadRequest {
return &UploadRequest{
Capabilities: capability.NewList(),
Wants: []plumbing.Hash{},
Shallows: []plumbing.Hash{},
Depth: DepthCommits(0),
}
}
// NewUploadRequestFromCapabilities returns a pointer to a new UploadRequest
// value, the request capabilities are filled with the most optimal ones, based
// on the adv value (advertised capabilities), the UploadRequest generated it
// has no wants or shallows and an infinite depth.
func NewUploadRequestFromCapabilities(adv *capability.List) *UploadRequest {
r := NewUploadRequest()
if adv.Supports(capability.MultiACKDetailed) {
r.Capabilities.Set(capability.MultiACKDetailed)
} else if adv.Supports(capability.MultiACK) {
r.Capabilities.Set(capability.MultiACK)
}
if adv.Supports(capability.Sideband64k) {
r.Capabilities.Set(capability.Sideband64k)
} else if adv.Supports(capability.Sideband) {
r.Capabilities.Set(capability.Sideband)
}
if adv.Supports(capability.ThinPack) {
r.Capabilities.Set(capability.ThinPack)
}
if adv.Supports(capability.OFSDelta) {
r.Capabilities.Set(capability.OFSDelta)
}
if adv.Supports(capability.Agent) {
r.Capabilities.Set(capability.Agent, capability.DefaultAgent())
}
return r
}
// Validate validates the content of UploadRequest, following the next rules:
// - Wants MUST have at least one reference
// - capability.Shallow MUST be present if Shallows is not empty
// - is a non-zero DepthCommits is given capability.Shallow MUST be present
// - is a DepthSince is given capability.Shallow MUST be present
// - is a DepthReference is given capability.DeepenNot MUST be present
// - MUST contain only maximum of one of capability.Sideband and capability.Sideband64k
// - MUST contain only maximum of one of capability.MultiACK and capability.MultiACKDetailed
func (req *UploadRequest) Validate() error {
if len(req.Wants) == 0 {
return fmt.Errorf("want can't be empty")
}
if err := req.validateRequiredCapabilities(); err != nil {
return err
}
if err := req.validateConflictCapabilities(); err != nil {
return err
}
return nil
}
func (req *UploadRequest) validateRequiredCapabilities() error {
msg := "missing capability %s"
if len(req.Shallows) != 0 && !req.Capabilities.Supports(capability.Shallow) {
return fmt.Errorf(msg, capability.Shallow)
}
switch req.Depth.(type) {
case DepthCommits:
if req.Depth != DepthCommits(0) {
if !req.Capabilities.Supports(capability.Shallow) {
return fmt.Errorf(msg, capability.Shallow)
}
}
case DepthSince:
if !req.Capabilities.Supports(capability.DeepenSince) {
return fmt.Errorf(msg, capability.DeepenSince)
}
case DepthReference:
if !req.Capabilities.Supports(capability.DeepenNot) {
return fmt.Errorf(msg, capability.DeepenNot)
}
}
return nil
}
func (req *UploadRequest) validateConflictCapabilities() error {
msg := "capabilities %s and %s are mutually exclusive"
if req.Capabilities.Supports(capability.Sideband) &&
req.Capabilities.Supports(capability.Sideband64k) {
return fmt.Errorf(msg, capability.Sideband, capability.Sideband64k)
}
if req.Capabilities.Supports(capability.MultiACK) &&
req.Capabilities.Supports(capability.MultiACKDetailed) {
return fmt.Errorf(msg, capability.MultiACK, capability.MultiACKDetailed)
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_decode.go
================================================
package packp
import (
"bytes"
"encoding/hex"
"fmt"
"io"
"strconv"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
// Decode reads the next upload-request form its input and
// stores it in the UploadRequest.
func (req *UploadRequest) Decode(r io.Reader) error {
d := newUlReqDecoder(r)
return d.Decode(req)
}
type ulReqDecoder struct {
s *pktline.Scanner // a pkt-line scanner from the input stream
line []byte // current pkt-line contents, use parser.nextLine() to make it advance
nLine int // current pkt-line number for debugging, begins at 1
err error // sticky error, use the parser.error() method to fill this out
data *UploadRequest // parsed data is stored here
}
func newUlReqDecoder(r io.Reader) *ulReqDecoder {
return &ulReqDecoder{
s: pktline.NewScanner(r),
}
}
func (d *ulReqDecoder) Decode(v *UploadRequest) error {
d.data = v
for state := d.decodeFirstWant; state != nil; {
state = state()
}
return d.err
}
// fills out the parser sticky error
func (d *ulReqDecoder) error(format string, a ...interface{}) {
msg := fmt.Sprintf(
"pkt-line %d: %s", d.nLine,
fmt.Sprintf(format, a...),
)
d.err = NewErrUnexpectedData(msg, d.line)
}
// Reads a new pkt-line from the scanner, makes its payload available as
// p.line and increments p.nLine. A successful invocation returns true,
// otherwise, false is returned and the sticky error is filled out
// accordingly. Trims eols at the end of the payloads.
func (d *ulReqDecoder) nextLine() bool {
d.nLine++
if !d.s.Scan() {
if d.err = d.s.Err(); d.err != nil {
return false
}
d.error("EOF")
return false
}
d.line = d.s.Bytes()
d.line = bytes.TrimSuffix(d.line, eol)
return true
}
// Expected format: want [ capabilities]
func (d *ulReqDecoder) decodeFirstWant() stateFn {
if ok := d.nextLine(); !ok {
return nil
}
if !bytes.HasPrefix(d.line, want) {
d.error("missing 'want ' prefix")
return nil
}
d.line = bytes.TrimPrefix(d.line, want)
hash, ok := d.readHash()
if !ok {
return nil
}
d.data.Wants = append(d.data.Wants, hash)
return d.decodeCaps
}
func (d *ulReqDecoder) readHash() (plumbing.Hash, bool) {
if len(d.line) < hashSize {
d.err = fmt.Errorf("malformed hash: %v", d.line)
return plumbing.ZeroHash, false
}
var hash plumbing.Hash
if _, err := hex.Decode(hash[:], d.line[:hashSize]); err != nil {
d.error("invalid hash text: %s", err)
return plumbing.ZeroHash, false
}
d.line = d.line[hashSize:]
return hash, true
}
// Expected format: sp cap1 sp cap2 sp cap3...
func (d *ulReqDecoder) decodeCaps() stateFn {
d.line = bytes.TrimPrefix(d.line, sp)
if err := d.data.Capabilities.Decode(d.line); err != nil {
d.error("invalid capabilities: %s", err)
}
return d.decodeOtherWants
}
// Expected format: want
func (d *ulReqDecoder) decodeOtherWants() stateFn {
if ok := d.nextLine(); !ok {
return nil
}
if bytes.HasPrefix(d.line, shallow) {
return d.decodeShallow
}
if bytes.HasPrefix(d.line, deepen) {
return d.decodeDeepen
}
if len(d.line) == 0 {
return nil
}
if !bytes.HasPrefix(d.line, want) {
d.error("unexpected payload while expecting a want: %q", d.line)
return nil
}
d.line = bytes.TrimPrefix(d.line, want)
hash, ok := d.readHash()
if !ok {
return nil
}
d.data.Wants = append(d.data.Wants, hash)
return d.decodeOtherWants
}
// Expected format: shallow
func (d *ulReqDecoder) decodeShallow() stateFn {
if bytes.HasPrefix(d.line, deepen) {
return d.decodeDeepen
}
if len(d.line) == 0 {
return nil
}
if !bytes.HasPrefix(d.line, shallow) {
d.error("unexpected payload while expecting a shallow: %q", d.line)
return nil
}
d.line = bytes.TrimPrefix(d.line, shallow)
hash, ok := d.readHash()
if !ok {
return nil
}
d.data.Shallows = append(d.data.Shallows, hash)
if ok := d.nextLine(); !ok {
return nil
}
return d.decodeShallow
}
// Expected format: deepen / deepen-since / deepen-not [
func (d *ulReqDecoder) decodeDeepen() stateFn {
if bytes.HasPrefix(d.line, deepenCommits) {
return d.decodeDeepenCommits
}
if bytes.HasPrefix(d.line, deepenSince) {
return d.decodeDeepenSince
}
if bytes.HasPrefix(d.line, deepenReference) {
return d.decodeDeepenReference
}
if len(d.line) == 0 {
return nil
}
d.error("unexpected deepen specification: %q", d.line)
return nil
}
func (d *ulReqDecoder) decodeDeepenCommits() stateFn {
d.line = bytes.TrimPrefix(d.line, deepenCommits)
var n int
if n, d.err = strconv.Atoi(string(d.line)); d.err != nil {
return nil
}
if n < 0 {
d.err = fmt.Errorf("negative depth")
return nil
}
d.data.Depth = DepthCommits(n)
return d.decodeFlush
}
func (d *ulReqDecoder) decodeDeepenSince() stateFn {
d.line = bytes.TrimPrefix(d.line, deepenSince)
var secs int64
secs, d.err = strconv.ParseInt(string(d.line), 10, 64)
if d.err != nil {
return nil
}
t := time.Unix(secs, 0).UTC()
d.data.Depth = DepthSince(t)
return d.decodeFlush
}
func (d *ulReqDecoder) decodeDeepenReference() stateFn {
d.line = bytes.TrimPrefix(d.line, deepenReference)
d.data.Depth = DepthReference(string(d.line))
return d.decodeFlush
}
func (d *ulReqDecoder) decodeFlush() stateFn {
if ok := d.nextLine(); !ok {
return nil
}
if len(d.line) != 0 {
d.err = fmt.Errorf("unexpected payload while expecting a flush-pkt: %q", d.line)
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/ulreq_encode.go
================================================
package packp
import (
"bytes"
"fmt"
"io"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
// Encode writes the UlReq encoding of u to the stream.
//
// All the payloads will end with a newline character. Wants and
// shallows are sorted alphabetically. A depth of 0 means no depth
// request is sent.
func (req *UploadRequest) Encode(w io.Writer) error {
e := newUlReqEncoder(w)
return e.Encode(req)
}
type ulReqEncoder struct {
pe *pktline.Encoder // where to write the encoded data
data *UploadRequest // the data to encode
err error // sticky error
}
func newUlReqEncoder(w io.Writer) *ulReqEncoder {
return &ulReqEncoder{
pe: pktline.NewEncoder(w),
}
}
func (e *ulReqEncoder) Encode(v *UploadRequest) error {
e.data = v
if len(v.Wants) == 0 {
return fmt.Errorf("empty wants provided")
}
plumbing.HashesSort(e.data.Wants)
for state := e.encodeFirstWant; state != nil; {
state = state()
}
return e.err
}
func (e *ulReqEncoder) encodeFirstWant() stateFn {
var err error
if e.data.Capabilities.IsEmpty() {
err = e.pe.Encodef("want %s\n", e.data.Wants[0])
} else {
err = e.pe.Encodef(
"want %s %s\n",
e.data.Wants[0],
e.data.Capabilities.String(),
)
}
if err != nil {
e.err = fmt.Errorf("encoding first want line: %s", err)
return nil
}
return e.encodeAdditionalWants
}
func (e *ulReqEncoder) encodeAdditionalWants() stateFn {
last := e.data.Wants[0]
for _, w := range e.data.Wants[1:] {
if bytes.Equal(last[:], w[:]) {
continue
}
if err := e.pe.Encodef("want %s\n", w); err != nil {
e.err = fmt.Errorf("encoding want %q: %s", w, err)
return nil
}
last = w
}
return e.encodeShallows
}
func (e *ulReqEncoder) encodeShallows() stateFn {
plumbing.HashesSort(e.data.Shallows)
var last plumbing.Hash
for _, s := range e.data.Shallows {
if bytes.Equal(last[:], s[:]) {
continue
}
if err := e.pe.Encodef("shallow %s\n", s); err != nil {
e.err = fmt.Errorf("encoding shallow %q: %s", s, err)
return nil
}
last = s
}
return e.encodeDepth
}
func (e *ulReqEncoder) encodeDepth() stateFn {
switch depth := e.data.Depth.(type) {
case DepthCommits:
if depth != 0 {
commits := int(depth)
if err := e.pe.Encodef("deepen %d\n", commits); err != nil {
e.err = fmt.Errorf("encoding depth %d: %s", depth, err)
return nil
}
}
case DepthSince:
when := time.Time(depth).UTC()
if err := e.pe.Encodef("deepen-since %d\n", when.Unix()); err != nil {
e.err = fmt.Errorf("encoding depth %s: %s", when, err)
return nil
}
case DepthReference:
reference := string(depth)
if err := e.pe.Encodef("deepen-not %s\n", reference); err != nil {
e.err = fmt.Errorf("encoding depth %s: %s", reference, err)
return nil
}
default:
e.err = fmt.Errorf("unsupported depth type")
return nil
}
return e.encodeFilter
}
func (e *ulReqEncoder) encodeFilter() stateFn {
if filter := e.data.Filter; filter != "" {
if err := e.pe.Encodef("filter %s\n", filter); err != nil {
e.err = fmt.Errorf("encoding filter %s: %s", filter, err)
return nil
}
}
return e.encodeFlush
}
func (e *ulReqEncoder) encodeFlush() stateFn {
if err := e.pe.Flush(); err != nil {
e.err = fmt.Errorf("encoding flush-pkt: %s", err)
return nil
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq.go
================================================
package packp
import (
"errors"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
)
var (
ErrEmptyCommands = errors.New("commands cannot be empty")
ErrMalformedCommand = errors.New("malformed command")
)
// ReferenceUpdateRequest values represent reference upload requests.
// Values from this type are not zero-value safe, use the New function instead.
type ReferenceUpdateRequest struct {
Capabilities *capability.List
Commands []*Command
Options []*Option
Shallow *plumbing.Hash
// Packfile contains an optional packfile reader.
Packfile io.ReadCloser
// Progress receives sideband progress messages from the server
Progress sideband.Progress
}
// New returns a pointer to a new ReferenceUpdateRequest value.
func NewReferenceUpdateRequest() *ReferenceUpdateRequest {
return &ReferenceUpdateRequest{
// TODO: Add support for push-cert
Capabilities: capability.NewList(),
Commands: nil,
}
}
// NewReferenceUpdateRequestFromCapabilities returns a pointer to a new
// ReferenceUpdateRequest value, the request capabilities are filled with the
// most optimal ones, based on the adv value (advertised capabilities), the
// ReferenceUpdateRequest contains no commands
//
// It does set the following capabilities:
// - agent
// - report-status
// - ofs-delta
// - ref-delta
// - delete-refs
// It leaves up to the user to add the following capabilities later:
// - atomic
// - ofs-delta
// - side-band
// - side-band-64k
// - quiet
// - push-cert
func NewReferenceUpdateRequestFromCapabilities(adv *capability.List) *ReferenceUpdateRequest {
r := NewReferenceUpdateRequest()
if adv.Supports(capability.Agent) {
r.Capabilities.Set(capability.Agent, capability.DefaultAgent())
}
if adv.Supports(capability.ReportStatus) {
r.Capabilities.Set(capability.ReportStatus)
}
return r
}
func (req *ReferenceUpdateRequest) validate() error {
if len(req.Commands) == 0 {
return ErrEmptyCommands
}
for _, c := range req.Commands {
if err := c.validate(); err != nil {
return err
}
}
return nil
}
type Action string
const (
Create Action = "create"
Update Action = "update"
Delete Action = "delete"
Invalid Action = "invalid"
)
type Command struct {
Name plumbing.ReferenceName
Old plumbing.Hash
New plumbing.Hash
}
func (c *Command) Action() Action {
if c.Old == plumbing.ZeroHash && c.New == plumbing.ZeroHash {
return Invalid
}
if c.Old == plumbing.ZeroHash {
return Create
}
if c.New == plumbing.ZeroHash {
return Delete
}
return Update
}
func (c *Command) validate() error {
if c.Action() == Invalid {
return ErrMalformedCommand
}
return nil
}
type Option struct {
Key string
Value string
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_decode.go
================================================
package packp
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
)
var (
shallowLineLength = len(shallow) + hashSize
minCommandLength = hashSize*2 + 2 + 1
minCommandAndCapsLength = minCommandLength + 1
)
var (
ErrEmpty = errors.New("empty update-request message")
errNoCommands = errors.New("unexpected EOF before any command")
errMissingCapabilitiesDelimiter = errors.New("capabilities delimiter not found")
)
func errMalformedRequest(reason string) error {
return fmt.Errorf("malformed request: %s", reason)
}
func errInvalidHashSize(got int) error {
return fmt.Errorf("invalid hash size: expected %d, got %d",
hashSize, got)
}
func errInvalidHash(err error) error {
return fmt.Errorf("invalid hash: %s", err.Error())
}
func errInvalidShallowLineLength(got int) error {
return errMalformedRequest(fmt.Sprintf(
"invalid shallow line length: expected %d, got %d",
shallowLineLength, got))
}
func errInvalidCommandCapabilitiesLineLength(got int) error {
return errMalformedRequest(fmt.Sprintf(
"invalid command and capabilities line length: expected at least %d, got %d",
minCommandAndCapsLength, got))
}
func errInvalidCommandLineLength(got int) error {
return errMalformedRequest(fmt.Sprintf(
"invalid command line length: expected at least %d, got %d",
minCommandLength, got))
}
func errInvalidShallowObjId(err error) error {
return errMalformedRequest(
fmt.Sprintf("invalid shallow object id: %s", err.Error()))
}
func errInvalidOldObjId(err error) error {
return errMalformedRequest(
fmt.Sprintf("invalid old object id: %s", err.Error()))
}
func errInvalidNewObjId(err error) error {
return errMalformedRequest(
fmt.Sprintf("invalid new object id: %s", err.Error()))
}
func errMalformedCommand(err error) error {
return errMalformedRequest(fmt.Sprintf(
"malformed command: %s", err.Error()))
}
// Decode reads the next update-request message form the reader and wr
func (req *ReferenceUpdateRequest) Decode(r io.Reader) error {
var rc io.ReadCloser
var ok bool
rc, ok = r.(io.ReadCloser)
if !ok {
rc = io.NopCloser(r)
}
d := &updReqDecoder{r: rc, s: pktline.NewScanner(r)}
return d.Decode(req)
}
type updReqDecoder struct {
r io.ReadCloser
s *pktline.Scanner
req *ReferenceUpdateRequest
}
func (d *updReqDecoder) Decode(req *ReferenceUpdateRequest) error {
d.req = req
funcs := []func() error{
d.scanLine,
d.decodeShallow,
d.decodeCommandAndCapabilities,
d.decodeCommands,
d.setPackfile,
req.validate,
}
for _, f := range funcs {
if err := f(); err != nil {
return err
}
}
return nil
}
func (d *updReqDecoder) scanLine() error {
if ok := d.s.Scan(); !ok {
return d.scanErrorOr(ErrEmpty)
}
return nil
}
func (d *updReqDecoder) decodeShallow() error {
b := d.s.Bytes()
if !bytes.HasPrefix(b, shallowNoSp) {
return nil
}
if len(b) != shallowLineLength {
return errInvalidShallowLineLength(len(b))
}
h, err := parseHash(string(b[len(shallow):]))
if err != nil {
return errInvalidShallowObjId(err)
}
if ok := d.s.Scan(); !ok {
return d.scanErrorOr(errNoCommands)
}
d.req.Shallow = &h
return nil
}
func (d *updReqDecoder) decodeCommands() error {
for {
b := d.s.Bytes()
if bytes.Equal(b, pktline.Flush) {
return nil
}
c, err := parseCommand(b)
if err != nil {
return err
}
d.req.Commands = append(d.req.Commands, c)
if ok := d.s.Scan(); !ok {
return d.s.Err()
}
}
}
func (d *updReqDecoder) decodeCommandAndCapabilities() error {
b := d.s.Bytes()
i := bytes.IndexByte(b, 0)
if i == -1 {
return errMissingCapabilitiesDelimiter
}
if len(b) < minCommandAndCapsLength {
return errInvalidCommandCapabilitiesLineLength(len(b))
}
cmd, err := parseCommand(b[:i])
if err != nil {
return err
}
d.req.Commands = append(d.req.Commands, cmd)
if err := d.req.Capabilities.Decode(b[i+1:]); err != nil {
return err
}
if err := d.scanLine(); err != nil {
return err
}
return nil
}
func (d *updReqDecoder) setPackfile() error {
d.req.Packfile = d.r
return nil
}
func parseCommand(b []byte) (*Command, error) {
if len(b) < minCommandLength {
return nil, errInvalidCommandLineLength(len(b))
}
var (
os, ns string
n plumbing.ReferenceName
)
if _, err := fmt.Sscanf(string(b), "%s %s %s", &os, &ns, &n); err != nil {
return nil, errMalformedCommand(err)
}
oh, err := parseHash(os)
if err != nil {
return nil, errInvalidOldObjId(err)
}
nh, err := parseHash(ns)
if err != nil {
return nil, errInvalidNewObjId(err)
}
return &Command{Old: oh, New: nh, Name: n}, nil
}
func parseHash(s string) (plumbing.Hash, error) {
if len(s) != hashSize {
return plumbing.ZeroHash, errInvalidHashSize(len(s))
}
if _, err := hex.DecodeString(s); err != nil {
return plumbing.ZeroHash, errInvalidHash(err)
}
h := plumbing.NewHash(s)
return h, nil
}
func (d *updReqDecoder) scanErrorOr(origErr error) error {
if err := d.s.Err(); err != nil {
return err
}
return origErr
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/updreq_encode.go
================================================
package packp
import (
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
)
// Encode writes the ReferenceUpdateRequest encoding to the stream.
func (req *ReferenceUpdateRequest) Encode(w io.Writer) error {
if err := req.validate(); err != nil {
return err
}
e := pktline.NewEncoder(w)
if err := req.encodeShallow(e, req.Shallow); err != nil {
return err
}
if err := req.encodeCommands(e, req.Commands, req.Capabilities); err != nil {
return err
}
if req.Capabilities.Supports(capability.PushOptions) {
if err := req.encodeOptions(e, req.Options); err != nil {
return err
}
}
if req.Packfile != nil {
if _, err := io.Copy(w, req.Packfile); err != nil {
return err
}
return req.Packfile.Close()
}
return nil
}
func (req *ReferenceUpdateRequest) encodeShallow(e *pktline.Encoder,
h *plumbing.Hash) error {
if h == nil {
return nil
}
objId := []byte(h.String())
return e.Encodef("%s%s", shallow, objId)
}
func (req *ReferenceUpdateRequest) encodeCommands(e *pktline.Encoder,
cmds []*Command, cap *capability.List) error {
if err := e.Encodef("%s\x00%s",
formatCommand(cmds[0]), cap.String()); err != nil {
return err
}
for _, cmd := range cmds[1:] {
if err := e.Encodef(formatCommand(cmd)); err != nil {
return err
}
}
return e.Flush()
}
func formatCommand(cmd *Command) string {
o := cmd.Old.String()
n := cmd.New.String()
return fmt.Sprintf("%s %s %s", o, n, cmd.Name)
}
func (req *ReferenceUpdateRequest) encodeOptions(e *pktline.Encoder,
opts []*Option) error {
for _, opt := range opts {
if err := e.Encodef("%s=%s", opt.Key, opt.Value); err != nil {
return err
}
}
return e.Flush()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/uppackreq.go
================================================
package packp
import (
"bytes"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
)
// UploadPackRequest represents a upload-pack request.
// Zero-value is not safe, use NewUploadPackRequest instead.
type UploadPackRequest struct {
UploadRequest
UploadHaves
}
// NewUploadPackRequest creates a new UploadPackRequest and returns a pointer.
func NewUploadPackRequest() *UploadPackRequest {
ur := NewUploadRequest()
return &UploadPackRequest{
UploadHaves: UploadHaves{},
UploadRequest: *ur,
}
}
// NewUploadPackRequestFromCapabilities creates a new UploadPackRequest and
// returns a pointer. The request capabilities are filled with the most optimal
// ones, based on the adv value (advertised capabilities), the UploadPackRequest
// it has no wants, haves or shallows and an infinite depth
func NewUploadPackRequestFromCapabilities(adv *capability.List) *UploadPackRequest {
ur := NewUploadRequestFromCapabilities(adv)
return &UploadPackRequest{
UploadHaves: UploadHaves{},
UploadRequest: *ur,
}
}
// IsEmpty returns whether a request is empty - it is empty if Haves are contained
// in the Wants, or if Wants length is zero, and we don't have any shallows
func (r *UploadPackRequest) IsEmpty() bool {
return isSubset(r.Wants, r.Haves) && len(r.Shallows) == 0
}
func isSubset(needle []plumbing.Hash, haystack []plumbing.Hash) bool {
for _, h := range needle {
found := false
for _, oh := range haystack {
if h == oh {
found = true
break
}
}
if !found {
return false
}
}
return true
}
// UploadHaves is a message to signal the references that a client has in a
// upload-pack. Do not use this directly. Use UploadPackRequest request instead.
type UploadHaves struct {
Haves []plumbing.Hash
}
// Encode encodes the UploadHaves into the Writer. If flush is true, a flush
// command will be encoded at the end of the writer content.
func (u *UploadHaves) Encode(w io.Writer, flush bool) error {
e := pktline.NewEncoder(w)
plumbing.HashesSort(u.Haves)
var last plumbing.Hash
for _, have := range u.Haves {
if bytes.Equal(last[:], have[:]) {
continue
}
if err := e.Encodef("have %s\n", have); err != nil {
return fmt.Errorf("sending haves for %q: %s", have, err)
}
last = have
}
if flush && len(u.Haves) != 0 {
if err := e.Flush(); err != nil {
return fmt.Errorf("sending flush-pkt after haves: %s", err)
}
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/protocol/packp/uppackresp.go
================================================
package packp
import (
"errors"
"io"
"bufio"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// ErrUploadPackResponseNotDecoded is returned if Read is called without
// decoding first
var ErrUploadPackResponseNotDecoded = errors.New("upload-pack-response should be decoded")
// UploadPackResponse contains all the information responded by the upload-pack
// service, the response implements io.ReadCloser that allows to read the
// packfile directly from it.
type UploadPackResponse struct {
ShallowUpdate
ServerResponse
r io.ReadCloser
isShallow bool
isMultiACK bool
}
// NewUploadPackResponse create a new UploadPackResponse instance, the request
// being responded by the response is required.
func NewUploadPackResponse(req *UploadPackRequest) *UploadPackResponse {
isShallow := !req.Depth.IsZero()
isMultiACK := req.Capabilities.Supports(capability.MultiACK) ||
req.Capabilities.Supports(capability.MultiACKDetailed)
return &UploadPackResponse{
isShallow: isShallow,
isMultiACK: isMultiACK,
}
}
// NewUploadPackResponseWithPackfile creates a new UploadPackResponse instance,
// and sets its packfile reader.
func NewUploadPackResponseWithPackfile(req *UploadPackRequest,
pf io.ReadCloser) *UploadPackResponse {
r := NewUploadPackResponse(req)
r.r = pf
return r
}
// Decode decodes all the responses sent by upload-pack service into the struct
// and prepares it to read the packfile using the Read method
func (r *UploadPackResponse) Decode(reader io.ReadCloser) error {
buf := bufio.NewReader(reader)
if r.isShallow {
if err := r.ShallowUpdate.Decode(buf); err != nil {
return err
}
}
if err := r.ServerResponse.Decode(buf, r.isMultiACK); err != nil {
return err
}
// now the reader is ready to read the packfile content
r.r = ioutil.NewReadCloser(buf, reader)
return nil
}
// Encode encodes an UploadPackResponse.
func (r *UploadPackResponse) Encode(w io.Writer) (err error) {
if r.isShallow {
if err := r.ShallowUpdate.Encode(w); err != nil {
return err
}
}
if err := r.ServerResponse.Encode(w, r.isMultiACK); err != nil {
return err
}
defer ioutil.CheckClose(r.r, &err)
_, err = io.Copy(w, r.r)
return err
}
// Read reads the packfile data, if the request was done with any Sideband
// capability the content read should be demultiplexed. If the methods wasn't
// called before the ErrUploadPackResponseNotDecoded will be return
func (r *UploadPackResponse) Read(p []byte) (int, error) {
if r.r == nil {
return 0, ErrUploadPackResponseNotDecoded
}
return r.r.Read(p)
}
// Close the underlying reader, if any
func (r *UploadPackResponse) Close() error {
if r.r == nil {
return nil
}
return r.r.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/reference.go
================================================
package plumbing
import (
"errors"
"fmt"
"regexp"
"strings"
)
const (
refPrefix = "refs/"
refHeadPrefix = refPrefix + "heads/"
refTagPrefix = refPrefix + "tags/"
refRemotePrefix = refPrefix + "remotes/"
refNotePrefix = refPrefix + "notes/"
symrefPrefix = "ref: "
)
// RefRevParseRules are a set of rules to parse references into short names, or expand into a full reference.
// These are the same rules as used by git in shorten_unambiguous_ref and expand_ref.
// See: https://github.com/git/git/blob/e0aaa1b6532cfce93d87af9bc813fb2e7a7ce9d7/refs.c#L417
var RefRevParseRules = []string{
"%s",
"refs/%s",
"refs/tags/%s",
"refs/heads/%s",
"refs/remotes/%s",
"refs/remotes/%s/HEAD",
}
var (
ErrReferenceNotFound = errors.New("reference not found")
// ErrInvalidReferenceName is returned when a reference name is invalid.
ErrInvalidReferenceName = errors.New("invalid reference name")
)
// ReferenceType reference type's
type ReferenceType int8
const (
InvalidReference ReferenceType = 0
HashReference ReferenceType = 1
SymbolicReference ReferenceType = 2
)
func (r ReferenceType) String() string {
switch r {
case InvalidReference:
return "invalid-reference"
case HashReference:
return "hash-reference"
case SymbolicReference:
return "symbolic-reference"
}
return ""
}
// ReferenceName reference name's
type ReferenceName string
// NewBranchReferenceName returns a reference name describing a branch based on
// his short name.
func NewBranchReferenceName(name string) ReferenceName {
return ReferenceName(refHeadPrefix + name)
}
// NewNoteReferenceName returns a reference name describing a note based on his
// short name.
func NewNoteReferenceName(name string) ReferenceName {
return ReferenceName(refNotePrefix + name)
}
// NewRemoteReferenceName returns a reference name describing a remote branch
// based on his short name and the remote name.
func NewRemoteReferenceName(remote, name string) ReferenceName {
return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, name))
}
// NewRemoteHEADReferenceName returns a reference name describing a the HEAD
// branch of a remote.
func NewRemoteHEADReferenceName(remote string) ReferenceName {
return ReferenceName(refRemotePrefix + fmt.Sprintf("%s/%s", remote, HEAD))
}
// NewTagReferenceName returns a reference name describing a tag based on short
// his name.
func NewTagReferenceName(name string) ReferenceName {
return ReferenceName(refTagPrefix + name)
}
// IsBranch check if a reference is a branch
func (r ReferenceName) IsBranch() bool {
return strings.HasPrefix(string(r), refHeadPrefix)
}
// IsNote check if a reference is a note
func (r ReferenceName) IsNote() bool {
return strings.HasPrefix(string(r), refNotePrefix)
}
// IsRemote check if a reference is a remote
func (r ReferenceName) IsRemote() bool {
return strings.HasPrefix(string(r), refRemotePrefix)
}
// IsTag check if a reference is a tag
func (r ReferenceName) IsTag() bool {
return strings.HasPrefix(string(r), refTagPrefix)
}
func (r ReferenceName) String() string {
return string(r)
}
// Short returns the short name of a ReferenceName
func (r ReferenceName) Short() string {
s := string(r)
res := s
for _, format := range RefRevParseRules[1:] {
_, err := fmt.Sscanf(s, format, &res)
if err == nil {
continue
}
}
return res
}
var (
ctrlSeqs = regexp.MustCompile(`[\000-\037\177]`)
)
// Validate validates a reference name.
// This follows the git-check-ref-format rules.
// See https://git-scm.com/docs/git-check-ref-format
//
// It is important to note that this function does not check if the reference
// exists in the repository.
// It only checks if the reference name is valid.
// This functions does not support the --refspec-pattern, --normalize, and
// --allow-onelevel options.
//
// Git imposes the following rules on how references are named:
//
// 1. They can include slash / for hierarchical (directory) grouping, but no
// slash-separated component can begin with a dot . or end with the
// sequence .lock.
// 2. They must contain at least one /. This enforces the presence of a
// category like heads/, tags/ etc. but the actual names are not
// restricted. If the --allow-onelevel option is used, this rule is
// waived.
// 3. They cannot have two consecutive dots .. anywhere.
// 4. They cannot have ASCII control characters (i.e. bytes whose values are
// lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon :
// anywhere.
// 5. They cannot have question-mark ?, asterisk *, or open bracket [
// anywhere. See the --refspec-pattern option below for an exception to this
// rule.
// 6. They cannot begin or end with a slash / or contain multiple consecutive
// slashes (see the --normalize option below for an exception to this rule).
// 7. They cannot end with a dot ..
// 8. They cannot contain a sequence @{.
// 9. They cannot be the single character @.
// 10. They cannot contain a \.
func (r ReferenceName) Validate() error {
s := string(r)
if len(s) == 0 {
return ErrInvalidReferenceName
}
// HEAD is a special case
if r == HEAD {
return nil
}
// rule 7
if strings.HasSuffix(s, ".") {
return ErrInvalidReferenceName
}
// rule 2
parts := strings.Split(s, "/")
if len(parts) < 2 {
return ErrInvalidReferenceName
}
isBranch := r.IsBranch()
isTag := r.IsTag()
for i, part := range parts {
// rule 6
if len(part) == 0 {
return ErrInvalidReferenceName
}
if strings.HasPrefix(part, ".") || // rule 1
strings.Contains(part, "..") || // rule 3
ctrlSeqs.MatchString(part) || // rule 4
strings.ContainsAny(part, "~^:?*[ \t\n") || // rule 4 & 5
strings.Contains(part, "@{") || // rule 8
part == "@" || // rule 9
strings.Contains(part, "\\") || // rule 10
strings.HasSuffix(part, ".lock") { // rule 1
return ErrInvalidReferenceName
}
if (isBranch || isTag) && strings.HasPrefix(part, "-") && (i == 2) { // branches & tags can't start with -
return ErrInvalidReferenceName
}
}
return nil
}
const (
HEAD ReferenceName = "HEAD"
Master ReferenceName = "refs/heads/master"
Main ReferenceName = "refs/heads/main"
)
// Reference is a representation of git reference
type Reference struct {
t ReferenceType
n ReferenceName
h Hash
target ReferenceName
}
// NewReferenceFromStrings creates a reference from name and target as string,
// the resulting reference can be a SymbolicReference or a HashReference base
// on the target provided
func NewReferenceFromStrings(name, target string) *Reference {
n := ReferenceName(name)
if strings.HasPrefix(target, symrefPrefix) {
target := ReferenceName(target[len(symrefPrefix):])
return NewSymbolicReference(n, target)
}
return NewHashReference(n, NewHash(target))
}
// NewSymbolicReference creates a new SymbolicReference reference
func NewSymbolicReference(n, target ReferenceName) *Reference {
return &Reference{
t: SymbolicReference,
n: n,
target: target,
}
}
// NewHashReference creates a new HashReference reference
func NewHashReference(n ReferenceName, h Hash) *Reference {
return &Reference{
t: HashReference,
n: n,
h: h,
}
}
// Type returns the type of a reference
func (r *Reference) Type() ReferenceType {
return r.t
}
// Name returns the name of a reference
func (r *Reference) Name() ReferenceName {
return r.n
}
// Hash returns the hash of a hash reference
func (r *Reference) Hash() Hash {
return r.h
}
// Target returns the target of a symbolic reference
func (r *Reference) Target() ReferenceName {
return r.target
}
// Strings dump a reference as a [2]string
func (r *Reference) Strings() [2]string {
var o [2]string
o[0] = r.Name().String()
switch r.Type() {
case HashReference:
o[1] = r.Hash().String()
case SymbolicReference:
o[1] = symrefPrefix + r.Target().String()
}
return o
}
func (r *Reference) String() string {
ref := ""
switch r.Type() {
case HashReference:
ref = r.Hash().String()
case SymbolicReference:
ref = symrefPrefix + r.Target().String()
default:
return ""
}
name := r.Name().String()
var v strings.Builder
v.Grow(len(ref) + len(name) + 1)
v.WriteString(ref)
v.WriteString(" ")
v.WriteString(name)
return v.String()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/revision.go
================================================
package plumbing
// Revision represents a git revision
// to get more details about git revisions
// please check git manual page :
// https://www.kernel.org/pub/software/scm/git/docs/gitrevisions.html
type Revision string
func (r Revision) String() string {
return string(r)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/revlist/revlist.go
================================================
// Package revlist provides support to access the ancestors of commits, in a
// similar way as the git-rev-list command.
package revlist
import (
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
)
// Objects applies a complementary set. It gets all the hashes from all
// the reachable objects from the given objects. Ignore param are object hashes
// that we want to ignore on the result. All that objects must be accessible
// from the object storer.
func Objects(
s storer.EncodedObjectStorer,
objs,
ignore []plumbing.Hash,
) ([]plumbing.Hash, error) {
return ObjectsWithStorageForIgnores(s, s, objs, ignore)
}
// ObjectsWithStorageForIgnores is the same as Objects, but a
// secondary storage layer can be provided, to be used to finding the
// full set of objects to be ignored while finding the reachable
// objects. This is useful when the main `s` storage layer is slow
// and/or remote, while the ignore list is available somewhere local.
func ObjectsWithStorageForIgnores(
s, ignoreStore storer.EncodedObjectStorer,
objs,
ignore []plumbing.Hash,
) ([]plumbing.Hash, error) {
ignore, err := objects(ignoreStore, ignore, nil, true)
if err != nil {
return nil, err
}
return objects(s, objs, ignore, false)
}
func objects(
s storer.EncodedObjectStorer,
objects,
ignore []plumbing.Hash,
allowMissingObjects bool,
) ([]plumbing.Hash, error) {
seen := hashListToSet(ignore)
result := make(map[plumbing.Hash]bool)
visited := make(map[plumbing.Hash]bool)
walkerFunc := func(h plumbing.Hash) {
if !seen[h] {
result[h] = true
seen[h] = true
}
}
for _, h := range objects {
if err := processObject(s, h, seen, visited, ignore, walkerFunc); err != nil {
if allowMissingObjects && err == plumbing.ErrObjectNotFound {
continue
}
return nil, err
}
}
return hashSetToList(result), nil
}
// processObject obtains the object using the hash an process it depending of its type
func processObject(
s storer.EncodedObjectStorer,
h plumbing.Hash,
seen map[plumbing.Hash]bool,
visited map[plumbing.Hash]bool,
ignore []plumbing.Hash,
walkerFunc func(h plumbing.Hash),
) error {
if seen[h] {
return nil
}
o, err := s.EncodedObject(plumbing.AnyObject, h)
if err != nil {
return err
}
do, err := object.DecodeObject(s, o)
if err != nil {
return err
}
switch do := do.(type) {
case *object.Commit:
return reachableObjects(do, seen, visited, ignore, walkerFunc)
case *object.Tree:
return iterateCommitTrees(seen, do, walkerFunc)
case *object.Tag:
walkerFunc(do.Hash)
return processObject(s, do.Target, seen, visited, ignore, walkerFunc)
case *object.Blob:
walkerFunc(do.Hash)
default:
return fmt.Errorf("object type not valid: %s. "+
"Object reference: %s", o.Type(), o.Hash())
}
return nil
}
// reachableObjects returns, using the callback function, all the reachable
// objects from the specified commit. To avoid to iterate over seen commits,
// if a commit hash is into the 'seen' set, we will not iterate all his trees
// and blobs objects.
func reachableObjects(
commit *object.Commit,
seen map[plumbing.Hash]bool,
visited map[plumbing.Hash]bool,
ignore []plumbing.Hash,
cb func(h plumbing.Hash),
) error {
i := object.NewCommitPreorderIter(commit, seen, ignore)
pending := make(map[plumbing.Hash]bool)
addPendingParents(pending, visited, commit)
for {
commit, err := i.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if pending[commit.Hash] {
delete(pending, commit.Hash)
}
addPendingParents(pending, visited, commit)
if visited[commit.Hash] && len(pending) == 0 {
break
}
if seen[commit.Hash] {
continue
}
cb(commit.Hash)
tree, err := commit.Tree()
if err != nil {
return err
}
if err := iterateCommitTrees(seen, tree, cb); err != nil {
return err
}
}
return nil
}
func addPendingParents(pending, visited map[plumbing.Hash]bool, commit *object.Commit) {
for _, p := range commit.ParentHashes {
if !visited[p] {
pending[p] = true
}
}
}
// iterateCommitTrees iterate all reachable trees from the given commit
func iterateCommitTrees(
seen map[plumbing.Hash]bool,
tree *object.Tree,
cb func(h plumbing.Hash),
) error {
if seen[tree.Hash] {
return nil
}
cb(tree.Hash)
treeWalker := object.NewTreeWalker(tree, true, seen)
for {
_, e, err := treeWalker.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if e.Mode == filemode.Submodule {
continue
}
if seen[e.Hash] {
continue
}
cb(e.Hash)
}
return nil
}
func hashSetToList(hashes map[plumbing.Hash]bool) []plumbing.Hash {
var result []plumbing.Hash
for key := range hashes {
result = append(result, key)
}
return result
}
func hashListToSet(hashes []plumbing.Hash) map[plumbing.Hash]bool {
result := make(map[plumbing.Hash]bool)
for _, h := range hashes {
result[h] = true
}
return result
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/doc.go
================================================
// Package storer defines the interfaces to store objects, references, etc.
package storer
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/index.go
================================================
package storer
import "github.com/go-git/go-git/v5/plumbing/format/index"
// IndexStorer generic storage of index.Index
type IndexStorer interface {
SetIndex(*index.Index) error
Index() (*index.Index, error)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/object.go
================================================
package storer
import (
"errors"
"io"
"time"
"github.com/go-git/go-git/v5/plumbing"
)
var (
//ErrStop is used to stop a ForEach function in an Iter
ErrStop = errors.New("stop iter")
)
// EncodedObjectStorer generic storage of objects
type EncodedObjectStorer interface {
// NewEncodedObject returns a new plumbing.EncodedObject, the real type
// of the object can be a custom implementation or the default one,
// plumbing.MemoryObject.
NewEncodedObject() plumbing.EncodedObject
// SetEncodedObject saves an object into the storage, the object should
// be create with the NewEncodedObject, method, and file if the type is
// not supported.
SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error)
// EncodedObject gets an object by hash with the given
// plumbing.ObjectType. Implementors should return
// (nil, plumbing.ErrObjectNotFound) if an object doesn't exist with
// both the given hash and object type.
//
// Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject,
// TreeObject and AnyObject. If plumbing.AnyObject is given, the object must
// be looked up regardless of its type.
EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
// IterObjects returns a custom EncodedObjectStorer over all the object
// on the storage.
//
// Valid plumbing.ObjectType values are CommitObject, BlobObject, TagObject,
IterEncodedObjects(plumbing.ObjectType) (EncodedObjectIter, error)
// HasEncodedObject returns ErrObjNotFound if the object doesn't
// exist. If the object does exist, it returns nil.
HasEncodedObject(plumbing.Hash) error
// EncodedObjectSize returns the plaintext size of the encoded object.
EncodedObjectSize(plumbing.Hash) (int64, error)
AddAlternate(remote string) error
}
// DeltaObjectStorer is an EncodedObjectStorer that can return delta
// objects.
type DeltaObjectStorer interface {
// DeltaObject is the same as EncodedObject but without resolving deltas.
// Deltas will be returned as plumbing.DeltaObject instances.
DeltaObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
}
// Transactioner is a optional method for ObjectStorer, it enables transactional read and write
// operations.
type Transactioner interface {
// Begin starts a transaction.
Begin() Transaction
}
// LooseObjectStorer is an optional interface for managing "loose"
// objects, i.e. those not in packfiles.
type LooseObjectStorer interface {
// ForEachObjectHash iterates over all the (loose) object hashes
// in the repository without necessarily having to read those objects.
// Objects only inside pack files may be omitted.
// If ErrStop is sent the iteration is stop but no error is returned.
ForEachObjectHash(func(plumbing.Hash) error) error
// LooseObjectTime looks up the (m)time associated with the
// loose object (that is not in a pack file). Some
// implementations (e.g. without loose objects)
// always return an error.
LooseObjectTime(plumbing.Hash) (time.Time, error)
// DeleteLooseObject deletes a loose object if it exists.
DeleteLooseObject(plumbing.Hash) error
}
// PackedObjectStorer is an optional interface for managing objects in
// packfiles.
type PackedObjectStorer interface {
// ObjectPacks returns hashes of object packs if the underlying
// implementation has pack files.
ObjectPacks() ([]plumbing.Hash, error)
// DeleteOldObjectPackAndIndex deletes an object pack and the corresponding index file if they exist.
// Deletion is only performed if the pack is older than the supplied time (or the time is zero).
DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error
}
// PackfileWriter is an optional method for ObjectStorer, it enables directly writing
// a packfile to storage.
type PackfileWriter interface {
// PackfileWriter returns a writer for writing a packfile to the storage
//
// If the Storer not implements PackfileWriter the objects should be written
// using the Set method.
PackfileWriter() (io.WriteCloser, error)
}
// EncodedObjectIter is a generic closable interface for iterating over objects.
type EncodedObjectIter interface {
Next() (plumbing.EncodedObject, error)
ForEach(func(plumbing.EncodedObject) error) error
Close()
}
// Transaction is an in-progress storage transaction. A transaction must end
// with a call to Commit or Rollback.
type Transaction interface {
SetEncodedObject(plumbing.EncodedObject) (plumbing.Hash, error)
EncodedObject(plumbing.ObjectType, plumbing.Hash) (plumbing.EncodedObject, error)
Commit() error
Rollback() error
}
// EncodedObjectLookupIter implements EncodedObjectIter. It iterates over a
// series of object hashes and yields their associated objects by retrieving
// each one from object storage. The retrievals are lazy and only occur when the
// iterator moves forward with a call to Next().
//
// The EncodedObjectLookupIter must be closed with a call to Close() when it is
// no longer needed.
type EncodedObjectLookupIter struct {
storage EncodedObjectStorer
series []plumbing.Hash
t plumbing.ObjectType
pos int
}
// NewEncodedObjectLookupIter returns an object iterator given an object storage
// and a slice of object hashes.
func NewEncodedObjectLookupIter(
storage EncodedObjectStorer, t plumbing.ObjectType, series []plumbing.Hash) *EncodedObjectLookupIter {
return &EncodedObjectLookupIter{
storage: storage,
series: series,
t: t,
}
}
// Next returns the next object from the iterator. If the iterator has reached
// the end it will return io.EOF as an error. If the object can't be found in
// the object storage, it will return plumbing.ErrObjectNotFound as an error.
// If the object is retrieved successfully error will be nil.
func (iter *EncodedObjectLookupIter) Next() (plumbing.EncodedObject, error) {
if iter.pos >= len(iter.series) {
return nil, io.EOF
}
hash := iter.series[iter.pos]
obj, err := iter.storage.EncodedObject(iter.t, hash)
if err == nil {
iter.pos++
}
return obj, err
}
// ForEach call the cb function for each object contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *EncodedObjectLookupIter) ForEach(cb func(plumbing.EncodedObject) error) error {
return ForEachIterator(iter, cb)
}
// Close releases any resources used by the iterator.
func (iter *EncodedObjectLookupIter) Close() {
iter.pos = len(iter.series)
}
// EncodedObjectSliceIter implements EncodedObjectIter. It iterates over a
// series of objects stored in a slice and yields each one in turn when Next()
// is called.
//
// The EncodedObjectSliceIter must be closed with a call to Close() when it is
// no longer needed.
type EncodedObjectSliceIter struct {
series []plumbing.EncodedObject
}
// NewEncodedObjectSliceIter returns an object iterator for the given slice of
// objects.
func NewEncodedObjectSliceIter(series []plumbing.EncodedObject) *EncodedObjectSliceIter {
return &EncodedObjectSliceIter{
series: series,
}
}
// Next returns the next object from the iterator. If the iterator has reached
// the end it will return io.EOF as an error. If the object is retrieved
// successfully error will be nil.
func (iter *EncodedObjectSliceIter) Next() (plumbing.EncodedObject, error) {
if len(iter.series) == 0 {
return nil, io.EOF
}
obj := iter.series[0]
iter.series = iter.series[1:]
return obj, nil
}
// ForEach call the cb function for each object contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *EncodedObjectSliceIter) ForEach(cb func(plumbing.EncodedObject) error) error {
return ForEachIterator(iter, cb)
}
// Close releases any resources used by the iterator.
func (iter *EncodedObjectSliceIter) Close() {
iter.series = []plumbing.EncodedObject{}
}
// MultiEncodedObjectIter implements EncodedObjectIter. It iterates over several
// EncodedObjectIter,
//
// The MultiObjectIter must be closed with a call to Close() when it is no
// longer needed.
type MultiEncodedObjectIter struct {
iters []EncodedObjectIter
}
// NewMultiEncodedObjectIter returns an object iterator for the given slice of
// EncodedObjectIters.
func NewMultiEncodedObjectIter(iters []EncodedObjectIter) EncodedObjectIter {
return &MultiEncodedObjectIter{iters: iters}
}
// Next returns the next object from the iterator, if one iterator reach io.EOF
// is removed and the next one is used.
func (iter *MultiEncodedObjectIter) Next() (plumbing.EncodedObject, error) {
if len(iter.iters) == 0 {
return nil, io.EOF
}
obj, err := iter.iters[0].Next()
if err == io.EOF {
iter.iters[0].Close()
iter.iters = iter.iters[1:]
return iter.Next()
}
return obj, err
}
// ForEach call the cb function for each object contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *MultiEncodedObjectIter) ForEach(cb func(plumbing.EncodedObject) error) error {
return ForEachIterator(iter, cb)
}
// Close releases any resources used by the iterator.
func (iter *MultiEncodedObjectIter) Close() {
for _, i := range iter.iters {
i.Close()
}
}
type bareIterator interface {
Next() (plumbing.EncodedObject, error)
Close()
}
// ForEachIterator is a helper function to build iterators without need to
// rewrite the same ForEach function each time.
func ForEachIterator(iter bareIterator, cb func(plumbing.EncodedObject) error) error {
defer iter.Close()
for {
obj, err := iter.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if err := cb(obj); err != nil {
if err == ErrStop {
return nil
}
return err
}
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/reference.go
================================================
package storer
import (
"errors"
"io"
"github.com/go-git/go-git/v5/plumbing"
)
const MaxResolveRecursion = 1024
// ErrMaxResolveRecursion is returned by ResolveReference is MaxResolveRecursion
// is exceeded
var ErrMaxResolveRecursion = errors.New("max. recursion level reached")
// ReferenceStorer is a generic storage of references.
type ReferenceStorer interface {
SetReference(*plumbing.Reference) error
// CheckAndSetReference sets the reference `new`, but if `old` is
// not `nil`, it first checks that the current stored value for
// `old.Name()` matches the given reference value in `old`. If
// not, it returns an error and doesn't update `new`.
CheckAndSetReference(new, old *plumbing.Reference) error
Reference(plumbing.ReferenceName) (*plumbing.Reference, error)
IterReferences() (ReferenceIter, error)
RemoveReference(plumbing.ReferenceName) error
CountLooseRefs() (int, error)
PackRefs() error
}
// ReferenceIter is a generic closable interface for iterating over references.
type ReferenceIter interface {
Next() (*plumbing.Reference, error)
ForEach(func(*plumbing.Reference) error) error
Close()
}
type referenceFilteredIter struct {
ff func(r *plumbing.Reference) bool
iter ReferenceIter
}
// NewReferenceFilteredIter returns a reference iterator for the given reference
// Iterator. This iterator will iterate only references that accomplish the
// provided function.
func NewReferenceFilteredIter(
ff func(r *plumbing.Reference) bool, iter ReferenceIter) ReferenceIter {
return &referenceFilteredIter{ff, iter}
}
// Next returns the next reference from the iterator. If the iterator has reached
// the end it will return io.EOF as an error.
func (iter *referenceFilteredIter) Next() (*plumbing.Reference, error) {
for {
r, err := iter.iter.Next()
if err != nil {
return nil, err
}
if iter.ff(r) {
return r, nil
}
continue
}
}
// ForEach call the cb function for each reference contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stopped but no error is returned. The iterator is closed.
func (iter *referenceFilteredIter) ForEach(cb func(*plumbing.Reference) error) error {
defer iter.Close()
for {
r, err := iter.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if err := cb(r); err != nil {
if err == ErrStop {
break
}
return err
}
}
return nil
}
// Close releases any resources used by the iterator.
func (iter *referenceFilteredIter) Close() {
iter.iter.Close()
}
// ReferenceSliceIter implements ReferenceIter. It iterates over a series of
// references stored in a slice and yields each one in turn when Next() is
// called.
//
// The ReferenceSliceIter must be closed with a call to Close() when it is no
// longer needed.
type ReferenceSliceIter struct {
series []*plumbing.Reference
pos int
}
// NewReferenceSliceIter returns a reference iterator for the given slice of
// objects.
func NewReferenceSliceIter(series []*plumbing.Reference) ReferenceIter {
return &ReferenceSliceIter{
series: series,
}
}
// Next returns the next reference from the iterator. If the iterator has
// reached the end it will return io.EOF as an error.
func (iter *ReferenceSliceIter) Next() (*plumbing.Reference, error) {
if iter.pos >= len(iter.series) {
return nil, io.EOF
}
obj := iter.series[iter.pos]
iter.pos++
return obj, nil
}
// ForEach call the cb function for each reference contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *ReferenceSliceIter) ForEach(cb func(*plumbing.Reference) error) error {
return forEachReferenceIter(iter, cb)
}
type bareReferenceIterator interface {
Next() (*plumbing.Reference, error)
Close()
}
func forEachReferenceIter(iter bareReferenceIterator, cb func(*plumbing.Reference) error) error {
defer iter.Close()
for {
obj, err := iter.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if err := cb(obj); err != nil {
if err == ErrStop {
return nil
}
return err
}
}
}
// Close releases any resources used by the iterator.
func (iter *ReferenceSliceIter) Close() {
iter.pos = len(iter.series)
}
// MultiReferenceIter implements ReferenceIter. It iterates over several
// ReferenceIter,
//
// The MultiReferenceIter must be closed with a call to Close() when it is no
// longer needed.
type MultiReferenceIter struct {
iters []ReferenceIter
}
// NewMultiReferenceIter returns an reference iterator for the given slice of
// EncodedObjectIters.
func NewMultiReferenceIter(iters []ReferenceIter) ReferenceIter {
return &MultiReferenceIter{iters: iters}
}
// Next returns the next reference from the iterator, if one iterator reach
// io.EOF is removed and the next one is used.
func (iter *MultiReferenceIter) Next() (*plumbing.Reference, error) {
if len(iter.iters) == 0 {
return nil, io.EOF
}
obj, err := iter.iters[0].Next()
if err == io.EOF {
iter.iters[0].Close()
iter.iters = iter.iters[1:]
return iter.Next()
}
return obj, err
}
// ForEach call the cb function for each reference contained on this iter until
// an error happens or the end of the iter is reached. If ErrStop is sent
// the iteration is stop but no error is returned. The iterator is closed.
func (iter *MultiReferenceIter) ForEach(cb func(*plumbing.Reference) error) error {
return forEachReferenceIter(iter, cb)
}
// Close releases any resources used by the iterator.
func (iter *MultiReferenceIter) Close() {
for _, i := range iter.iters {
i.Close()
}
}
// ResolveReference resolves a SymbolicReference to a HashReference.
func ResolveReference(s ReferenceStorer, n plumbing.ReferenceName) (*plumbing.Reference, error) {
r, err := s.Reference(n)
if err != nil || r == nil {
return r, err
}
return resolveReference(s, r, 0)
}
func resolveReference(s ReferenceStorer, r *plumbing.Reference, recursion int) (*plumbing.Reference, error) {
if r.Type() != plumbing.SymbolicReference {
return r, nil
}
if recursion > MaxResolveRecursion {
return nil, ErrMaxResolveRecursion
}
t, err := s.Reference(r.Target())
if err != nil {
return nil, err
}
recursion++
return resolveReference(s, t, recursion)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/shallow.go
================================================
package storer
import "github.com/go-git/go-git/v5/plumbing"
// ShallowStorer is a storage of references to shallow commits by hash,
// meaning that these commits have missing parents because of a shallow fetch.
type ShallowStorer interface {
SetShallow([]plumbing.Hash) error
Shallow() ([]plumbing.Hash, error)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/storer/storer.go
================================================
package storer
// Storer is a basic storer for encoded objects and references.
type Storer interface {
EncodedObjectStorer
ReferenceStorer
}
// Initializer should be implemented by storers that require to perform any
// operation when creating a new repository (i.e. git init).
type Initializer interface {
// Init performs initialization of the storer and returns the error, if
// any.
Init() error
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/client/client.go
================================================
// Package client contains helper function to deal with the different client
// protocols.
package client
import (
"fmt"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/file"
"github.com/go-git/go-git/v5/plumbing/transport/git"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/go-git/go-git/v5/plumbing/transport/ssh"
)
// Protocols are the protocols supported by default.
var Protocols = map[string]transport.Transport{
"http": http.DefaultClient,
"https": http.DefaultClient,
"ssh": ssh.DefaultClient,
"git": git.DefaultClient,
"file": file.DefaultClient,
}
// InstallProtocol adds or modifies an existing protocol.
func InstallProtocol(scheme string, c transport.Transport) {
if c == nil {
delete(Protocols, scheme)
return
}
Protocols[scheme] = c
}
// NewClient returns the appropriate client among of the set of known protocols:
// http://, https://, ssh:// and file://.
// See `InstallProtocol` to add or modify protocols.
func NewClient(endpoint *transport.Endpoint) (transport.Transport, error) {
return getTransport(endpoint)
}
func getTransport(endpoint *transport.Endpoint) (transport.Transport, error) {
f, ok := Protocols[endpoint.Protocol]
if !ok {
return nil, fmt.Errorf("unsupported scheme %q", endpoint.Protocol)
}
if f == nil {
return nil, fmt.Errorf("malformed client for scheme %q, client is defined as nil", endpoint.Protocol)
}
return f, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/common.go
================================================
// Package transport includes the implementation for different transport
// protocols.
//
// `Client` can be used to fetch and send packfiles to a git server.
// The `client` package provides higher level functions to instantiate the
// appropriate `Client` based on the repository URL.
//
// go-git supports HTTP and SSH (see `Protocols`), but you can also install
// your own protocols (see the `client` package).
//
// Each protocol has its own implementation of `Client`, but you should
// generally not use them directly, use `client.NewClient` instead.
package transport
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"net/url"
"path/filepath"
"strconv"
"strings"
giturl "github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
)
var (
ErrRepositoryNotFound = errors.New("repository not found")
ErrEmptyRemoteRepository = errors.New("remote repository is empty")
ErrAuthenticationRequired = errors.New("authentication required")
ErrAuthorizationFailed = errors.New("authorization failed")
ErrEmptyUploadPackRequest = errors.New("empty git-upload-pack given")
ErrInvalidAuthMethod = errors.New("invalid auth method")
ErrAlreadyConnected = errors.New("session already established")
)
const (
UploadPackServiceName = "git-upload-pack"
ReceivePackServiceName = "git-receive-pack"
)
// Transport can initiate git-upload-pack and git-receive-pack processes.
// It is implemented both by the client and the server, making this a RPC.
type Transport interface {
// NewUploadPackSession starts a git-upload-pack session for an endpoint.
NewUploadPackSession(*Endpoint, AuthMethod) (UploadPackSession, error)
// NewReceivePackSession starts a git-receive-pack session for an endpoint.
NewReceivePackSession(*Endpoint, AuthMethod) (ReceivePackSession, error)
}
type Session interface {
// AdvertisedReferences retrieves the advertised references for a
// repository.
// If the repository does not exist, returns ErrRepositoryNotFound.
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository.
AdvertisedReferences() (*packp.AdvRefs, error)
// AdvertisedReferencesContext retrieves the advertised references for a
// repository.
// If the repository does not exist, returns ErrRepositoryNotFound.
// If the repository exists, but is empty, returns ErrEmptyRemoteRepository.
AdvertisedReferencesContext(context.Context) (*packp.AdvRefs, error)
io.Closer
}
type AuthMethod interface {
fmt.Stringer
Name() string
}
// UploadPackSession represents a git-upload-pack session.
// A git-upload-pack session has two steps: reference discovery
// (AdvertisedReferences) and uploading pack (UploadPack).
type UploadPackSession interface {
Session
// UploadPack takes a git-upload-pack request and returns a response,
// including a packfile. Don't be confused by terminology, the client
// side of a git-upload-pack is called git-fetch-pack, although here
// the same interface is used to make it RPC-like.
UploadPack(context.Context, *packp.UploadPackRequest) (*packp.UploadPackResponse, error)
}
// ReceivePackSession represents a git-receive-pack session.
// A git-receive-pack session has two steps: reference discovery
// (AdvertisedReferences) and receiving pack (ReceivePack).
// In that order.
type ReceivePackSession interface {
Session
// ReceivePack sends an update references request and a packfile
// reader and returns a ReportStatus and error. Don't be confused by
// terminology, the client side of a git-receive-pack is called
// git-send-pack, although here the same interface is used to make it
// RPC-like.
ReceivePack(context.Context, *packp.ReferenceUpdateRequest) (*packp.ReportStatus, error)
}
// Endpoint represents a Git URL in any supported protocol.
type Endpoint struct {
// Protocol is the protocol of the endpoint (e.g. git, https, file).
Protocol string
// User is the user.
User string
// Password is the password.
Password string
// Host is the host.
Host string
// Port is the port to connect, if 0 the default port for the given protocol
// will be used.
Port int
// Path is the repository path.
Path string
// InsecureSkipTLS skips ssl verify if protocol is https
InsecureSkipTLS bool
// CaBundle specify additional ca bundle with system cert pool
CaBundle []byte
// Proxy provides info required for connecting to a proxy.
Proxy ProxyOptions
}
type ProxyOptions struct {
URL string
Username string
Password string
}
func (o *ProxyOptions) Validate() error {
if o.URL != "" {
_, err := url.Parse(o.URL)
return err
}
return nil
}
func (o *ProxyOptions) FullURL() (*url.URL, error) {
proxyURL, err := url.Parse(o.URL)
if err != nil {
return nil, err
}
if o.Username != "" {
if o.Password != "" {
proxyURL.User = url.UserPassword(o.Username, o.Password)
} else {
proxyURL.User = url.User(o.Username)
}
}
return proxyURL, nil
}
var defaultPorts = map[string]int{
"http": 80,
"https": 443,
"git": 9418,
"ssh": 22,
}
// String returns a string representation of the Git URL.
func (u *Endpoint) String() string {
var buf bytes.Buffer
if u.Protocol != "" {
buf.WriteString(u.Protocol)
buf.WriteByte(':')
}
if u.Protocol != "" || u.Host != "" || u.User != "" || u.Password != "" {
buf.WriteString("//")
if u.User != "" || u.Password != "" {
buf.WriteString(url.PathEscape(u.User))
if u.Password != "" {
buf.WriteByte(':')
buf.WriteString(url.PathEscape(u.Password))
}
buf.WriteByte('@')
}
if u.Host != "" {
buf.WriteString(u.Host)
if u.Port != 0 {
port, ok := defaultPorts[strings.ToLower(u.Protocol)]
if !ok || ok && port != u.Port {
fmt.Fprintf(&buf, ":%d", u.Port)
}
}
}
}
if u.Path != "" && u.Path[0] != '/' && u.Host != "" {
buf.WriteByte('/')
}
buf.WriteString(u.Path)
return buf.String()
}
func NewEndpoint(endpoint string) (*Endpoint, error) {
if e, ok := parseSCPLike(endpoint); ok {
return e, nil
}
if e, ok := parseFile(endpoint); ok {
return e, nil
}
return parseURL(endpoint)
}
func parseURL(endpoint string) (*Endpoint, error) {
u, err := url.Parse(endpoint)
if err != nil {
return nil, err
}
if !u.IsAbs() {
return nil, plumbing.NewPermanentError(fmt.Errorf(
"invalid endpoint: %s", endpoint,
))
}
var user, pass string
if u.User != nil {
user = u.User.Username()
pass, _ = u.User.Password()
}
host := u.Hostname()
if strings.Contains(host, ":") {
// IPv6 address
host = "[" + host + "]"
}
return &Endpoint{
Protocol: u.Scheme,
User: user,
Password: pass,
Host: host,
Port: getPort(u),
Path: getPath(u),
}, nil
}
func getPort(u *url.URL) int {
p := u.Port()
if p == "" {
return 0
}
i, err := strconv.Atoi(p)
if err != nil {
return 0
}
return i
}
func getPath(u *url.URL) string {
var res string = u.Path
if u.RawQuery != "" {
res += "?" + u.RawQuery
}
if u.Fragment != "" {
res += "#" + u.Fragment
}
return res
}
func parseSCPLike(endpoint string) (*Endpoint, bool) {
if giturl.MatchesScheme(endpoint) || !giturl.MatchesScpLike(endpoint) {
return nil, false
}
user, host, portStr, path := giturl.FindScpLikeComponents(endpoint)
port, err := strconv.Atoi(portStr)
if err != nil {
port = 22
}
return &Endpoint{
Protocol: "ssh",
User: user,
Host: host,
Port: port,
Path: path,
}, true
}
func parseFile(endpoint string) (*Endpoint, bool) {
if giturl.MatchesScheme(endpoint) {
return nil, false
}
path, err := filepath.Abs(endpoint)
if err != nil {
return nil, false
}
return &Endpoint{
Protocol: "file",
Path: path,
}, true
}
// UnsupportedCapabilities are the capabilities not supported by any client
// implementation
var UnsupportedCapabilities = []capability.Capability{
capability.MultiACK,
capability.MultiACKDetailed,
capability.ThinPack,
}
// FilterUnsupportedCapabilities it filter out all the UnsupportedCapabilities
// from a capability.List, the intended usage is on the client implementation
// to filter the capabilities from an AdvRefs message.
func FilterUnsupportedCapabilities(list *capability.List) {
for _, c := range UnsupportedCapabilities {
list.Delete(c)
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/file/client.go
================================================
// Package file implements the file transport protocol.
package file
import (
"bufio"
"errors"
"io"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"golang.org/x/sys/execabs"
)
// DefaultClient is the default local client.
var DefaultClient = NewClient(
transport.UploadPackServiceName,
transport.ReceivePackServiceName,
)
type runner struct {
UploadPackBin string
ReceivePackBin string
}
// NewClient returns a new local client using the given git-upload-pack and
// git-receive-pack binaries.
func NewClient(uploadPackBin, receivePackBin string) transport.Transport {
return common.NewClient(&runner{
UploadPackBin: uploadPackBin,
ReceivePackBin: receivePackBin,
})
}
func prefixExecPath(cmd string) (string, error) {
// Use `git --exec-path` to find the exec path.
execCmd := execabs.Command("git", "--exec-path")
stdout, err := execCmd.StdoutPipe()
if err != nil {
return "", err
}
stdoutBuf := bufio.NewReader(stdout)
err = execCmd.Start()
if err != nil {
return "", err
}
execPathBytes, isPrefix, err := stdoutBuf.ReadLine()
if err != nil {
return "", err
}
if isPrefix {
return "", errors.New("couldn't read exec-path line all at once")
}
err = execCmd.Wait()
if err != nil {
return "", err
}
execPath := string(execPathBytes)
execPath = strings.TrimSpace(execPath)
cmd = filepath.Join(execPath, cmd)
// Make sure it actually exists.
_, err = execabs.LookPath(cmd)
if err != nil {
return "", err
}
return cmd, nil
}
func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod,
) (common.Command, error) {
switch cmd {
case transport.UploadPackServiceName:
cmd = r.UploadPackBin
case transport.ReceivePackServiceName:
cmd = r.ReceivePackBin
}
_, err := execabs.LookPath(cmd)
if err != nil {
if e, ok := err.(*execabs.Error); ok && e.Err == execabs.ErrNotFound {
cmd, err = prefixExecPath(cmd)
if err != nil {
return nil, err
}
} else {
return nil, err
}
}
return &command{cmd: execabs.Command(cmd, adjustPathForWindows(ep.Path))}, nil
}
func isDriveLetter(c byte) bool {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
// On Windows, the path that results from a file: URL has a leading slash. This
// has to be removed if there's a drive letter
func adjustPathForWindows(p string) string {
if runtime.GOOS != "windows" {
return p
}
if len(p) >= 3 && p[0] == '/' && isDriveLetter(p[1]) && p[2] == ':' {
return p[1:]
}
return p
}
type command struct {
cmd *execabs.Cmd
stderrCloser io.Closer
closed bool
}
func (c *command) Start() error {
return c.cmd.Start()
}
func (c *command) StderrPipe() (io.Reader, error) {
// Pipe returned by Command.StderrPipe has a race with Read + Command.Wait.
// We use an io.Pipe and close it after the command finishes.
r, w := io.Pipe()
c.cmd.Stderr = w
c.stderrCloser = r
return r, nil
}
func (c *command) StdinPipe() (io.WriteCloser, error) {
return c.cmd.StdinPipe()
}
func (c *command) StdoutPipe() (io.Reader, error) {
return c.cmd.StdoutPipe()
}
func (c *command) Kill() error {
c.cmd.Process.Kill()
return c.Close()
}
// Close waits for the command to exit.
func (c *command) Close() error {
if c.closed {
return nil
}
defer func() {
c.closed = true
_ = c.stderrCloser.Close()
}()
err := c.cmd.Wait()
if _, ok := err.(*os.PathError); ok {
return nil
}
// When a repository does not exist, the command exits with code 128.
if _, ok := err.(*execabs.ExitError); ok {
return nil
}
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/file/server.go
================================================
package file
import (
"fmt"
"os"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"github.com/go-git/go-git/v5/plumbing/transport/server"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// ServeUploadPack serves a git-upload-pack request using standard output, input
// and error. This is meant to be used when implementing a git-upload-pack
// command.
func ServeUploadPack(path string) error {
ep, err := transport.NewEndpoint(path)
if err != nil {
return err
}
// TODO: define and implement a server-side AuthMethod
s, err := server.DefaultServer.NewUploadPackSession(ep, nil)
if err != nil {
return fmt.Errorf("error creating session: %s", err)
}
return common.ServeUploadPack(srvCmd, s)
}
// ServeReceivePack serves a git-receive-pack request using standard output,
// input and error. This is meant to be used when implementing a
// git-receive-pack command.
func ServeReceivePack(path string) error {
ep, err := transport.NewEndpoint(path)
if err != nil {
return err
}
// TODO: define and implement a server-side AuthMethod
s, err := server.DefaultServer.NewReceivePackSession(ep, nil)
if err != nil {
return fmt.Errorf("error creating session: %s", err)
}
return common.ServeReceivePack(srvCmd, s)
}
var srvCmd = common.ServerCommand{
Stdin: os.Stdin,
Stdout: ioutil.WriteNopCloser(os.Stdout),
Stderr: os.Stderr,
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/git/common.go
================================================
// Package git implements the git transport protocol.
package git
import (
"io"
"net"
"strconv"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// DefaultClient is the default git client.
var DefaultClient = common.NewClient(&runner{})
const DefaultPort = 9418
type runner struct{}
// Command returns a new Command for the given cmd in the given Endpoint
func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (common.Command, error) {
// auth not allowed since git protocol doesn't support authentication
if auth != nil {
return nil, transport.ErrInvalidAuthMethod
}
c := &command{command: cmd, endpoint: ep}
if err := c.connect(); err != nil {
return nil, err
}
return c, nil
}
type command struct {
conn net.Conn
connected bool
command string
endpoint *transport.Endpoint
}
// Start executes the command sending the required message to the TCP connection
func (c *command) Start() error {
req := packp.GitProtoRequest{
RequestCommand: c.command,
Pathname: c.endpoint.Path,
}
host := c.endpoint.Host
if c.endpoint.Port != DefaultPort {
host = net.JoinHostPort(c.endpoint.Host, strconv.Itoa(c.endpoint.Port))
}
req.Host = host
return req.Encode(c.conn)
}
func (c *command) connect() error {
if c.connected {
return transport.ErrAlreadyConnected
}
var err error
c.conn, err = net.Dial("tcp", c.getHostWithPort())
if err != nil {
return err
}
c.connected = true
return nil
}
func (c *command) getHostWithPort() string {
host := c.endpoint.Host
port := c.endpoint.Port
if port <= 0 {
port = DefaultPort
}
return net.JoinHostPort(host, strconv.Itoa(port))
}
// StderrPipe git protocol doesn't have any dedicated error channel
func (c *command) StderrPipe() (io.Reader, error) {
return nil, nil
}
// StdinPipe returns the underlying connection as WriteCloser, wrapped to prevent
// call to the Close function from the connection, a command execution in git
// protocol can't be closed or killed
func (c *command) StdinPipe() (io.WriteCloser, error) {
return ioutil.WriteNopCloser(c.conn), nil
}
// StdoutPipe returns the underlying connection as Reader
func (c *command) StdoutPipe() (io.Reader, error) {
return c.conn, nil
}
// Close closes the TCP connection and connection.
func (c *command) Close() error {
if !c.connected {
return nil
}
c.connected = false
return c.conn.Close()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/http/common.go
================================================
// Package http implements the HTTP transport protocol.
package http
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"fmt"
"net"
"net/http"
"net/url"
"reflect"
"strconv"
"strings"
"sync"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/golang/groupcache/lru"
)
// it requires a bytes.Buffer, because we need to know the length
func applyHeadersToRequest(req *http.Request, content *bytes.Buffer, host string, requestType string) {
req.Header.Add("User-Agent", capability.DefaultAgent())
req.Header.Add("Host", host) // host:port
if content == nil {
req.Header.Add("Accept", "*/*")
return
}
req.Header.Add("Accept", fmt.Sprintf("application/x-%s-result", requestType))
req.Header.Add("Content-Type", fmt.Sprintf("application/x-%s-request", requestType))
req.Header.Add("Content-Length", strconv.Itoa(content.Len()))
}
const infoRefsPath = "/info/refs"
func advertisedReferences(ctx context.Context, s *session, serviceName string) (ref *packp.AdvRefs, err error) {
url := fmt.Sprintf(
"%s%s?service=%s",
s.endpoint.String(), infoRefsPath, serviceName,
)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
s.ApplyAuthToRequest(req)
applyHeadersToRequest(req, nil, s.endpoint.Host, serviceName)
res, err := s.client.Do(req.WithContext(ctx))
if err != nil {
return nil, err
}
s.ModifyEndpointIfRedirect(res)
defer ioutil.CheckClose(res.Body, &err)
if err = NewErr(res); err != nil {
return nil, err
}
ar := packp.NewAdvRefs()
if err = ar.Decode(res.Body); err != nil {
if err == packp.ErrEmptyAdvRefs {
err = transport.ErrEmptyRemoteRepository
}
return nil, err
}
// Git 2.41+ returns a zero-id plus capabilities when an empty
// repository is being cloned. This skips the existing logic within
// advrefs_decode.decodeFirstHash, which expects a flush-pkt instead.
//
// This logic aligns with plumbing/transport/internal/common/common.go.
if ar.IsEmpty() &&
// Empty repositories are valid for git-receive-pack.
transport.ReceivePackServiceName != serviceName {
return nil, transport.ErrEmptyRemoteRepository
}
transport.FilterUnsupportedCapabilities(ar.Capabilities)
s.advRefs = ar
return ar, nil
}
type client struct {
client *http.Client
transports *lru.Cache
mutex sync.RWMutex
}
// ClientOptions holds user configurable options for the client.
type ClientOptions struct {
// CacheMaxEntries is the max no. of entries that the transport objects
// cache will hold at any given point of time. It must be a positive integer.
// Calling `client.addTransport()` after the cache has reached the specified
// size, will result in the least recently used transport getting deleted
// before the provided transport is added to the cache.
CacheMaxEntries int
}
var (
// defaultTransportCacheSize is the default capacity of the transport objects cache.
// Its value is 0 because transport caching is turned off by default and is an
// opt-in feature.
defaultTransportCacheSize = 0
// DefaultClient is the default HTTP client, which uses a net/http client configured
// with http.DefaultTransport.
DefaultClient = NewClient(nil)
)
// NewClient creates a new client with a custom net/http client.
// See `InstallProtocol` to install and override default http client.
// If the net/http client is nil or empty, it will use a net/http client configured
// with http.DefaultTransport.
//
// Note that for HTTP client cannot distinguish between private repositories and
// unexistent repositories on GitHub. So it returns `ErrAuthorizationRequired`
// for both.
func NewClient(c *http.Client) transport.Transport {
if c == nil {
c = &http.Client{
Transport: http.DefaultTransport,
}
}
return NewClientWithOptions(c, &ClientOptions{
CacheMaxEntries: defaultTransportCacheSize,
})
}
// NewClientWithOptions returns a new client configured with the provided net/http client
// and other custom options specific to the client.
// If the net/http client is nil or empty, it will use a net/http client configured
// with http.DefaultTransport.
func NewClientWithOptions(c *http.Client, opts *ClientOptions) transport.Transport {
if c == nil {
c = &http.Client{
Transport: http.DefaultTransport,
}
}
cl := &client{
client: c,
}
if opts != nil {
if opts.CacheMaxEntries > 0 {
cl.transports = lru.New(opts.CacheMaxEntries)
}
}
return cl
}
func (c *client) NewUploadPackSession(ep *transport.Endpoint, auth transport.AuthMethod) (
transport.UploadPackSession, error) {
return newUploadPackSession(c, ep, auth)
}
func (c *client) NewReceivePackSession(ep *transport.Endpoint, auth transport.AuthMethod) (
transport.ReceivePackSession, error) {
return newReceivePackSession(c, ep, auth)
}
type session struct {
auth AuthMethod
client *http.Client
endpoint *transport.Endpoint
advRefs *packp.AdvRefs
}
func transportWithInsecureTLS(transport *http.Transport) {
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{}
}
transport.TLSClientConfig.InsecureSkipVerify = true
}
func transportWithCABundle(transport *http.Transport, caBundle []byte) error {
rootCAs, err := x509.SystemCertPool()
if err != nil {
return err
}
if rootCAs == nil {
rootCAs = x509.NewCertPool()
}
rootCAs.AppendCertsFromPEM(caBundle)
if transport.TLSClientConfig == nil {
transport.TLSClientConfig = &tls.Config{}
}
transport.TLSClientConfig.RootCAs = rootCAs
return nil
}
func transportWithProxy(transport *http.Transport, proxyURL *url.URL) {
transport.Proxy = http.ProxyURL(proxyURL)
}
func configureTransport(transport *http.Transport, ep *transport.Endpoint) error {
if len(ep.CaBundle) > 0 {
if err := transportWithCABundle(transport, ep.CaBundle); err != nil {
return err
}
}
if ep.InsecureSkipTLS {
transportWithInsecureTLS(transport)
}
if ep.Proxy.URL != "" {
proxyURL, err := ep.Proxy.FullURL()
if err != nil {
return err
}
transportWithProxy(transport, proxyURL)
}
return nil
}
func newSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (*session, error) {
var httpClient *http.Client
// We need to configure the http transport if there are transport specific
// options present in the endpoint.
if len(ep.CaBundle) > 0 || ep.InsecureSkipTLS || ep.Proxy.URL != "" {
var transport *http.Transport
// if the client wasn't configured to have a cache for transports then just configure
// the transport and use it directly, otherwise try to use the cache.
if c.transports == nil {
tr, ok := c.client.Transport.(*http.Transport)
if !ok {
return nil, fmt.Errorf("expected underlying client transport to be of type: %s; got: %s",
reflect.TypeOf(transport), reflect.TypeOf(c.client.Transport))
}
transport = tr.Clone()
configureTransport(transport, ep)
} else {
transportOpts := transportOptions{
caBundle: string(ep.CaBundle),
insecureSkipTLS: ep.InsecureSkipTLS,
}
if ep.Proxy.URL != "" {
proxyURL, err := ep.Proxy.FullURL()
if err != nil {
return nil, err
}
transportOpts.proxyURL = *proxyURL
}
var found bool
transport, found = c.fetchTransport(transportOpts)
if !found {
transport = c.client.Transport.(*http.Transport).Clone()
configureTransport(transport, ep)
c.addTransport(transportOpts, transport)
}
}
httpClient = &http.Client{
Transport: transport,
CheckRedirect: c.client.CheckRedirect,
Jar: c.client.Jar,
Timeout: c.client.Timeout,
}
} else {
httpClient = c.client
}
s := &session{
auth: basicAuthFromEndpoint(ep),
client: httpClient,
endpoint: ep,
}
if auth != nil {
a, ok := auth.(AuthMethod)
if !ok {
return nil, transport.ErrInvalidAuthMethod
}
s.auth = a
}
return s, nil
}
func (s *session) ApplyAuthToRequest(req *http.Request) {
if s.auth == nil {
return
}
s.auth.SetAuth(req)
}
func (s *session) ModifyEndpointIfRedirect(res *http.Response) {
if res.Request == nil {
return
}
r := res.Request
if !strings.HasSuffix(r.URL.Path, infoRefsPath) {
return
}
h, p, err := net.SplitHostPort(r.URL.Host)
if err != nil {
h = r.URL.Host
}
if p != "" {
port, err := strconv.Atoi(p)
if err == nil {
s.endpoint.Port = port
}
}
s.endpoint.Host = h
s.endpoint.Protocol = r.URL.Scheme
s.endpoint.Path = r.URL.Path[:len(r.URL.Path)-len(infoRefsPath)]
}
func (*session) Close() error {
return nil
}
// AuthMethod is concrete implementation of common.AuthMethod for HTTP services
type AuthMethod interface {
transport.AuthMethod
SetAuth(r *http.Request)
}
func basicAuthFromEndpoint(ep *transport.Endpoint) *BasicAuth {
u := ep.User
if u == "" {
return nil
}
return &BasicAuth{u, ep.Password}
}
// BasicAuth represent a HTTP basic auth
type BasicAuth struct {
Username, Password string
}
func (a *BasicAuth) SetAuth(r *http.Request) {
if a == nil {
return
}
r.SetBasicAuth(a.Username, a.Password)
}
// Name is name of the auth
func (a *BasicAuth) Name() string {
return "http-basic-auth"
}
func (a *BasicAuth) String() string {
masked := "*******"
if a.Password == "" {
masked = "]"
}
return fmt.Sprintf("%s - %s:%s", a.Name(), a.Username, masked)
}
// TokenAuth implements an http.AuthMethod that can be used with http transport
// to authenticate with HTTP token authentication (also known as bearer
// authentication).
//
// IMPORTANT: If you are looking to use OAuth tokens with popular servers (e.g.
// GitHub, Bitbucket, GitLab) you should use BasicAuth instead. These servers
// use basic HTTP authentication, with the OAuth token as user or password.
// Check the documentation of your git server for details.
type TokenAuth struct {
Token string
}
func (a *TokenAuth) SetAuth(r *http.Request) {
if a == nil {
return
}
r.Header.Add("Authorization", fmt.Sprintf("Bearer %s", a.Token))
}
// Name is name of the auth
func (a *TokenAuth) Name() string {
return "http-token-auth"
}
func (a *TokenAuth) String() string {
masked := "*******"
if a.Token == "" {
masked = ""
}
return fmt.Sprintf("%s - %s", a.Name(), masked)
}
// Err is a dedicated error to return errors based on status code
type Err struct {
Response *http.Response
Reason string
}
// NewErr returns a new Err based on a http response and closes response body
// if needed
func NewErr(r *http.Response) error {
if r.StatusCode >= http.StatusOK && r.StatusCode < http.StatusMultipleChoices {
return nil
}
var reason string
// If a response message is present, add it to error
var messageBuffer bytes.Buffer
if r.Body != nil {
messageLength, _ := messageBuffer.ReadFrom(r.Body)
if messageLength > 0 {
reason = messageBuffer.String()
}
_ = r.Body.Close()
}
switch r.StatusCode {
case http.StatusUnauthorized:
return fmt.Errorf("%w: %s", transport.ErrAuthenticationRequired, reason)
case http.StatusForbidden:
return fmt.Errorf("%w: %s", transport.ErrAuthorizationFailed, reason)
case http.StatusNotFound:
return fmt.Errorf("%w: %s", transport.ErrRepositoryNotFound, reason)
}
return plumbing.NewUnexpectedError(&Err{r, reason})
}
// StatusCode returns the status code of the response
func (e *Err) StatusCode() int {
return e.Response.StatusCode
}
func (e *Err) Error() string {
return fmt.Sprintf("unexpected requesting %q status code: %d",
e.Response.Request.URL, e.Response.StatusCode,
)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/http/receive_pack.go
================================================
package http
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/utils/ioutil"
)
type rpSession struct {
*session
}
func newReceivePackSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (transport.ReceivePackSession, error) {
s, err := newSession(c, ep, auth)
return &rpSession{s}, err
}
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) {
return advertisedReferences(context.TODO(), s.session, transport.ReceivePackServiceName)
}
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
return advertisedReferences(ctx, s.session, transport.ReceivePackServiceName)
}
func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateRequest) (
*packp.ReportStatus, error) {
url := fmt.Sprintf(
"%s/%s",
s.endpoint.String(), transport.ReceivePackServiceName,
)
buf := bytes.NewBuffer(nil)
if err := req.Encode(buf); err != nil {
return nil, err
}
res, err := s.doRequest(ctx, http.MethodPost, url, buf)
if err != nil {
return nil, err
}
r, err := ioutil.NonEmptyReader(res.Body)
if err == ioutil.ErrEmptyReader {
return nil, nil
}
if err != nil {
return nil, err
}
var d *sideband.Demuxer
if req.Capabilities.Supports(capability.Sideband64k) {
d = sideband.NewDemuxer(sideband.Sideband64k, r)
} else if req.Capabilities.Supports(capability.Sideband) {
d = sideband.NewDemuxer(sideband.Sideband, r)
}
if d != nil {
d.Progress = req.Progress
r = d
}
rc := ioutil.NewReadCloser(r, res.Body)
report := packp.NewReportStatus()
if err := report.Decode(rc); err != nil {
return nil, err
}
return report, report.Error()
}
func (s *rpSession) doRequest(
ctx context.Context, method, url string, content *bytes.Buffer,
) (*http.Response, error) {
var body io.Reader
if content != nil {
body = content
}
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, plumbing.NewPermanentError(err)
}
applyHeadersToRequest(req, content, s.endpoint.Host, transport.ReceivePackServiceName)
s.ApplyAuthToRequest(req)
res, err := s.client.Do(req.WithContext(ctx))
if err != nil {
return nil, plumbing.NewUnexpectedError(err)
}
if err := NewErr(res); err != nil {
return nil, err
}
return res, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/http/transport.go
================================================
package http
import (
"net/http"
"net/url"
)
// transportOptions contains transport specific configuration.
type transportOptions struct {
insecureSkipTLS bool
// []byte is not comparable.
caBundle string
proxyURL url.URL
}
func (c *client) addTransport(opts transportOptions, transport *http.Transport) {
c.mutex.Lock()
c.transports.Add(opts, transport)
c.mutex.Unlock()
}
func (c *client) removeTransport(opts transportOptions) {
c.mutex.Lock()
c.transports.Remove(opts)
c.mutex.Unlock()
}
func (c *client) fetchTransport(opts transportOptions) (*http.Transport, bool) {
c.mutex.RLock()
t, ok := c.transports.Get(opts)
c.mutex.RUnlock()
if !ok {
return nil, false
}
transport, ok := t.(*http.Transport)
if !ok {
return nil, false
}
return transport, true
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/http/upload_pack.go
================================================
package http
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"github.com/go-git/go-git/v5/utils/ioutil"
)
type upSession struct {
*session
}
func newUploadPackSession(c *client, ep *transport.Endpoint, auth transport.AuthMethod) (transport.UploadPackSession, error) {
s, err := newSession(c, ep, auth)
return &upSession{s}, err
}
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) {
return advertisedReferences(context.TODO(), s.session, transport.UploadPackServiceName)
}
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
return advertisedReferences(ctx, s.session, transport.UploadPackServiceName)
}
func (s *upSession) UploadPack(
ctx context.Context, req *packp.UploadPackRequest,
) (*packp.UploadPackResponse, error) {
if req.IsEmpty() {
return nil, transport.ErrEmptyUploadPackRequest
}
if err := req.Validate(); err != nil {
return nil, err
}
url := fmt.Sprintf(
"%s/%s",
s.endpoint.String(), transport.UploadPackServiceName,
)
content, err := uploadPackRequestToReader(req)
if err != nil {
return nil, err
}
res, err := s.doRequest(ctx, http.MethodPost, url, content)
if err != nil {
return nil, err
}
r, err := ioutil.NonEmptyReader(res.Body)
if err != nil {
if err == ioutil.ErrEmptyReader || err == io.ErrUnexpectedEOF {
return nil, transport.ErrEmptyUploadPackRequest
}
return nil, err
}
rc := ioutil.NewReadCloser(r, res.Body)
return common.DecodeUploadPackResponse(rc, req)
}
// Close does nothing.
func (s *upSession) Close() error {
return nil
}
func (s *upSession) doRequest(
ctx context.Context, method, url string, content *bytes.Buffer,
) (*http.Response, error) {
var body io.Reader
if content != nil {
body = content
}
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, plumbing.NewPermanentError(err)
}
applyHeadersToRequest(req, content, s.endpoint.Host, transport.UploadPackServiceName)
s.ApplyAuthToRequest(req)
res, err := s.client.Do(req.WithContext(ctx))
if err != nil {
return nil, plumbing.NewUnexpectedError(err)
}
if err := NewErr(res); err != nil {
return nil, err
}
return res, nil
}
func uploadPackRequestToReader(req *packp.UploadPackRequest) (*bytes.Buffer, error) {
buf := bytes.NewBuffer(nil)
e := pktline.NewEncoder(buf)
if err := req.UploadRequest.Encode(buf); err != nil {
return nil, fmt.Errorf("sending upload-req message: %s", err)
}
if err := req.UploadHaves.Encode(buf, false); err != nil {
return nil, fmt.Errorf("sending haves message: %s", err)
}
if err := e.EncodeString("done\n"); err != nil {
return nil, err
}
return buf, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/internal/common/common.go
================================================
// Package common implements the git pack protocol with a pluggable transport.
// This is a low-level package to implement new transports. Use a concrete
// implementation instead (e.g. http, file, ssh).
//
// A simple example of usage can be found in the file package.
package common
import (
"bufio"
"context"
"errors"
"fmt"
"io"
"regexp"
"strings"
"time"
"github.com/go-git/go-git/v5/plumbing/format/pktline"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/utils/ioutil"
)
const (
readErrorSecondsTimeout = 10
)
var (
ErrTimeoutExceeded = errors.New("timeout exceeded")
// stdErrSkipPattern is used for skipping lines from a command's stderr output.
// Any line matching this pattern will be skipped from further
// processing and not be returned to calling code.
stdErrSkipPattern = regexp.MustCompile("^remote:( =*){0,1}$")
)
// Commander creates Command instances. This is the main entry point for
// transport implementations.
type Commander interface {
// Command creates a new Command for the given git command and
// endpoint. cmd can be git-upload-pack or git-receive-pack. An
// error should be returned if the endpoint is not supported or the
// command cannot be created (e.g. binary does not exist, connection
// cannot be established).
Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (Command, error)
}
// Command is used for a single command execution.
// This interface is modeled after exec.Cmd and ssh.Session in the standard
// library.
type Command interface {
// StderrPipe returns a pipe that will be connected to the command's
// standard error when the command starts. It should not be called after
// Start.
StderrPipe() (io.Reader, error)
// StdinPipe returns a pipe that will be connected to the command's
// standard input when the command starts. It should not be called after
// Start. The pipe should be closed when no more input is expected.
StdinPipe() (io.WriteCloser, error)
// StdoutPipe returns a pipe that will be connected to the command's
// standard output when the command starts. It should not be called after
// Start.
StdoutPipe() (io.Reader, error)
// Start starts the specified command. It does not wait for it to
// complete.
Start() error
// Close closes the command and releases any resources used by it. It
// will block until the command exits.
Close() error
}
// CommandKiller expands the Command interface, enabling it for being killed.
type CommandKiller interface {
// Kill and close the session whatever the state it is. It will block until
// the command is terminated.
Kill() error
}
type client struct {
cmdr Commander
}
// NewClient creates a new client using the given Commander.
func NewClient(runner Commander) transport.Transport {
return &client{runner}
}
// NewUploadPackSession creates a new UploadPackSession.
func (c *client) NewUploadPackSession(ep *transport.Endpoint, auth transport.AuthMethod) (
transport.UploadPackSession, error) {
return c.newSession(transport.UploadPackServiceName, ep, auth)
}
// NewReceivePackSession creates a new ReceivePackSession.
func (c *client) NewReceivePackSession(ep *transport.Endpoint, auth transport.AuthMethod) (
transport.ReceivePackSession, error) {
return c.newSession(transport.ReceivePackServiceName, ep, auth)
}
type session struct {
Stdin io.WriteCloser
Stdout io.Reader
Command Command
isReceivePack bool
advRefs *packp.AdvRefs
packRun bool
finished bool
firstErrLine chan string
}
func (c *client) newSession(s string, ep *transport.Endpoint, auth transport.AuthMethod) (*session, error) {
cmd, err := c.cmdr.Command(s, ep, auth)
if err != nil {
return nil, err
}
stdin, err := cmd.StdinPipe()
if err != nil {
return nil, err
}
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
stderr, err := cmd.StderrPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
return &session{
Stdin: stdin,
Stdout: stdout,
Command: cmd,
firstErrLine: c.listenFirstError(stderr),
isReceivePack: s == transport.ReceivePackServiceName,
}, nil
}
func (c *client) listenFirstError(r io.Reader) chan string {
if r == nil {
return nil
}
errLine := make(chan string, 1)
go func() {
s := bufio.NewScanner(r)
for {
if s.Scan() {
line := s.Text()
if !stdErrSkipPattern.MatchString(line) {
errLine <- line
break
}
} else {
close(errLine)
break
}
}
_, _ = io.Copy(io.Discard, r)
}()
return errLine
}
func (s *session) AdvertisedReferences() (*packp.AdvRefs, error) {
return s.AdvertisedReferencesContext(context.TODO())
}
// AdvertisedReferences retrieves the advertised references from the server.
func (s *session) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
if s.advRefs != nil {
return s.advRefs, nil
}
ar := packp.NewAdvRefs()
if err := ar.Decode(s.StdoutContext(ctx)); err != nil {
if err := s.handleAdvRefDecodeError(err); err != nil {
return nil, err
}
}
// Some servers like jGit, announce capabilities instead of returning an
// packp message with a flush. This verifies that we received a empty
// adv-refs, even it contains capabilities.
if !s.isReceivePack && ar.IsEmpty() {
return nil, transport.ErrEmptyRemoteRepository
}
transport.FilterUnsupportedCapabilities(ar.Capabilities)
s.advRefs = ar
return ar, nil
}
func (s *session) handleAdvRefDecodeError(err error) error {
var errLine *pktline.ErrorLine
if errors.As(err, &errLine) {
if isRepoNotFoundError(errLine.Text) {
return transport.ErrRepositoryNotFound
}
return errLine
}
// If repository is not found, we get empty stdout and server writes an
// error to stderr.
if errors.Is(err, packp.ErrEmptyInput) {
// TODO:(v6): handle this error in a better way.
// Instead of checking the stderr output for a specific error message,
// define an ExitError and embed the stderr output and exit (if one
// exists) in the error struct. Just like exec.ExitError.
s.finished = true
if err := s.checkNotFoundError(); err != nil {
return err
}
return io.ErrUnexpectedEOF
}
// For empty (but existing) repositories, we get empty advertised-references
// message. But valid. That is, it includes at least a flush.
if err == packp.ErrEmptyAdvRefs {
// Empty repositories are valid for git-receive-pack.
if s.isReceivePack {
return nil
}
if err := s.finish(); err != nil {
return err
}
return transport.ErrEmptyRemoteRepository
}
// Some server sends the errors as normal content (git protocol), so when
// we try to decode it fails, we need to check the content of it, to detect
// not found errors
if uerr, ok := err.(*packp.ErrUnexpectedData); ok {
if isRepoNotFoundError(string(uerr.Data)) {
return transport.ErrRepositoryNotFound
}
}
return err
}
// UploadPack performs a request to the server to fetch a packfile. A reader is
// returned with the packfile content. The reader must be closed after reading.
func (s *session) UploadPack(ctx context.Context, req *packp.UploadPackRequest) (*packp.UploadPackResponse, error) {
if req.IsEmpty() {
// XXX: IsEmpty means haves are a subset of wants, in that case we have
// everything we asked for. Close the connection and return nil.
if err := s.finish(); err != nil {
return nil, err
}
// TODO:(v6) return nil here
return nil, transport.ErrEmptyUploadPackRequest
}
if err := req.Validate(); err != nil {
return nil, err
}
if _, err := s.AdvertisedReferencesContext(ctx); err != nil {
return nil, err
}
s.packRun = true
in := s.StdinContext(ctx)
out := s.StdoutContext(ctx)
if err := uploadPack(in, out, req); err != nil {
return nil, err
}
r, err := ioutil.NonEmptyReader(out)
if err == ioutil.ErrEmptyReader {
if c, ok := s.Stdout.(io.Closer); ok {
_ = c.Close()
}
return nil, transport.ErrEmptyUploadPackRequest
}
if err != nil {
return nil, err
}
rc := ioutil.NewReadCloser(r, s)
return DecodeUploadPackResponse(rc, req)
}
func (s *session) StdinContext(ctx context.Context) io.WriteCloser {
return ioutil.NewWriteCloserOnError(
ioutil.NewContextWriteCloser(ctx, s.Stdin),
s.onError,
)
}
func (s *session) StdoutContext(ctx context.Context) io.Reader {
return ioutil.NewReaderOnError(
ioutil.NewContextReader(ctx, s.Stdout),
s.onError,
)
}
func (s *session) onError(err error) {
if k, ok := s.Command.(CommandKiller); ok {
_ = k.Kill()
}
_ = s.Close()
}
func (s *session) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateRequest) (*packp.ReportStatus, error) {
if _, err := s.AdvertisedReferences(); err != nil {
return nil, err
}
s.packRun = true
w := s.StdinContext(ctx)
if err := req.Encode(w); err != nil {
return nil, err
}
if err := w.Close(); err != nil {
return nil, err
}
if !req.Capabilities.Supports(capability.ReportStatus) {
// If we don't have report-status, we can only
// check return value error.
return nil, s.Command.Close()
}
r := s.StdoutContext(ctx)
var d *sideband.Demuxer
if req.Capabilities.Supports(capability.Sideband64k) {
d = sideband.NewDemuxer(sideband.Sideband64k, r)
} else if req.Capabilities.Supports(capability.Sideband) {
d = sideband.NewDemuxer(sideband.Sideband, r)
}
if d != nil {
d.Progress = req.Progress
r = d
}
report := packp.NewReportStatus()
if err := report.Decode(r); err != nil {
return nil, err
}
if err := report.Error(); err != nil {
defer s.Close()
return report, err
}
return report, s.Command.Close()
}
func (s *session) finish() error {
if s.finished {
return nil
}
s.finished = true
// If we did not run a upload/receive-pack, we close the connection
// gracefully by sending a flush packet to the server. If the server
// operates correctly, it will exit with status 0.
if !s.packRun {
_, err := s.Stdin.Write(pktline.FlushPkt)
return err
}
return nil
}
func (s *session) Close() (err error) {
err = s.finish()
defer ioutil.CheckClose(s.Command, &err)
return
}
func (s *session) checkNotFoundError() error {
t := time.NewTicker(time.Second * readErrorSecondsTimeout)
defer t.Stop()
select {
case <-t.C:
return ErrTimeoutExceeded
case line, ok := <-s.firstErrLine:
if !ok || len(line) == 0 {
return nil
}
if isRepoNotFoundError(line) {
return transport.ErrRepositoryNotFound
}
// TODO:(v6): return server error just as it is without a prefix
return fmt.Errorf("unknown error: %s", line)
}
}
const (
githubRepoNotFoundErr = "Repository not found."
bitbucketRepoNotFoundErr = "repository does not exist."
localRepoNotFoundErr = "does not appear to be a git repository"
gitProtocolNotFoundErr = "Repository not found."
gitProtocolNoSuchErr = "no such repository"
gitProtocolAccessDeniedErr = "access denied"
gogsAccessDeniedErr = "Repository does not exist or you do not have access"
gitlabRepoNotFoundErr = "The project you were looking for could not be found"
)
func isRepoNotFoundError(s string) bool {
for _, err := range []string{
githubRepoNotFoundErr,
bitbucketRepoNotFoundErr,
localRepoNotFoundErr,
gitProtocolNotFoundErr,
gitProtocolNoSuchErr,
gitProtocolAccessDeniedErr,
gogsAccessDeniedErr,
gitlabRepoNotFoundErr,
} {
if strings.Contains(s, err) {
return true
}
}
return false
}
// uploadPack implements the git-upload-pack protocol.
func uploadPack(w io.WriteCloser, _ io.Reader, req *packp.UploadPackRequest) error {
// TODO support multi_ack mode
// TODO support multi_ack_detailed mode
// TODO support acks for common objects
// TODO build a proper state machine for all these processing options
if err := req.UploadRequest.Encode(w); err != nil {
return fmt.Errorf("sending upload-req message: %s", err)
}
if err := req.UploadHaves.Encode(w, true); err != nil {
return fmt.Errorf("sending haves message: %s", err)
}
if err := sendDone(w); err != nil {
return fmt.Errorf("sending done message: %s", err)
}
if err := w.Close(); err != nil {
return fmt.Errorf("closing input: %s", err)
}
return nil
}
func sendDone(w io.Writer) error {
e := pktline.NewEncoder(w)
return e.Encodef("done\n")
}
// DecodeUploadPackResponse decodes r into a new packp.UploadPackResponse
func DecodeUploadPackResponse(r io.ReadCloser, req *packp.UploadPackRequest) (
*packp.UploadPackResponse, error,
) {
res := packp.NewUploadPackResponse(req)
if err := res.Decode(r); err != nil {
return nil, fmt.Errorf("error decoding upload-pack response: %s", err)
}
return res, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/internal/common/mocks.go
================================================
package common
import (
"bytes"
"io"
gogitioutil "github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/plumbing/transport"
)
type MockCommand struct {
stdin bytes.Buffer
stdout bytes.Buffer
stderr bytes.Buffer
}
func (c MockCommand) StderrPipe() (io.Reader, error) {
return &c.stderr, nil
}
func (c MockCommand) StdinPipe() (io.WriteCloser, error) {
return gogitioutil.WriteNopCloser(&c.stdin), nil
}
func (c MockCommand) StdoutPipe() (io.Reader, error) {
return &c.stdout, nil
}
func (c MockCommand) Start() error {
return nil
}
func (c MockCommand) Close() error {
panic("not implemented")
}
type MockCommander struct {
stderr string
}
func (c MockCommander) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (Command, error) {
return &MockCommand{
stderr: *bytes.NewBufferString(c.stderr),
}, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/internal/common/server.go
================================================
package common
import (
"context"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// ServerCommand is used for a single server command execution.
type ServerCommand struct {
Stderr io.Writer
Stdout io.WriteCloser
Stdin io.Reader
}
func ServeUploadPack(cmd ServerCommand, s transport.UploadPackSession) (err error) {
ioutil.CheckClose(cmd.Stdout, &err)
ar, err := s.AdvertisedReferences()
if err != nil {
return err
}
if err := ar.Encode(cmd.Stdout); err != nil {
return err
}
req := packp.NewUploadPackRequest()
if err := req.Decode(cmd.Stdin); err != nil {
return err
}
var resp *packp.UploadPackResponse
resp, err = s.UploadPack(context.TODO(), req)
if err != nil {
return err
}
return resp.Encode(cmd.Stdout)
}
func ServeReceivePack(cmd ServerCommand, s transport.ReceivePackSession) error {
ar, err := s.AdvertisedReferences()
if err != nil {
return fmt.Errorf("internal error in advertised references: %s", err)
}
if err := ar.Encode(cmd.Stdout); err != nil {
return fmt.Errorf("error in advertised references encoding: %s", err)
}
req := packp.NewReferenceUpdateRequest()
if err := req.Decode(cmd.Stdin); err != nil {
return fmt.Errorf("error decoding: %s", err)
}
rs, err := s.ReceivePack(context.TODO(), req)
if rs != nil {
if err := rs.Encode(cmd.Stdout); err != nil {
return fmt.Errorf("error in encoding report status %s", err)
}
}
if err != nil {
return fmt.Errorf("error in receive pack: %s", err)
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/server/loader.go
================================================
package server
import (
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/osfs"
)
// DefaultLoader is a filesystem loader ignoring host and resolving paths to /.
var DefaultLoader = NewFilesystemLoader(osfs.New(""))
// Loader loads repository's storer.Storer based on an optional host and a path.
type Loader interface {
// Load loads a storer.Storer given a transport.Endpoint.
// Returns transport.ErrRepositoryNotFound if the repository does not
// exist.
Load(ep *transport.Endpoint) (storer.Storer, error)
}
type fsLoader struct {
base billy.Filesystem
}
// NewFilesystemLoader creates a Loader that ignores host and resolves paths
// with a given base filesystem.
func NewFilesystemLoader(base billy.Filesystem) Loader {
return &fsLoader{base}
}
// Load looks up the endpoint's path in the base file system and returns a
// storer for it. Returns transport.ErrRepositoryNotFound if a repository does
// not exist in the given path.
func (l *fsLoader) Load(ep *transport.Endpoint) (storer.Storer, error) {
fs, err := l.base.Chroot(ep.Path)
if err != nil {
return nil, err
}
var bare bool
if _, err := fs.Stat("config"); err == nil {
bare = true
}
if !bare {
// do not use git.GitDirName due to import cycle
if _, err := fs.Stat(".git"); err != nil {
return nil, transport.ErrRepositoryNotFound
}
}
return filesystem.NewStorage(fs, cache.NewObjectLRUDefault()), nil
}
// MapLoader is a Loader that uses a lookup map of storer.Storer by
// transport.Endpoint.
type MapLoader map[string]storer.Storer
// Load returns a storer.Storer for given a transport.Endpoint by looking it up
// in the map. Returns transport.ErrRepositoryNotFound if the endpoint does not
// exist.
func (l MapLoader) Load(ep *transport.Endpoint) (storer.Storer, error) {
s, ok := l[ep.String()]
if !ok {
return nil, transport.ErrRepositoryNotFound
}
return s, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/server/server.go
================================================
// Package server implements the git server protocol. For most use cases, the
// transport-specific implementations should be used.
package server
import (
"context"
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/revlist"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/utils/ioutil"
)
var DefaultServer = NewServer(DefaultLoader)
type server struct {
loader Loader
handler *handler
}
// NewServer returns a transport.Transport implementing a git server,
// independent of transport. Each transport must wrap this.
func NewServer(loader Loader) transport.Transport {
return &server{
loader,
&handler{asClient: false},
}
}
// NewClient returns a transport.Transport implementing a client with an
// embedded server.
func NewClient(loader Loader) transport.Transport {
return &server{
loader,
&handler{asClient: true},
}
}
func (s *server) NewUploadPackSession(ep *transport.Endpoint, auth transport.AuthMethod) (transport.UploadPackSession, error) {
sto, err := s.loader.Load(ep)
if err != nil {
return nil, err
}
return s.handler.NewUploadPackSession(sto)
}
func (s *server) NewReceivePackSession(ep *transport.Endpoint, auth transport.AuthMethod) (transport.ReceivePackSession, error) {
sto, err := s.loader.Load(ep)
if err != nil {
return nil, err
}
return s.handler.NewReceivePackSession(sto)
}
type handler struct {
asClient bool
}
func (h *handler) NewUploadPackSession(s storer.Storer) (transport.UploadPackSession, error) {
return &upSession{
session: session{storer: s, asClient: h.asClient},
}, nil
}
func (h *handler) NewReceivePackSession(s storer.Storer) (transport.ReceivePackSession, error) {
return &rpSession{
session: session{storer: s, asClient: h.asClient},
cmdStatus: map[plumbing.ReferenceName]error{},
}, nil
}
type session struct {
storer storer.Storer
caps *capability.List
asClient bool
}
func (s *session) Close() error {
return nil
}
func (s *session) SetAuth(transport.AuthMethod) error {
//TODO: deprecate
return nil
}
func (s *session) checkSupportedCapabilities(cl *capability.List) error {
for _, c := range cl.All() {
if !s.caps.Supports(c) {
return fmt.Errorf("unsupported capability: %s", c)
}
}
return nil
}
type upSession struct {
session
}
func (s *upSession) AdvertisedReferences() (*packp.AdvRefs, error) {
return s.AdvertisedReferencesContext(context.TODO())
}
func (s *upSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
ar := packp.NewAdvRefs()
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil {
return nil, err
}
s.caps = ar.Capabilities
if err := setReferences(s.storer, ar); err != nil {
return nil, err
}
if err := setHEAD(s.storer, ar); err != nil {
return nil, err
}
if s.asClient && len(ar.References) == 0 {
return nil, transport.ErrEmptyRemoteRepository
}
return ar, nil
}
func (s *upSession) UploadPack(ctx context.Context, req *packp.UploadPackRequest) (*packp.UploadPackResponse, error) {
if req.IsEmpty() {
return nil, transport.ErrEmptyUploadPackRequest
}
if err := req.Validate(); err != nil {
return nil, err
}
if s.caps == nil {
s.caps = capability.NewList()
if err := s.setSupportedCapabilities(s.caps); err != nil {
return nil, err
}
}
if err := s.checkSupportedCapabilities(req.Capabilities); err != nil {
return nil, err
}
s.caps = req.Capabilities
if len(req.Shallows) > 0 {
return nil, fmt.Errorf("shallow not supported")
}
objs, err := s.objectsToUpload(req)
if err != nil {
return nil, err
}
pr, pw := io.Pipe()
e := packfile.NewEncoder(pw, s.storer, false)
go func() {
// TODO: plumb through a pack window.
_, err := e.Encode(objs, 10)
pw.CloseWithError(err)
}()
return packp.NewUploadPackResponseWithPackfile(req,
ioutil.NewContextReadCloser(ctx, pr),
), nil
}
func (s *upSession) objectsToUpload(req *packp.UploadPackRequest) ([]plumbing.Hash, error) {
haves, err := revlist.Objects(s.storer, req.Haves, nil)
if err != nil {
return nil, err
}
return revlist.Objects(s.storer, req.Wants, haves)
}
func (*upSession) setSupportedCapabilities(c *capability.List) error {
if err := c.Set(capability.Agent, capability.DefaultAgent()); err != nil {
return err
}
if err := c.Set(capability.OFSDelta); err != nil {
return err
}
return nil
}
type rpSession struct {
session
cmdStatus map[plumbing.ReferenceName]error
firstErr error
unpackErr error
}
func (s *rpSession) AdvertisedReferences() (*packp.AdvRefs, error) {
return s.AdvertisedReferencesContext(context.TODO())
}
func (s *rpSession) AdvertisedReferencesContext(ctx context.Context) (*packp.AdvRefs, error) {
ar := packp.NewAdvRefs()
if err := s.setSupportedCapabilities(ar.Capabilities); err != nil {
return nil, err
}
s.caps = ar.Capabilities
if err := setReferences(s.storer, ar); err != nil {
return nil, err
}
if err := setHEAD(s.storer, ar); err != nil {
return nil, err
}
return ar, nil
}
var (
ErrUpdateReference = errors.New("failed to update ref")
)
func (s *rpSession) ReceivePack(ctx context.Context, req *packp.ReferenceUpdateRequest) (*packp.ReportStatus, error) {
if s.caps == nil {
s.caps = capability.NewList()
if err := s.setSupportedCapabilities(s.caps); err != nil {
return nil, err
}
}
if err := s.checkSupportedCapabilities(req.Capabilities); err != nil {
return nil, err
}
s.caps = req.Capabilities
//TODO: Implement 'atomic' update of references.
if req.Packfile != nil {
r := ioutil.NewContextReadCloser(ctx, req.Packfile)
if err := s.writePackfile(r); err != nil {
s.unpackErr = err
s.firstErr = err
return s.reportStatus(), err
}
}
s.updateReferences(req)
return s.reportStatus(), s.firstErr
}
func (s *rpSession) updateReferences(req *packp.ReferenceUpdateRequest) {
for _, cmd := range req.Commands {
exists, err := referenceExists(s.storer, cmd.Name)
if err != nil {
s.setStatus(cmd.Name, err)
continue
}
switch cmd.Action() {
case packp.Create:
if exists {
s.setStatus(cmd.Name, ErrUpdateReference)
continue
}
ref := plumbing.NewHashReference(cmd.Name, cmd.New)
err := s.storer.SetReference(ref)
s.setStatus(cmd.Name, err)
case packp.Delete:
if !exists {
s.setStatus(cmd.Name, ErrUpdateReference)
continue
}
err := s.storer.RemoveReference(cmd.Name)
s.setStatus(cmd.Name, err)
case packp.Update:
if !exists {
s.setStatus(cmd.Name, ErrUpdateReference)
continue
}
ref := plumbing.NewHashReference(cmd.Name, cmd.New)
err := s.storer.SetReference(ref)
s.setStatus(cmd.Name, err)
}
}
}
func (s *rpSession) writePackfile(r io.ReadCloser) error {
if r == nil {
return nil
}
if err := packfile.UpdateObjectStorage(s.storer, r); err != nil {
_ = r.Close()
return err
}
return r.Close()
}
func (s *rpSession) setStatus(ref plumbing.ReferenceName, err error) {
s.cmdStatus[ref] = err
if s.firstErr == nil && err != nil {
s.firstErr = err
}
}
func (s *rpSession) reportStatus() *packp.ReportStatus {
if !s.caps.Supports(capability.ReportStatus) {
return nil
}
rs := packp.NewReportStatus()
rs.UnpackStatus = "ok"
if s.unpackErr != nil {
rs.UnpackStatus = s.unpackErr.Error()
}
if s.cmdStatus == nil {
return rs
}
for ref, err := range s.cmdStatus {
msg := "ok"
if err != nil {
msg = err.Error()
}
status := &packp.CommandStatus{
ReferenceName: ref,
Status: msg,
}
rs.CommandStatuses = append(rs.CommandStatuses, status)
}
return rs
}
func (*rpSession) setSupportedCapabilities(c *capability.List) error {
if err := c.Set(capability.Agent, capability.DefaultAgent()); err != nil {
return err
}
if err := c.Set(capability.OFSDelta); err != nil {
return err
}
if err := c.Set(capability.DeleteRefs); err != nil {
return err
}
return c.Set(capability.ReportStatus)
}
func setHEAD(s storer.Storer, ar *packp.AdvRefs) error {
ref, err := s.Reference(plumbing.HEAD)
if err == plumbing.ErrReferenceNotFound {
return nil
}
if err != nil {
return err
}
if ref.Type() == plumbing.SymbolicReference {
if err := ar.AddReference(ref); err != nil {
return nil
}
ref, err = storer.ResolveReference(s, ref.Target())
if err == plumbing.ErrReferenceNotFound {
return nil
}
if err != nil {
return err
}
}
if ref.Type() != plumbing.HashReference {
return plumbing.ErrInvalidType
}
h := ref.Hash()
ar.Head = &h
return nil
}
func setReferences(s storer.Storer, ar *packp.AdvRefs) error {
//TODO: add peeled references.
iter, err := s.IterReferences()
if err != nil {
return err
}
return iter.ForEach(func(ref *plumbing.Reference) error {
if ref.Type() != plumbing.HashReference {
return nil
}
ar.References[ref.Name().String()] = ref.Hash()
return nil
})
}
func referenceExists(s storer.ReferenceStorer, n plumbing.ReferenceName) (bool, error) {
_, err := s.Reference(n)
if err == plumbing.ErrReferenceNotFound {
return false, nil
}
return err == nil, err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/auth_method.go
================================================
package ssh
import (
"errors"
"fmt"
"os"
"os/user"
"path/filepath"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/skeema/knownhosts"
sshagent "github.com/xanzy/ssh-agent"
"golang.org/x/crypto/ssh"
)
const DefaultUsername = "git"
// AuthMethod is the interface all auth methods for the ssh client
// must implement. The clientConfig method returns the ssh client
// configuration needed to establish an ssh connection.
type AuthMethod interface {
transport.AuthMethod
// ClientConfig should return a valid ssh.ClientConfig to be used to create
// a connection to the SSH server.
ClientConfig() (*ssh.ClientConfig, error)
}
// The names of the AuthMethod implementations. To be returned by the
// Name() method. Most git servers only allow PublicKeysName and
// PublicKeysCallbackName.
const (
KeyboardInteractiveName = "ssh-keyboard-interactive"
PasswordName = "ssh-password"
PasswordCallbackName = "ssh-password-callback"
PublicKeysName = "ssh-public-keys"
PublicKeysCallbackName = "ssh-public-key-callback"
)
// KeyboardInteractive implements AuthMethod by using a
// prompt/response sequence controlled by the server.
type KeyboardInteractive struct {
User string
Challenge ssh.KeyboardInteractiveChallenge
HostKeyCallbackHelper
}
func (a *KeyboardInteractive) Name() string {
return KeyboardInteractiveName
}
func (a *KeyboardInteractive) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}
func (a *KeyboardInteractive) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{
a.Challenge,
},
})
}
// Password implements AuthMethod by using the given password.
type Password struct {
User string
Password string
HostKeyCallbackHelper
}
func (a *Password) Name() string {
return PasswordName
}
func (a *Password) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}
func (a *Password) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.Password(a.Password)},
})
}
// PasswordCallback implements AuthMethod by using a callback
// to fetch the password.
type PasswordCallback struct {
User string
Callback func() (pass string, err error)
HostKeyCallbackHelper
}
func (a *PasswordCallback) Name() string {
return PasswordCallbackName
}
func (a *PasswordCallback) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}
func (a *PasswordCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PasswordCallback(a.Callback)},
})
}
// PublicKeys implements AuthMethod by using the given key pairs.
type PublicKeys struct {
User string
Signer ssh.Signer
HostKeyCallbackHelper
}
// NewPublicKeys returns a PublicKeys from a PEM encoded private key. An
// encryption password should be given if the pemBytes contains a password
// encrypted PEM block otherwise password should be empty. It supports RSA
// (PKCS#1), PKCS#8, DSA (OpenSSL), and ECDSA private keys.
func NewPublicKeys(user string, pemBytes []byte, password string) (*PublicKeys, error) {
signer, err := ssh.ParsePrivateKey(pemBytes)
if _, ok := err.(*ssh.PassphraseMissingError); ok {
signer, err = ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte(password))
}
if err != nil {
return nil, err
}
return &PublicKeys{User: user, Signer: signer}, nil
}
// NewPublicKeysFromFile returns a PublicKeys from a file containing a PEM
// encoded private key. An encryption password should be given if the pemBytes
// contains a password encrypted PEM block otherwise password should be empty.
func NewPublicKeysFromFile(user, pemFile, password string) (*PublicKeys, error) {
bytes, err := os.ReadFile(pemFile)
if err != nil {
return nil, err
}
return NewPublicKeys(user, bytes, password)
}
func (a *PublicKeys) Name() string {
return PublicKeysName
}
func (a *PublicKeys) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}
func (a *PublicKeys) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeys(a.Signer)},
})
}
func username() (string, error) {
var username string
if user, err := user.Current(); err == nil {
username = user.Username
} else {
username = os.Getenv("USER")
}
if username == "" {
return "", errors.New("failed to get username")
}
return username, nil
}
// PublicKeysCallback implements AuthMethod by asking a
// ssh.agent.Agent to act as a signer.
type PublicKeysCallback struct {
User string
Callback func() (signers []ssh.Signer, err error)
HostKeyCallbackHelper
}
// NewSSHAgentAuth returns a PublicKeysCallback based on a SSH agent, it opens
// a pipe with the SSH agent and uses the pipe as the implementer of the public
// key callback function.
func NewSSHAgentAuth(u string) (*PublicKeysCallback, error) {
var err error
if u == "" {
u, err = username()
if err != nil {
return nil, err
}
}
a, _, err := sshagent.New()
if err != nil {
return nil, fmt.Errorf("error creating SSH agent: %q", err)
}
return &PublicKeysCallback{
User: u,
Callback: a.Signers,
}, nil
}
func (a *PublicKeysCallback) Name() string {
return PublicKeysCallbackName
}
func (a *PublicKeysCallback) String() string {
return fmt.Sprintf("user: %s, name: %s", a.User, a.Name())
}
func (a *PublicKeysCallback) ClientConfig() (*ssh.ClientConfig, error) {
return a.SetHostKeyCallback(&ssh.ClientConfig{
User: a.User,
Auth: []ssh.AuthMethod{ssh.PublicKeysCallback(a.Callback)},
})
}
// NewKnownHostsCallback returns ssh.HostKeyCallback based on a file based on a
// known_hosts file. http://man.openbsd.org/sshd#SSH_KNOWN_HOSTS_FILE_FORMAT
//
// If list of files is empty, then it will be read from the SSH_KNOWN_HOSTS
// environment variable, example:
//
// /home/foo/custom_known_hosts_file:/etc/custom_known/hosts_file
//
// If SSH_KNOWN_HOSTS is not set the following file locations will be used:
//
// ~/.ssh/known_hosts
// /etc/ssh/ssh_known_hosts
func NewKnownHostsCallback(files ...string) (ssh.HostKeyCallback, error) {
kh, err := newKnownHosts(files...)
return ssh.HostKeyCallback(kh), err
}
func newKnownHosts(files ...string) (knownhosts.HostKeyCallback, error) {
var err error
if len(files) == 0 {
if files, err = getDefaultKnownHostsFiles(); err != nil {
return nil, err
}
}
if files, err = filterKnownHostsFiles(files...); err != nil {
return nil, err
}
return knownhosts.New(files...)
}
func getDefaultKnownHostsFiles() ([]string, error) {
files := filepath.SplitList(os.Getenv("SSH_KNOWN_HOSTS"))
if len(files) != 0 {
return files, nil
}
homeDirPath, err := os.UserHomeDir()
if err != nil {
return nil, err
}
return []string{
filepath.Join(homeDirPath, "/.ssh/known_hosts"),
"/etc/ssh/ssh_known_hosts",
}, nil
}
func filterKnownHostsFiles(files ...string) ([]string, error) {
var out []string
for _, file := range files {
_, err := os.Stat(file)
if err == nil {
out = append(out, file)
continue
}
if !os.IsNotExist(err) {
return nil, err
}
}
if len(out) == 0 {
return nil, fmt.Errorf("unable to find any valid known_hosts file, set SSH_KNOWN_HOSTS env variable")
}
return out, nil
}
// HostKeyCallbackHelper is a helper that provides common functionality to
// configure HostKeyCallback into a ssh.ClientConfig.
type HostKeyCallbackHelper struct {
// HostKeyCallback is the function type used for verifying server keys.
// If nil default callback will be create using NewKnownHostsCallback
// without argument.
HostKeyCallback ssh.HostKeyCallback
}
// SetHostKeyCallback sets the field HostKeyCallback in the given cfg. If
// HostKeyCallback is empty a default callback is created using
// NewKnownHostsCallback.
func (m *HostKeyCallbackHelper) SetHostKeyCallback(cfg *ssh.ClientConfig) (*ssh.ClientConfig, error) {
var err error
if m.HostKeyCallback == nil {
if m.HostKeyCallback, err = NewKnownHostsCallback(); err != nil {
return cfg, err
}
}
cfg.HostKeyCallback = m.HostKeyCallback
return cfg, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/plumbing/transport/ssh/common.go
================================================
// Package ssh implements the SSH transport protocol.
package ssh
import (
"context"
"fmt"
"net"
"reflect"
"strconv"
"strings"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/internal/common"
"github.com/skeema/knownhosts"
"github.com/kevinburke/ssh_config"
"golang.org/x/crypto/ssh"
"golang.org/x/net/proxy"
)
// DefaultClient is the default SSH client.
var DefaultClient = NewClient(nil)
// DefaultSSHConfig is the reader used to access parameters stored in the
// system's ssh_config files. If nil all the ssh_config are ignored.
var DefaultSSHConfig sshConfig = ssh_config.DefaultUserSettings
type sshConfig interface {
Get(alias, key string) string
}
// NewClient creates a new SSH client with an optional *ssh.ClientConfig.
func NewClient(config *ssh.ClientConfig) transport.Transport {
return common.NewClient(&runner{config: config})
}
// DefaultAuthBuilder is the function used to create a default AuthMethod, when
// the user doesn't provide any.
var DefaultAuthBuilder = func(user string) (AuthMethod, error) {
return NewSSHAgentAuth(user)
}
const DefaultPort = 22
type runner struct {
config *ssh.ClientConfig
}
func (r *runner) Command(cmd string, ep *transport.Endpoint, auth transport.AuthMethod) (common.Command, error) {
c := &command{command: cmd, endpoint: ep, config: r.config}
if auth != nil {
if err := c.setAuth(auth); err != nil {
return nil, err
}
}
if err := c.connect(); err != nil {
return nil, err
}
return c, nil
}
type command struct {
*ssh.Session
connected bool
command string
endpoint *transport.Endpoint
client *ssh.Client
auth AuthMethod
config *ssh.ClientConfig
}
func (c *command) setAuth(auth transport.AuthMethod) error {
a, ok := auth.(AuthMethod)
if !ok {
return transport.ErrInvalidAuthMethod
}
c.auth = a
return nil
}
func (c *command) Start() error {
return c.Session.Start(endpointToCommand(c.command, c.endpoint))
}
// Close closes the SSH session and connection.
func (c *command) Close() error {
if !c.connected {
return nil
}
c.connected = false
//XXX: If did read the full packfile, then the session might be already
// closed.
_ = c.Session.Close()
err := c.client.Close()
//XXX: in go1.16+ we can use errors.Is(err, net.ErrClosed)
if err != nil && strings.HasSuffix(err.Error(), "use of closed network connection") {
return nil
}
return err
}
// connect connects to the SSH server, unless a AuthMethod was set with
// SetAuth method, by default uses an auth method based on PublicKeysCallback,
// it connects to a SSH agent, using the address stored in the SSH_AUTH_SOCK
// environment var.
func (c *command) connect() error {
if c.connected {
return transport.ErrAlreadyConnected
}
if c.auth == nil {
if err := c.setAuthFromEndpoint(); err != nil {
return err
}
}
var err error
config, err := c.auth.ClientConfig()
if err != nil {
return err
}
hostWithPort := c.getHostWithPort()
if config.HostKeyCallback == nil {
kh, err := newKnownHosts()
if err != nil {
return err
}
config.HostKeyCallback = kh.HostKeyCallback()
config.HostKeyAlgorithms = kh.HostKeyAlgorithms(hostWithPort)
} else if len(config.HostKeyAlgorithms) == 0 {
// Set the HostKeyAlgorithms based on HostKeyCallback.
// For background see https://github.com/go-git/go-git/issues/411 as well as
// https://github.com/golang/go/issues/29286 for root cause.
config.HostKeyAlgorithms = knownhosts.HostKeyAlgorithms(config.HostKeyCallback, hostWithPort)
}
overrideConfig(c.config, config)
c.client, err = dial("tcp", hostWithPort, c.endpoint.Proxy, config)
if err != nil {
return err
}
c.Session, err = c.client.NewSession()
if err != nil {
_ = c.client.Close()
return err
}
c.connected = true
return nil
}
func dial(network, addr string, proxyOpts transport.ProxyOptions, config *ssh.ClientConfig) (*ssh.Client, error) {
var (
ctx = context.Background()
cancel context.CancelFunc
)
if config.Timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, config.Timeout)
} else {
ctx, cancel = context.WithCancel(ctx)
}
defer cancel()
var conn net.Conn
var dialErr error
if proxyOpts.URL != "" {
proxyUrl, err := proxyOpts.FullURL()
if err != nil {
return nil, err
}
dialer, err := proxy.FromURL(proxyUrl, proxy.Direct)
if err != nil {
return nil, err
}
// Try to use a ContextDialer, but fall back to a Dialer if that goes south.
ctxDialer, ok := dialer.(proxy.ContextDialer)
if !ok {
return nil, fmt.Errorf("expected ssh proxy dialer to be of type %s; got %s",
reflect.TypeOf(ctxDialer), reflect.TypeOf(dialer))
}
conn, dialErr = ctxDialer.DialContext(ctx, "tcp", addr)
} else {
conn, dialErr = proxy.Dial(ctx, network, addr)
}
if dialErr != nil {
return nil, dialErr
}
c, chans, reqs, err := ssh.NewClientConn(conn, addr, config)
if err != nil {
return nil, err
}
return ssh.NewClient(c, chans, reqs), nil
}
func (c *command) getHostWithPort() string {
if addr, found := c.doGetHostWithPortFromSSHConfig(); found {
return addr
}
host := c.endpoint.Host
port := c.endpoint.Port
if port <= 0 {
port = DefaultPort
}
return net.JoinHostPort(host, strconv.Itoa(port))
}
func (c *command) doGetHostWithPortFromSSHConfig() (addr string, found bool) {
if DefaultSSHConfig == nil {
return
}
host := c.endpoint.Host
port := c.endpoint.Port
configHost := DefaultSSHConfig.Get(c.endpoint.Host, "Hostname")
if configHost != "" {
host = configHost
found = true
}
if !found {
return
}
configPort := DefaultSSHConfig.Get(c.endpoint.Host, "Port")
if configPort != "" {
if i, err := strconv.Atoi(configPort); err == nil {
port = i
}
}
addr = net.JoinHostPort(host, strconv.Itoa(port))
return
}
func (c *command) setAuthFromEndpoint() error {
var err error
c.auth, err = DefaultAuthBuilder(c.endpoint.User)
return err
}
func endpointToCommand(cmd string, ep *transport.Endpoint) string {
return fmt.Sprintf("%s '%s'", cmd, ep.Path)
}
func overrideConfig(overrides *ssh.ClientConfig, c *ssh.ClientConfig) {
if overrides == nil {
return
}
t := reflect.TypeOf(*c)
vc := reflect.ValueOf(c).Elem()
vo := reflect.ValueOf(overrides).Elem()
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
vcf := vc.FieldByName(f.Name)
vof := vo.FieldByName(f.Name)
vcf.Set(vof)
}
*c = vc.Interface().(ssh.ClientConfig)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/prune.go
================================================
package git
import (
"errors"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
)
type PruneHandler func(unreferencedObjectHash plumbing.Hash) error
type PruneOptions struct {
// OnlyObjectsOlderThan if set to non-zero value
// selects only objects older than the time provided.
OnlyObjectsOlderThan time.Time
// Handler is called on matching objects
Handler PruneHandler
}
var ErrLooseObjectsNotSupported = errors.New("loose objects not supported")
// DeleteObject deletes an object from a repository.
// The type conveniently matches PruneHandler.
func (r *Repository) DeleteObject(hash plumbing.Hash) error {
los, ok := r.Storer.(storer.LooseObjectStorer)
if !ok {
return ErrLooseObjectsNotSupported
}
return los.DeleteLooseObject(hash)
}
func (r *Repository) Prune(opt PruneOptions) error {
los, ok := r.Storer.(storer.LooseObjectStorer)
if !ok {
return ErrLooseObjectsNotSupported
}
pw := newObjectWalker(r.Storer)
err := pw.walkAllRefs()
if err != nil {
return err
}
// Now walk all (loose) objects in storage.
return los.ForEachObjectHash(func(hash plumbing.Hash) error {
// Get out if we have seen this object.
if pw.isSeen(hash) {
return nil
}
// Otherwise it is a candidate for pruning.
// Check out for too new objects next.
if !opt.OnlyObjectsOlderThan.IsZero() {
// Errors here are non-fatal. The object may be e.g. packed.
// Or concurrently deleted. Skip such objects.
t, err := los.LooseObjectTime(hash)
if err != nil {
return nil
}
// Skip too new objects.
if !t.Before(opt.OnlyObjectsOlderThan) {
return nil
}
}
return opt.Handler(hash)
})
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/remote.go
================================================
package git
import (
"context"
"errors"
"fmt"
"io"
"strings"
"time"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/protocol/packp"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/capability"
"github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband"
"github.com/go-git/go-git/v5/plumbing/revlist"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/plumbing/transport"
"github.com/go-git/go-git/v5/plumbing/transport/client"
"github.com/go-git/go-git/v5/storage"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-git/go-git/v5/storage/memory"
"github.com/go-git/go-git/v5/utils/ioutil"
)
var (
NoErrAlreadyUpToDate = errors.New("already up-to-date")
ErrDeleteRefNotSupported = errors.New("server does not support delete-refs")
ErrForceNeeded = errors.New("some refs were not updated")
ErrExactSHA1NotSupported = errors.New("server does not support exact SHA1 refspec")
ErrEmptyUrls = errors.New("URLs cannot be empty")
)
type NoMatchingRefSpecError struct {
refSpec config.RefSpec
}
func (e NoMatchingRefSpecError) Error() string {
return fmt.Sprintf("couldn't find remote ref %q", e.refSpec.Src())
}
func (e NoMatchingRefSpecError) Is(target error) bool {
_, ok := target.(NoMatchingRefSpecError)
return ok
}
const (
// This describes the maximum number of commits to walk when
// computing the haves to send to a server, for each ref in the
// repo containing this remote, when not using the multi-ack
// protocol. Setting this to 0 means there is no limit.
maxHavesToVisitPerRef = 100
// peeledSuffix is the suffix used to build peeled reference names.
peeledSuffix = "^{}"
)
// Remote represents a connection to a remote repository.
type Remote struct {
c *config.RemoteConfig
s storage.Storer
}
// NewRemote creates a new Remote.
// The intended purpose is to use the Remote for tasks such as listing remote references (like using git ls-remote).
// Otherwise Remotes should be created via the use of a Repository.
func NewRemote(s storage.Storer, c *config.RemoteConfig) *Remote {
return &Remote{s: s, c: c}
}
// Config returns the RemoteConfig object used to instantiate this Remote.
func (r *Remote) Config() *config.RemoteConfig {
return r.c
}
func (r *Remote) String() string {
var fetch, push string
if len(r.c.URLs) > 0 {
fetch = r.c.URLs[0]
push = r.c.URLs[len(r.c.URLs)-1]
}
return fmt.Sprintf("%s\t%s (fetch)\n%[1]s\t%[3]s (push)", r.c.Name, fetch, push)
}
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if the
// remote was already up-to-date.
func (r *Remote) Push(o *PushOptions) error {
return r.PushContext(context.Background(), o)
}
// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
if err := o.Validate(); err != nil {
return err
}
if o.RemoteName != r.c.Name {
return fmt.Errorf("remote names don't match: %s != %s", o.RemoteName, r.c.Name)
}
if o.RemoteURL == "" && len(r.c.URLs) > 0 {
o.RemoteURL = r.c.URLs[len(r.c.URLs)-1]
}
s, err := newSendPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
if err != nil {
return err
}
defer ioutil.CheckClose(s, &err)
ar, err := s.AdvertisedReferencesContext(ctx)
if err != nil {
return err
}
remoteRefs, err := ar.AllReferences()
if err != nil {
return err
}
if err := r.checkRequireRemoteRefs(o.RequireRemoteRefs, remoteRefs); err != nil {
return err
}
isDelete := false
allDelete := true
for _, rs := range o.RefSpecs {
if rs.IsDelete() {
isDelete = true
} else {
allDelete = false
}
if isDelete && !allDelete {
break
}
}
if isDelete && !ar.Capabilities.Supports(capability.DeleteRefs) {
return ErrDeleteRefNotSupported
}
if o.Force {
for i := 0; i < len(o.RefSpecs); i++ {
rs := &o.RefSpecs[i]
if !rs.IsForceUpdate() && !rs.IsDelete() {
o.RefSpecs[i] = config.RefSpec("+" + rs.String())
}
}
}
localRefs, err := r.references()
if err != nil {
return err
}
req, err := r.newReferenceUpdateRequest(o, localRefs, remoteRefs, ar)
if err != nil {
return err
}
if len(req.Commands) == 0 {
return NoErrAlreadyUpToDate
}
objects := objectsToPush(req.Commands)
haves, err := referencesToHashes(remoteRefs)
if err != nil {
return err
}
stop, err := r.s.Shallow()
if err != nil {
return err
}
// if we have shallow we should include this as part of the objects that
// we are aware.
haves = append(haves, stop...)
var hashesToPush []plumbing.Hash
// Avoid the expensive revlist operation if we're only doing deletes.
if !allDelete {
if url.IsLocalEndpoint(o.RemoteURL) {
// If we're are pushing to a local repo, it might be much
// faster to use a local storage layer to get the commits
// to ignore, when calculating the object revlist.
localStorer := filesystem.NewStorage(
osfs.New(o.RemoteURL), cache.NewObjectLRUDefault())
hashesToPush, err = revlist.ObjectsWithStorageForIgnores(
r.s, localStorer, objects, haves)
} else {
hashesToPush, err = revlist.Objects(r.s, objects, haves)
}
if err != nil {
return err
}
}
if len(hashesToPush) == 0 {
allDelete = true
for _, command := range req.Commands {
if command.Action() != packp.Delete {
allDelete = false
break
}
}
}
rs, err := pushHashes(ctx, s, r.s, req, hashesToPush, r.useRefDeltas(ar), allDelete)
if err != nil {
return err
}
if rs != nil {
if err = rs.Error(); err != nil {
return err
}
}
return r.updateRemoteReferenceStorage(req)
}
func (r *Remote) useRefDeltas(ar *packp.AdvRefs) bool {
return !ar.Capabilities.Supports(capability.OFSDelta)
}
func (r *Remote) addReachableTags(localRefs []*plumbing.Reference, remoteRefs storer.ReferenceStorer, req *packp.ReferenceUpdateRequest) error {
tags := make(map[plumbing.Reference]struct{})
// get a list of all tags locally
for _, ref := range localRefs {
if strings.HasPrefix(string(ref.Name()), "refs/tags") {
tags[*ref] = struct{}{}
}
}
remoteRefIter, err := remoteRefs.IterReferences()
if err != nil {
return err
}
// remove any that are already on the remote
if err := remoteRefIter.ForEach(func(reference *plumbing.Reference) error {
delete(tags, *reference)
return nil
}); err != nil {
return err
}
for tag := range tags {
tagObject, err := object.GetObject(r.s, tag.Hash())
var tagCommit *object.Commit
if err != nil {
return fmt.Errorf("get tag object: %w", err)
}
if tagObject.Type() != plumbing.TagObject {
continue
}
annotatedTag, ok := tagObject.(*object.Tag)
if !ok {
return errors.New("could not get annotated tag object")
}
tagCommit, err = object.GetCommit(r.s, annotatedTag.Target)
if err != nil {
return fmt.Errorf("get annotated tag commit: %w", err)
}
// only include tags that are reachable from one of the refs
// already being pushed
for _, cmd := range req.Commands {
if tag.Name() == cmd.Name {
continue
}
if strings.HasPrefix(cmd.Name.String(), "refs/tags") {
continue
}
c, err := object.GetCommit(r.s, cmd.New)
if err != nil {
return fmt.Errorf("get commit %v: %w", cmd.Name, err)
}
if isAncestor, err := tagCommit.IsAncestor(c); err == nil && isAncestor {
req.Commands = append(req.Commands, &packp.Command{Name: tag.Name(), New: tag.Hash()})
}
}
}
return nil
}
func (r *Remote) newReferenceUpdateRequest(
o *PushOptions,
localRefs []*plumbing.Reference,
remoteRefs storer.ReferenceStorer,
ar *packp.AdvRefs,
) (*packp.ReferenceUpdateRequest, error) {
req := packp.NewReferenceUpdateRequestFromCapabilities(ar.Capabilities)
if o.Progress != nil {
req.Progress = o.Progress
if ar.Capabilities.Supports(capability.Sideband64k) {
_ = req.Capabilities.Set(capability.Sideband64k)
} else if ar.Capabilities.Supports(capability.Sideband) {
_ = req.Capabilities.Set(capability.Sideband)
}
}
if ar.Capabilities.Supports(capability.PushOptions) {
_ = req.Capabilities.Set(capability.PushOptions)
for k, v := range o.Options {
req.Options = append(req.Options, &packp.Option{Key: k, Value: v})
}
}
if o.Atomic && ar.Capabilities.Supports(capability.Atomic) {
_ = req.Capabilities.Set(capability.Atomic)
}
if err := r.addReferencesToUpdate(o.RefSpecs, localRefs, remoteRefs, req, o.Prune, o.ForceWithLease); err != nil {
return nil, err
}
if o.FollowTags {
if err := r.addReachableTags(localRefs, remoteRefs, req); err != nil {
return nil, err
}
}
return req, nil
}
func (r *Remote) updateRemoteReferenceStorage(
req *packp.ReferenceUpdateRequest,
) error {
for _, spec := range r.c.Fetch {
for _, c := range req.Commands {
if !spec.Match(c.Name) {
continue
}
local := spec.Dst(c.Name)
ref := plumbing.NewHashReference(local, c.New)
switch c.Action() {
case packp.Create, packp.Update:
if err := r.s.SetReference(ref); err != nil {
return err
}
case packp.Delete:
if err := r.s.RemoveReference(local); err != nil {
return err
}
}
}
}
return nil
}
// FetchContext fetches references along with the objects necessary to complete
// their histories.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (r *Remote) FetchContext(ctx context.Context, o *FetchOptions) error {
_, err := r.fetch(ctx, o)
return err
}
// Fetch fetches references along with the objects necessary to complete their
// histories.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
func (r *Remote) Fetch(o *FetchOptions) error {
return r.FetchContext(context.Background(), o)
}
func (r *Remote) fetch(ctx context.Context, o *FetchOptions) (sto storer.ReferenceStorer, err error) {
if o.RemoteName == "" {
o.RemoteName = r.c.Name
}
if err = o.Validate(); err != nil {
return nil, err
}
if len(o.RefSpecs) == 0 {
o.RefSpecs = r.c.Fetch
}
if o.RemoteURL == "" {
o.RemoteURL = r.c.URLs[0]
}
s, err := newUploadPackSession(o.RemoteURL, o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
if err != nil {
return nil, err
}
defer ioutil.CheckClose(s, &err)
ar, err := s.AdvertisedReferencesContext(ctx)
if err != nil {
return nil, err
}
req, err := r.newUploadPackRequest(o, ar)
if err != nil {
return nil, err
}
if err := r.isSupportedRefSpec(o.RefSpecs, ar); err != nil {
return nil, err
}
remoteRefs, err := ar.AllReferences()
if err != nil {
return nil, err
}
localRefs, err := r.references()
if err != nil {
return nil, err
}
refs, specToRefs, err := calculateRefs(o.RefSpecs, remoteRefs, o.Tags)
if err != nil {
return nil, err
}
if !req.Depth.IsZero() {
req.Shallows, err = r.s.Shallow()
if err != nil {
return nil, fmt.Errorf("existing checkout is not shallow")
}
}
req.Wants, err = getWants(r.s, refs, o.Depth)
if len(req.Wants) > 0 {
req.Haves, err = getHaves(localRefs, remoteRefs, r.s, o.Depth)
if err != nil {
return nil, err
}
if err = r.fetchPack(ctx, o, s, req); err != nil {
return nil, err
}
}
var updatedPrune bool
if o.Prune {
updatedPrune, err = r.pruneRemotes(o.RefSpecs, localRefs, remoteRefs)
if err != nil {
return nil, err
}
}
updated, err := r.updateLocalReferenceStorage(o.RefSpecs, refs, remoteRefs, specToRefs, o.Tags, o.Force)
if err != nil {
return nil, err
}
if !updated {
updated, err = depthChanged(req.Shallows, r.s)
if err != nil {
return nil, fmt.Errorf("error checking depth change: %v", err)
}
}
if !updated && !updatedPrune {
// No references updated, but may have fetched new objects, check if we now have any of our wants
for _, hash := range req.Wants {
exists, _ := objectExists(r.s, hash)
if exists {
updated = true
break
}
}
if !updated {
return remoteRefs, NoErrAlreadyUpToDate
}
}
return remoteRefs, nil
}
func depthChanged(before []plumbing.Hash, s storage.Storer) (bool, error) {
after, err := s.Shallow()
if err != nil {
return false, err
}
if len(before) != len(after) {
return true, nil
}
bm := make(map[plumbing.Hash]bool, len(before))
for _, b := range before {
bm[b] = true
}
for _, a := range after {
if _, ok := bm[a]; !ok {
return true, nil
}
}
return false, nil
}
func newUploadPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.UploadPackSession, error) {
c, ep, err := newClient(url, insecure, cabundle, proxyOpts)
if err != nil {
return nil, err
}
return c.NewUploadPackSession(ep, auth)
}
func newSendPackSession(url string, auth transport.AuthMethod, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.ReceivePackSession, error) {
c, ep, err := newClient(url, insecure, cabundle, proxyOpts)
if err != nil {
return nil, err
}
return c.NewReceivePackSession(ep, auth)
}
func newClient(url string, insecure bool, cabundle []byte, proxyOpts transport.ProxyOptions) (transport.Transport, *transport.Endpoint, error) {
ep, err := transport.NewEndpoint(url)
if err != nil {
return nil, nil, err
}
ep.InsecureSkipTLS = insecure
ep.CaBundle = cabundle
ep.Proxy = proxyOpts
c, err := client.NewClient(ep)
if err != nil {
return nil, nil, err
}
return c, ep, err
}
func (r *Remote) fetchPack(ctx context.Context, o *FetchOptions, s transport.UploadPackSession,
req *packp.UploadPackRequest) (err error) {
reader, err := s.UploadPack(ctx, req)
if err != nil {
if errors.Is(err, transport.ErrEmptyUploadPackRequest) {
// XXX: no packfile provided, everything is up-to-date.
return nil
}
return err
}
defer ioutil.CheckClose(reader, &err)
if err = r.updateShallow(o, reader); err != nil {
return err
}
if err = packfile.UpdateObjectStorage(r.s,
buildSidebandIfSupported(req.Capabilities, reader, o.Progress),
); err != nil {
return err
}
return err
}
func (r *Remote) pruneRemotes(specs []config.RefSpec, localRefs []*plumbing.Reference, remoteRefs memory.ReferenceStorage) (bool, error) {
var updatedPrune bool
for _, spec := range specs {
rev := spec.Reverse()
for _, ref := range localRefs {
if !rev.Match(ref.Name()) {
continue
}
_, err := remoteRefs.Reference(rev.Dst(ref.Name()))
if errors.Is(err, plumbing.ErrReferenceNotFound) {
updatedPrune = true
err := r.s.RemoveReference(ref.Name())
if err != nil {
return false, err
}
}
}
}
return updatedPrune, nil
}
func (r *Remote) addReferencesToUpdate(
refspecs []config.RefSpec,
localRefs []*plumbing.Reference,
remoteRefs storer.ReferenceStorer,
req *packp.ReferenceUpdateRequest,
prune bool,
forceWithLease *ForceWithLease,
) error {
// This references dictionary will be used to search references by name.
refsDict := make(map[string]*plumbing.Reference)
for _, ref := range localRefs {
refsDict[ref.Name().String()] = ref
}
for _, rs := range refspecs {
if rs.IsDelete() {
if err := r.deleteReferences(rs, remoteRefs, refsDict, req, false); err != nil {
return err
}
} else {
err := r.addOrUpdateReferences(rs, localRefs, refsDict, remoteRefs, req, forceWithLease)
if err != nil {
return err
}
if prune {
if err := r.deleteReferences(rs, remoteRefs, refsDict, req, true); err != nil {
return err
}
}
}
}
return nil
}
func (r *Remote) addOrUpdateReferences(
rs config.RefSpec,
localRefs []*plumbing.Reference,
refsDict map[string]*plumbing.Reference,
remoteRefs storer.ReferenceStorer,
req *packp.ReferenceUpdateRequest,
forceWithLease *ForceWithLease,
) error {
// If it is not a wildcard refspec we can directly search for the reference
// in the references dictionary.
if !rs.IsWildcard() {
ref, ok := refsDict[rs.Src()]
if !ok {
commit, err := object.GetCommit(r.s, plumbing.NewHash(rs.Src()))
if err == nil {
return r.addCommit(rs, remoteRefs, commit.Hash, req)
}
return nil
}
return r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req, forceWithLease)
}
for _, ref := range localRefs {
err := r.addReferenceIfRefSpecMatches(rs, remoteRefs, ref, req, forceWithLease)
if err != nil {
return err
}
}
return nil
}
func (r *Remote) deleteReferences(rs config.RefSpec,
remoteRefs storer.ReferenceStorer,
refsDict map[string]*plumbing.Reference,
req *packp.ReferenceUpdateRequest,
prune bool) error {
iter, err := remoteRefs.IterReferences()
if err != nil {
return err
}
return iter.ForEach(func(ref *plumbing.Reference) error {
if ref.Type() != plumbing.HashReference {
return nil
}
if prune {
rs := rs.Reverse()
if !rs.Match(ref.Name()) {
return nil
}
if _, ok := refsDict[rs.Dst(ref.Name()).String()]; ok {
return nil
}
} else if rs.Dst("") != ref.Name() {
return nil
}
cmd := &packp.Command{
Name: ref.Name(),
Old: ref.Hash(),
New: plumbing.ZeroHash,
}
req.Commands = append(req.Commands, cmd)
return nil
})
}
func (r *Remote) addCommit(rs config.RefSpec,
remoteRefs storer.ReferenceStorer, localCommit plumbing.Hash,
req *packp.ReferenceUpdateRequest) error {
if rs.IsWildcard() {
return errors.New("can't use wildcard together with hash refspecs")
}
cmd := &packp.Command{
Name: rs.Dst(""),
Old: plumbing.ZeroHash,
New: localCommit,
}
remoteRef, err := remoteRefs.Reference(cmd.Name)
if err == nil {
if remoteRef.Type() != plumbing.HashReference {
// TODO: check actual git behavior here
return nil
}
cmd.Old = remoteRef.Hash()
} else if err != plumbing.ErrReferenceNotFound {
return err
}
if cmd.Old == cmd.New {
return nil
}
if !rs.IsForceUpdate() {
if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil {
return err
}
}
req.Commands = append(req.Commands, cmd)
return nil
}
func (r *Remote) addReferenceIfRefSpecMatches(rs config.RefSpec,
remoteRefs storer.ReferenceStorer, localRef *plumbing.Reference,
req *packp.ReferenceUpdateRequest, forceWithLease *ForceWithLease) error {
if localRef.Type() != plumbing.HashReference {
return nil
}
if !rs.Match(localRef.Name()) {
return nil
}
cmd := &packp.Command{
Name: rs.Dst(localRef.Name()),
Old: plumbing.ZeroHash,
New: localRef.Hash(),
}
remoteRef, err := remoteRefs.Reference(cmd.Name)
if err == nil {
if remoteRef.Type() != plumbing.HashReference {
// TODO: check actual git behavior here
return nil
}
cmd.Old = remoteRef.Hash()
} else if err != plumbing.ErrReferenceNotFound {
return err
}
if cmd.Old == cmd.New {
return nil
}
if forceWithLease != nil {
if err = r.checkForceWithLease(localRef, cmd, forceWithLease); err != nil {
return err
}
} else if !rs.IsForceUpdate() {
if err := checkFastForwardUpdate(r.s, remoteRefs, cmd); err != nil {
return err
}
}
req.Commands = append(req.Commands, cmd)
return nil
}
func (r *Remote) checkForceWithLease(localRef *plumbing.Reference, cmd *packp.Command, forceWithLease *ForceWithLease) error {
remotePrefix := fmt.Sprintf("refs/remotes/%s/", r.Config().Name)
ref, err := storer.ResolveReference(
r.s,
plumbing.ReferenceName(remotePrefix+strings.Replace(localRef.Name().String(), "refs/heads/", "", -1)))
if err != nil {
return err
}
if forceWithLease.RefName.String() == "" || (forceWithLease.RefName == cmd.Name) {
expectedOID := ref.Hash()
if !forceWithLease.Hash.IsZero() {
expectedOID = forceWithLease.Hash
}
if cmd.Old != expectedOID {
return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
}
}
return nil
}
func (r *Remote) references() ([]*plumbing.Reference, error) {
var localRefs []*plumbing.Reference
iter, err := r.s.IterReferences()
if err != nil {
return nil, err
}
for {
ref, err := iter.Next()
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
localRefs = append(localRefs, ref)
}
return localRefs, nil
}
func getRemoteRefsFromStorer(remoteRefStorer storer.ReferenceStorer) (
map[plumbing.Hash]bool, error) {
remoteRefs := map[plumbing.Hash]bool{}
iter, err := remoteRefStorer.IterReferences()
if err != nil {
return nil, err
}
err = iter.ForEach(func(ref *plumbing.Reference) error {
if ref.Type() != plumbing.HashReference {
return nil
}
remoteRefs[ref.Hash()] = true
return nil
})
if err != nil {
return nil, err
}
return remoteRefs, nil
}
// getHavesFromRef populates the given `haves` map with the given
// reference, and up to `maxHavesToVisitPerRef` ancestor commits.
func getHavesFromRef(
ref *plumbing.Reference,
remoteRefs map[plumbing.Hash]bool,
s storage.Storer,
haves map[plumbing.Hash]bool,
depth int,
) error {
h := ref.Hash()
if haves[h] {
return nil
}
commit, err := object.GetCommit(s, h)
if err != nil {
if !errors.Is(err, plumbing.ErrObjectNotFound) {
// Ignore the error if this isn't a commit.
haves[ref.Hash()] = true
}
return nil
}
// Until go-git supports proper commit negotiation during an
// upload pack request, include up to `maxHavesToVisitPerRef`
// commits from the history of each ref.
walker := object.NewCommitPreorderIter(commit, haves, nil)
toVisit := maxHavesToVisitPerRef
// But only need up to the requested depth
if depth > 0 && depth < maxHavesToVisitPerRef {
toVisit = depth
}
// It is safe to ignore any error here as we are just trying to find the references that we already have
// An example of a legitimate failure is we have a shallow clone and don't have the previous commit(s)
_ = walker.ForEach(func(c *object.Commit) error {
haves[c.Hash] = true
toVisit--
// If toVisit starts out at 0 (indicating there is no
// max), then it will be negative here and we won't stop
// early.
if toVisit == 0 || remoteRefs[c.Hash] {
return storer.ErrStop
}
return nil
})
return nil
}
func getHaves(
localRefs []*plumbing.Reference,
remoteRefStorer storer.ReferenceStorer,
s storage.Storer,
depth int,
) ([]plumbing.Hash, error) {
haves := map[plumbing.Hash]bool{}
// Build a map of all the remote references, to avoid loading too
// many parent commits for references we know don't need to be
// transferred.
remoteRefs, err := getRemoteRefsFromStorer(remoteRefStorer)
if err != nil {
return nil, err
}
for _, ref := range localRefs {
if haves[ref.Hash()] {
continue
}
if ref.Type() != plumbing.HashReference {
continue
}
err = getHavesFromRef(ref, remoteRefs, s, haves, depth)
if err != nil {
return nil, err
}
}
var result []plumbing.Hash
for h := range haves {
result = append(result, h)
}
return result, nil
}
const refspecAllTags = "+refs/tags/*:refs/tags/*"
func calculateRefs(
spec []config.RefSpec,
remoteRefs storer.ReferenceStorer,
tagMode TagMode,
) (memory.ReferenceStorage, [][]*plumbing.Reference, error) {
if tagMode == AllTags {
spec = append(spec, refspecAllTags)
}
refs := make(memory.ReferenceStorage)
// list of references matched for each spec
specToRefs := make([][]*plumbing.Reference, len(spec))
for i := range spec {
var err error
specToRefs[i], err = doCalculateRefs(spec[i], remoteRefs, refs)
if err != nil {
return nil, nil, err
}
}
return refs, specToRefs, nil
}
func doCalculateRefs(
s config.RefSpec,
remoteRefs storer.ReferenceStorer,
refs memory.ReferenceStorage,
) ([]*plumbing.Reference, error) {
var refList []*plumbing.Reference
if s.IsExactSHA1() {
ref := plumbing.NewHashReference(s.Dst(""), plumbing.NewHash(s.Src()))
refList = append(refList, ref)
return refList, refs.SetReference(ref)
}
var matched bool
onMatched := func(ref *plumbing.Reference) error {
if ref.Type() == plumbing.SymbolicReference {
target, err := storer.ResolveReference(remoteRefs, ref.Name())
if err != nil {
return err
}
ref = plumbing.NewHashReference(ref.Name(), target.Hash())
}
if ref.Type() != plumbing.HashReference {
return nil
}
matched = true
refList = append(refList, ref)
return refs.SetReference(ref)
}
var ret error
if s.IsWildcard() {
iter, err := remoteRefs.IterReferences()
if err != nil {
return nil, err
}
ret = iter.ForEach(func(ref *plumbing.Reference) error {
if !s.Match(ref.Name()) {
return nil
}
return onMatched(ref)
})
} else {
var resolvedRef *plumbing.Reference
src := s.Src()
resolvedRef, ret = expand_ref(remoteRefs, plumbing.ReferenceName(src))
if ret == nil {
ret = onMatched(resolvedRef)
}
}
if !matched && !s.IsWildcard() {
return nil, NoMatchingRefSpecError{refSpec: s}
}
return refList, ret
}
func getWants(localStorer storage.Storer, refs memory.ReferenceStorage, depth int) ([]plumbing.Hash, error) {
// If depth is anything other than 1 and the repo has shallow commits then just because we have the commit
// at the reference doesn't mean that we don't still need to fetch the parents
shallow := false
if depth != 1 {
if s, _ := localStorer.Shallow(); len(s) > 0 {
shallow = true
}
}
wants := map[plumbing.Hash]bool{}
for _, ref := range refs {
hash := ref.Hash()
exists, err := objectExists(localStorer, ref.Hash())
if err != nil {
return nil, err
}
if !exists || shallow {
wants[hash] = true
}
}
var result []plumbing.Hash
for h := range wants {
result = append(result, h)
}
return result, nil
}
func objectExists(s storer.EncodedObjectStorer, h plumbing.Hash) (bool, error) {
_, err := s.EncodedObject(plumbing.AnyObject, h)
if err == plumbing.ErrObjectNotFound {
return false, nil
}
return true, err
}
func checkFastForwardUpdate(s storer.EncodedObjectStorer, remoteRefs storer.ReferenceStorer, cmd *packp.Command) error {
if cmd.Old == plumbing.ZeroHash {
_, err := remoteRefs.Reference(cmd.Name)
if err == plumbing.ErrReferenceNotFound {
return nil
}
if err != nil {
return err
}
return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
}
ff, err := isFastForward(s, cmd.Old, cmd.New, nil)
if err != nil {
return err
}
if !ff {
return fmt.Errorf("non-fast-forward update: %s", cmd.Name.String())
}
return nil
}
func isFastForward(s storer.EncodedObjectStorer, old, new plumbing.Hash, earliestShallow *plumbing.Hash) (bool, error) {
c, err := object.GetCommit(s, new)
if err != nil {
return false, err
}
parentsToIgnore := []plumbing.Hash{}
if earliestShallow != nil {
earliestCommit, err := object.GetCommit(s, *earliestShallow)
if err != nil {
return false, err
}
parentsToIgnore = earliestCommit.ParentHashes
}
found := false
// stop iterating at the earliest shallow commit, ignoring its parents
// note: when pull depth is smaller than the number of new changes on the remote, this fails due to missing parents.
// as far as i can tell, without the commits in-between the shallow pull and the earliest shallow, there's no
// real way of telling whether it will be a fast-forward merge.
iter := object.NewCommitPreorderIter(c, nil, parentsToIgnore)
err = iter.ForEach(func(c *object.Commit) error {
if c.Hash != old {
return nil
}
found = true
return storer.ErrStop
})
return found, err
}
func (r *Remote) newUploadPackRequest(o *FetchOptions,
ar *packp.AdvRefs) (*packp.UploadPackRequest, error) {
req := packp.NewUploadPackRequestFromCapabilities(ar.Capabilities)
if o.Depth != 0 {
req.Depth = packp.DepthCommits(o.Depth)
if err := req.Capabilities.Set(capability.Shallow); err != nil {
return nil, err
}
}
if o.Progress == nil && ar.Capabilities.Supports(capability.NoProgress) {
if err := req.Capabilities.Set(capability.NoProgress); err != nil {
return nil, err
}
}
isWildcard := true
for _, s := range o.RefSpecs {
if !s.IsWildcard() {
isWildcard = false
break
}
}
if isWildcard && o.Tags == TagFollowing && ar.Capabilities.Supports(capability.IncludeTag) {
if err := req.Capabilities.Set(capability.IncludeTag); err != nil {
return nil, err
}
}
return req, nil
}
func (r *Remote) isSupportedRefSpec(refs []config.RefSpec, ar *packp.AdvRefs) error {
var containsIsExact bool
for _, ref := range refs {
if ref.IsExactSHA1() {
containsIsExact = true
}
}
if !containsIsExact {
return nil
}
if ar.Capabilities.Supports(capability.AllowReachableSHA1InWant) ||
ar.Capabilities.Supports(capability.AllowTipSHA1InWant) {
return nil
}
return ErrExactSHA1NotSupported
}
func buildSidebandIfSupported(l *capability.List, reader io.Reader, p sideband.Progress) io.Reader {
var t sideband.Type
switch {
case l.Supports(capability.Sideband):
t = sideband.Sideband
case l.Supports(capability.Sideband64k):
t = sideband.Sideband64k
default:
return reader
}
d := sideband.NewDemuxer(t, reader)
d.Progress = p
return d
}
func (r *Remote) updateLocalReferenceStorage(
specs []config.RefSpec,
fetchedRefs, remoteRefs memory.ReferenceStorage,
specToRefs [][]*plumbing.Reference,
tagMode TagMode,
force bool,
) (updated bool, err error) {
isWildcard := true
forceNeeded := false
for i, spec := range specs {
if !spec.IsWildcard() {
isWildcard = false
}
for _, ref := range specToRefs[i] {
if ref.Type() != plumbing.HashReference {
continue
}
localName := spec.Dst(ref.Name())
// If localName doesn't start with "refs/" then treat as a branch.
if !strings.HasPrefix(localName.String(), "refs/") {
localName = plumbing.NewBranchReferenceName(localName.String())
}
old, _ := storer.ResolveReference(r.s, localName)
new := plumbing.NewHashReference(localName, ref.Hash())
// If the ref exists locally as a non-tag and force is not
// specified, only update if the new ref is an ancestor of the old
if old != nil && !old.Name().IsTag() && !force && !spec.IsForceUpdate() {
ff, err := isFastForward(r.s, old.Hash(), new.Hash(), nil)
if err != nil {
return updated, err
}
if !ff {
forceNeeded = true
continue
}
}
refUpdated, err := checkAndUpdateReferenceStorerIfNeeded(r.s, new, old)
if err != nil {
return updated, err
}
if refUpdated {
updated = true
}
}
}
if tagMode == NoTags {
return updated, nil
}
tags := fetchedRefs
if isWildcard {
tags = remoteRefs
}
tagUpdated, err := r.buildFetchedTags(tags)
if err != nil {
return updated, err
}
if tagUpdated {
updated = true
}
if forceNeeded {
err = ErrForceNeeded
}
return
}
func (r *Remote) buildFetchedTags(refs memory.ReferenceStorage) (updated bool, err error) {
for _, ref := range refs {
if !ref.Name().IsTag() {
continue
}
_, err := r.s.EncodedObject(plumbing.AnyObject, ref.Hash())
if err == plumbing.ErrObjectNotFound {
continue
}
if err != nil {
return false, err
}
refUpdated, err := updateReferenceStorerIfNeeded(r.s, ref)
if err != nil {
return updated, err
}
if refUpdated {
updated = true
}
}
return
}
// List the references on the remote repository.
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects to the
// transport operations.
func (r *Remote) ListContext(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) {
return r.list(ctx, o)
}
func (r *Remote) List(o *ListOptions) (rfs []*plumbing.Reference, err error) {
timeout := o.Timeout
// Default to the old hardcoded 10s value if a timeout is not explicitly set.
if timeout == 0 {
timeout = 10
}
if timeout < 0 {
return nil, fmt.Errorf("invalid timeout: %d", timeout)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
defer cancel()
return r.ListContext(ctx, o)
}
func (r *Remote) list(ctx context.Context, o *ListOptions) (rfs []*plumbing.Reference, err error) {
if r.c == nil || len(r.c.URLs) == 0 {
return nil, ErrEmptyUrls
}
s, err := newUploadPackSession(r.c.URLs[0], o.Auth, o.InsecureSkipTLS, o.CABundle, o.ProxyOptions)
if err != nil {
return nil, err
}
defer ioutil.CheckClose(s, &err)
ar, err := s.AdvertisedReferencesContext(ctx)
if err != nil {
return nil, err
}
allRefs, err := ar.AllReferences()
if err != nil {
return nil, err
}
refs, err := allRefs.IterReferences()
if err != nil {
return nil, err
}
var resultRefs []*plumbing.Reference
if o.PeelingOption == AppendPeeled || o.PeelingOption == IgnorePeeled {
err = refs.ForEach(func(ref *plumbing.Reference) error {
resultRefs = append(resultRefs, ref)
return nil
})
if err != nil {
return nil, err
}
}
if o.PeelingOption == AppendPeeled || o.PeelingOption == OnlyPeeled {
for k, v := range ar.Peeled {
resultRefs = append(resultRefs, plumbing.NewReferenceFromStrings(k+"^{}", v.String()))
}
}
return resultRefs, nil
}
func objectsToPush(commands []*packp.Command) []plumbing.Hash {
objects := make([]plumbing.Hash, 0, len(commands))
for _, cmd := range commands {
if cmd.New == plumbing.ZeroHash {
continue
}
objects = append(objects, cmd.New)
}
return objects
}
func referencesToHashes(refs storer.ReferenceStorer) ([]plumbing.Hash, error) {
iter, err := refs.IterReferences()
if err != nil {
return nil, err
}
var hs []plumbing.Hash
err = iter.ForEach(func(ref *plumbing.Reference) error {
if ref.Type() != plumbing.HashReference {
return nil
}
hs = append(hs, ref.Hash())
return nil
})
if err != nil {
return nil, err
}
return hs, nil
}
func pushHashes(
ctx context.Context,
sess transport.ReceivePackSession,
s storage.Storer,
req *packp.ReferenceUpdateRequest,
hs []plumbing.Hash,
useRefDeltas bool,
allDelete bool,
) (*packp.ReportStatus, error) {
rd, wr := io.Pipe()
config, err := s.Config()
if err != nil {
return nil, err
}
// Set buffer size to 1 so the error message can be written when
// ReceivePack fails. Otherwise the goroutine will be blocked writing
// to the channel.
done := make(chan error, 1)
if !allDelete {
req.Packfile = rd
go func() {
e := packfile.NewEncoder(wr, s, useRefDeltas)
if _, err := e.Encode(hs, config.Pack.Window); err != nil {
done <- wr.CloseWithError(err)
return
}
done <- wr.Close()
}()
} else {
close(done)
}
rs, err := sess.ReceivePack(ctx, req)
if err != nil {
// close the pipe to unlock encode write
_ = rd.Close()
return nil, err
}
if err := <-done; err != nil {
return nil, err
}
return rs, nil
}
func (r *Remote) updateShallow(o *FetchOptions, resp *packp.UploadPackResponse) error {
if o.Depth == 0 || len(resp.Shallows) == 0 {
return nil
}
shallows, err := r.s.Shallow()
if err != nil {
return err
}
outer:
for _, s := range resp.Shallows {
for _, oldS := range shallows {
if s == oldS {
continue outer
}
}
shallows = append(shallows, s)
}
return r.s.SetShallow(shallows)
}
func (r *Remote) checkRequireRemoteRefs(requires []config.RefSpec, remoteRefs storer.ReferenceStorer) error {
for _, require := range requires {
if require.IsWildcard() {
return fmt.Errorf("wildcards not supported in RequireRemoteRefs, got %s", require.String())
}
name := require.Dst("")
remote, err := remoteRefs.Reference(name)
if err != nil {
return fmt.Errorf("remote ref %s required to be %s but is absent", name.String(), require.Src())
}
var requireHash string
if require.IsExactSHA1() {
requireHash = require.Src()
} else {
target, err := storer.ResolveReference(remoteRefs, plumbing.ReferenceName(require.Src()))
if err != nil {
return fmt.Errorf("could not resolve ref %s in RequireRemoteRefs", require.Src())
}
requireHash = target.Hash().String()
}
if remote.Hash().String() != requireHash {
return fmt.Errorf("remote ref %s required to be %s but is %s", name.String(), requireHash, remote.Hash().String())
}
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/repository.go
================================================
package git
import (
"bytes"
"context"
"crypto"
"encoding/hex"
"errors"
"fmt"
"io"
"os"
"path"
"path/filepath"
"strings"
"time"
"dario.cat/mergo"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/osfs"
"github.com/go-git/go-billy/v5/util"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/internal/path_util"
"github.com/go-git/go-git/v5/internal/revision"
"github.com/go-git/go-git/v5/internal/url"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
formatcfg "github.com/go-git/go-git/v5/plumbing/format/config"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage"
"github.com/go-git/go-git/v5/storage/filesystem"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// GitDirName this is a special folder where all the git stuff is.
const GitDirName = ".git"
var (
// ErrBranchExists an error stating the specified branch already exists
ErrBranchExists = errors.New("branch already exists")
// ErrBranchNotFound an error stating the specified branch does not exist
ErrBranchNotFound = errors.New("branch not found")
// ErrTagExists an error stating the specified tag already exists
ErrTagExists = errors.New("tag already exists")
// ErrTagNotFound an error stating the specified tag does not exist
ErrTagNotFound = errors.New("tag not found")
// ErrFetching is returned when the packfile could not be downloaded
ErrFetching = errors.New("unable to fetch packfile")
ErrInvalidReference = errors.New("invalid reference, should be a tag or a branch")
ErrRepositoryNotExists = errors.New("repository does not exist")
ErrRepositoryIncomplete = errors.New("repository's commondir path does not exist")
ErrRepositoryAlreadyExists = errors.New("repository already exists")
ErrRemoteNotFound = errors.New("remote not found")
ErrRemoteExists = errors.New("remote already exists")
ErrAnonymousRemoteName = errors.New("anonymous remote name must be 'anonymous'")
ErrWorktreeNotProvided = errors.New("worktree should be provided")
ErrIsBareRepository = errors.New("worktree not available in a bare repository")
ErrUnableToResolveCommit = errors.New("unable to resolve commit")
ErrPackedObjectsNotSupported = errors.New("packed objects not supported")
ErrSHA256NotSupported = errors.New("go-git was not compiled with SHA256 support")
ErrAlternatePathNotSupported = errors.New("alternate path must use the file scheme")
ErrUnsupportedMergeStrategy = errors.New("unsupported merge strategy")
ErrFastForwardMergeNotPossible = errors.New("not possible to fast-forward merge changes")
)
// Repository represents a git repository
type Repository struct {
Storer storage.Storer
r map[string]*Remote
wt billy.Filesystem
}
type InitOptions struct {
// The default branch (e.g. "refs/heads/master")
DefaultBranch plumbing.ReferenceName
}
// Init creates an empty git repository, based on the given Storer and worktree.
// The worktree Filesystem is optional, if nil a bare repository is created. If
// the given storer is not empty ErrRepositoryAlreadyExists is returned
func Init(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
options := InitOptions{
DefaultBranch: plumbing.Master,
}
return InitWithOptions(s, worktree, options)
}
func InitWithOptions(s storage.Storer, worktree billy.Filesystem, options InitOptions) (*Repository, error) {
if err := initStorer(s); err != nil {
return nil, err
}
if options.DefaultBranch == "" {
options.DefaultBranch = plumbing.Master
}
if err := options.DefaultBranch.Validate(); err != nil {
return nil, err
}
r := newRepository(s, worktree)
_, err := r.Reference(plumbing.HEAD, false)
switch err {
case plumbing.ErrReferenceNotFound:
case nil:
return nil, ErrRepositoryAlreadyExists
default:
return nil, err
}
h := plumbing.NewSymbolicReference(plumbing.HEAD, options.DefaultBranch)
if err := s.SetReference(h); err != nil {
return nil, err
}
if worktree == nil {
_ = r.setIsBare(true)
return r, nil
}
return r, setWorktreeAndStoragePaths(r, worktree)
}
func initStorer(s storer.Storer) error {
i, ok := s.(storer.Initializer)
if !ok {
return nil
}
return i.Init()
}
func setWorktreeAndStoragePaths(r *Repository, worktree billy.Filesystem) error {
type fsBased interface {
Filesystem() billy.Filesystem
}
// .git file is only created if the storage is file based and the file
// system is osfs.OS
fs, isFSBased := r.Storer.(fsBased)
if !isFSBased {
return nil
}
if err := createDotGitFile(worktree, fs.Filesystem()); err != nil {
return err
}
return setConfigWorktree(r, worktree, fs.Filesystem())
}
func createDotGitFile(worktree, storage billy.Filesystem) error {
path, err := filepath.Rel(worktree.Root(), storage.Root())
if err != nil {
path = storage.Root()
}
if path == GitDirName {
// not needed, since the folder is the default place
return nil
}
f, err := worktree.Create(GitDirName)
if err != nil {
return err
}
defer f.Close()
_, err = fmt.Fprintf(f, "gitdir: %s\n", path)
return err
}
func setConfigWorktree(r *Repository, worktree, storage billy.Filesystem) error {
path, err := filepath.Rel(storage.Root(), worktree.Root())
if err != nil {
path = worktree.Root()
}
if path == ".." {
// not needed, since the folder is the default place
return nil
}
cfg, err := r.Config()
if err != nil {
return err
}
cfg.Core.Worktree = path
return r.Storer.SetConfig(cfg)
}
// Open opens a git repository using the given Storer and worktree filesystem,
// if the given storer is complete empty ErrRepositoryNotExists is returned.
// The worktree can be nil when the repository being opened is bare, if the
// repository is a normal one (not bare) and worktree is nil the err
// ErrWorktreeNotProvided is returned
func Open(s storage.Storer, worktree billy.Filesystem) (*Repository, error) {
_, err := s.Reference(plumbing.HEAD)
if err == plumbing.ErrReferenceNotFound {
return nil, ErrRepositoryNotExists
}
if err != nil {
return nil, err
}
return newRepository(s, worktree), nil
}
// Clone a repository into the given Storer and worktree Filesystem with the
// given options, if worktree is nil a bare repository is created. If the given
// storer is not empty ErrRepositoryAlreadyExists is returned.
func Clone(s storage.Storer, worktree billy.Filesystem, o *CloneOptions) (*Repository, error) {
return CloneContext(context.Background(), s, worktree, o)
}
// CloneContext a repository into the given Storer and worktree Filesystem with
// the given options, if worktree is nil a bare repository is created. If the
// given storer is not empty ErrRepositoryAlreadyExists is returned.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func CloneContext(
ctx context.Context, s storage.Storer, worktree billy.Filesystem, o *CloneOptions,
) (*Repository, error) {
r, err := Init(s, worktree)
if err != nil {
return nil, err
}
return r, r.clone(ctx, o)
}
// PlainInit create an empty git repository at the given path. isBare defines
// if the repository will have worktree (non-bare) or not (bare), if the path
// is not empty ErrRepositoryAlreadyExists is returned.
func PlainInit(path string, isBare bool) (*Repository, error) {
return PlainInitWithOptions(path, &PlainInitOptions{
Bare: isBare,
})
}
func PlainInitWithOptions(path string, opts *PlainInitOptions) (*Repository, error) {
if opts == nil {
opts = &PlainInitOptions{}
}
var wt, dot billy.Filesystem
if opts.Bare {
dot = osfs.New(path)
} else {
wt = osfs.New(path)
dot, _ = wt.Chroot(GitDirName)
}
s := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
r, err := InitWithOptions(s, wt, opts.InitOptions)
if err != nil {
return nil, err
}
cfg, err := r.Config()
if err != nil {
return nil, err
}
if opts.ObjectFormat != "" {
if opts.ObjectFormat == formatcfg.SHA256 && hash.CryptoType != crypto.SHA256 {
return nil, ErrSHA256NotSupported
}
cfg.Core.RepositoryFormatVersion = formatcfg.Version_1
cfg.Extensions.ObjectFormat = opts.ObjectFormat
}
err = r.Storer.SetConfig(cfg)
if err != nil {
return nil, err
}
return r, err
}
// PlainOpen opens a git repository from the given path. It detects if the
// repository is bare or a normal one. If the path doesn't contain a valid
// repository ErrRepositoryNotExists is returned
func PlainOpen(path string) (*Repository, error) {
return PlainOpenWithOptions(path, &PlainOpenOptions{})
}
// PlainOpenWithOptions opens a git repository from the given path with specific
// options. See PlainOpen for more info.
func PlainOpenWithOptions(path string, o *PlainOpenOptions) (*Repository, error) {
dot, wt, err := dotGitToOSFilesystems(path, o.DetectDotGit)
if err != nil {
return nil, err
}
if _, err := dot.Stat(""); err != nil {
if os.IsNotExist(err) {
return nil, ErrRepositoryNotExists
}
return nil, err
}
var repositoryFs billy.Filesystem
if o.EnableDotGitCommonDir {
dotGitCommon, err := dotGitCommonDirectory(dot)
if err != nil {
return nil, err
}
repositoryFs = dotgit.NewRepositoryFilesystem(dot, dotGitCommon)
} else {
repositoryFs = dot
}
s := filesystem.NewStorage(repositoryFs, cache.NewObjectLRUDefault())
return Open(s, wt)
}
func dotGitToOSFilesystems(path string, detect bool) (dot, wt billy.Filesystem, err error) {
path, err = path_util.ReplaceTildeWithHome(path)
if err != nil {
return nil, nil, err
}
if path, err = filepath.Abs(path); err != nil {
return nil, nil, err
}
var fs billy.Filesystem
var fi os.FileInfo
for {
fs = osfs.New(path)
pathinfo, err := fs.Stat("/")
if !os.IsNotExist(err) {
if pathinfo == nil {
return nil, nil, err
}
if !pathinfo.IsDir() && detect {
fs = osfs.New(filepath.Dir(path))
}
}
fi, err = fs.Stat(GitDirName)
if err == nil {
// no error; stop
break
}
if !os.IsNotExist(err) {
// unknown error; stop
return nil, nil, err
}
if detect {
// try its parent as long as we haven't reached
// the root dir
if dir := filepath.Dir(path); dir != path {
path = dir
continue
}
}
// not detecting via parent dirs and the dir does not exist;
// stop
return fs, nil, nil
}
if fi.IsDir() {
dot, err = fs.Chroot(GitDirName)
return dot, fs, err
}
dot, err = dotGitFileToOSFilesystem(path, fs)
if err != nil {
return nil, nil, err
}
return dot, fs, nil
}
func dotGitFileToOSFilesystem(path string, fs billy.Filesystem) (bfs billy.Filesystem, err error) {
f, err := fs.Open(GitDirName)
if err != nil {
return nil, err
}
defer ioutil.CheckClose(f, &err)
b, err := io.ReadAll(f)
if err != nil {
return nil, err
}
line := string(b)
const prefix = "gitdir: "
if !strings.HasPrefix(line, prefix) {
return nil, fmt.Errorf(".git file has no %s prefix", prefix)
}
gitdir := strings.Split(line[len(prefix):], "\n")[0]
gitdir = strings.TrimSpace(gitdir)
if filepath.IsAbs(gitdir) {
return osfs.New(gitdir), nil
}
return osfs.New(fs.Join(path, gitdir)), nil
}
func dotGitCommonDirectory(fs billy.Filesystem) (commonDir billy.Filesystem, err error) {
f, err := fs.Open("commondir")
if os.IsNotExist(err) {
return nil, nil
}
if err != nil {
return nil, err
}
b, err := io.ReadAll(f)
if err != nil {
return nil, err
}
if len(b) > 0 {
path := strings.TrimSpace(string(b))
if filepath.IsAbs(path) {
commonDir = osfs.New(path)
} else {
commonDir = osfs.New(filepath.Join(fs.Root(), path))
}
if _, err := commonDir.Stat(""); err != nil {
if os.IsNotExist(err) {
return nil, ErrRepositoryIncomplete
}
return nil, err
}
}
return commonDir, nil
}
// PlainClone a repository into the path with the given options, isBare defines
// if the new repository will be bare or normal. If the path is not empty
// ErrRepositoryAlreadyExists is returned.
//
// TODO(mcuadros): move isBare to CloneOptions in v5
func PlainClone(path string, isBare bool, o *CloneOptions) (*Repository, error) {
return PlainCloneContext(context.Background(), path, isBare, o)
}
// PlainCloneContext a repository into the path with the given options, isBare
// defines if the new repository will be bare or normal. If the path is not empty
// ErrRepositoryAlreadyExists is returned.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
//
// TODO(mcuadros): move isBare to CloneOptions in v5
// TODO(smola): refuse upfront to clone on a non-empty directory in v5, see #1027
func PlainCloneContext(ctx context.Context, path string, isBare bool, o *CloneOptions) (*Repository, error) {
cleanup, cleanupParent, err := checkIfCleanupIsNeeded(path)
if err != nil {
return nil, err
}
if o.Mirror {
isBare = true
}
r, err := PlainInit(path, isBare)
if err != nil {
return nil, err
}
err = r.clone(ctx, o)
if err != nil && err != ErrRepositoryAlreadyExists {
if cleanup {
_ = cleanUpDir(path, cleanupParent)
}
}
return r, err
}
func newRepository(s storage.Storer, worktree billy.Filesystem) *Repository {
return &Repository{
Storer: s,
wt: worktree,
r: make(map[string]*Remote),
}
}
func checkIfCleanupIsNeeded(path string) (cleanup bool, cleanParent bool, err error) {
fi, err := osfs.Default.Stat(path)
if err != nil {
if os.IsNotExist(err) {
return true, true, nil
}
return false, false, err
}
if !fi.IsDir() {
return false, false, fmt.Errorf("path is not a directory: %s", path)
}
files, err := osfs.Default.ReadDir(path)
if err != nil {
return false, false, err
}
if len(files) == 0 {
return true, false, nil
}
return false, false, nil
}
func cleanUpDir(path string, all bool) error {
if all {
return util.RemoveAll(osfs.Default, path)
}
files, err := osfs.Default.ReadDir(path)
if err != nil {
return err
}
for _, fi := range files {
if err := util.RemoveAll(osfs.Default, osfs.Default.Join(path, fi.Name())); err != nil {
return err
}
}
return err
}
// Config return the repository config. In a filesystem backed repository this
// means read the `.git/config`.
func (r *Repository) Config() (*config.Config, error) {
return r.Storer.Config()
}
// SetConfig marshall and writes the repository config. In a filesystem backed
// repository this means write the `.git/config`. This function should be called
// with the result of `Repository.Config` and never with the output of
// `Repository.ConfigScoped`.
func (r *Repository) SetConfig(cfg *config.Config) error {
return r.Storer.SetConfig(cfg)
}
// ConfigScoped returns the repository config, merged with requested scope and
// lower. For example if, config.GlobalScope is given the local and global config
// are returned merged in one config value.
func (r *Repository) ConfigScoped(scope config.Scope) (*config.Config, error) {
// TODO(mcuadros): v6, add this as ConfigOptions.Scoped
var err error
system := config.NewConfig()
if scope >= config.SystemScope {
system, err = config.LoadConfig(config.SystemScope)
if err != nil {
return nil, err
}
}
global := config.NewConfig()
if scope >= config.GlobalScope {
global, err = config.LoadConfig(config.GlobalScope)
if err != nil {
return nil, err
}
}
local, err := r.Storer.Config()
if err != nil {
return nil, err
}
_ = mergo.Merge(global, system)
_ = mergo.Merge(local, global)
return local, nil
}
// Remote return a remote if exists
func (r *Repository) Remote(name string) (*Remote, error) {
cfg, err := r.Config()
if err != nil {
return nil, err
}
c, ok := cfg.Remotes[name]
if !ok {
return nil, ErrRemoteNotFound
}
return NewRemote(r.Storer, c), nil
}
// Remotes returns a list with all the remotes
func (r *Repository) Remotes() ([]*Remote, error) {
cfg, err := r.Config()
if err != nil {
return nil, err
}
remotes := make([]*Remote, len(cfg.Remotes))
var i int
for _, c := range cfg.Remotes {
remotes[i] = NewRemote(r.Storer, c)
i++
}
return remotes, nil
}
// CreateRemote creates a new remote
func (r *Repository) CreateRemote(c *config.RemoteConfig) (*Remote, error) {
if err := c.Validate(); err != nil {
return nil, err
}
remote := NewRemote(r.Storer, c)
cfg, err := r.Config()
if err != nil {
return nil, err
}
if _, ok := cfg.Remotes[c.Name]; ok {
return nil, ErrRemoteExists
}
cfg.Remotes[c.Name] = c
return remote, r.Storer.SetConfig(cfg)
}
// CreateRemoteAnonymous creates a new anonymous remote. c.Name must be "anonymous".
// It's used like 'git fetch git@github.com:src-d/go-git.git master:master'.
func (r *Repository) CreateRemoteAnonymous(c *config.RemoteConfig) (*Remote, error) {
if err := c.Validate(); err != nil {
return nil, err
}
if c.Name != "anonymous" {
return nil, ErrAnonymousRemoteName
}
remote := NewRemote(r.Storer, c)
return remote, nil
}
// DeleteRemote delete a remote from the repository and delete the config
func (r *Repository) DeleteRemote(name string) error {
cfg, err := r.Config()
if err != nil {
return err
}
if _, ok := cfg.Remotes[name]; !ok {
return ErrRemoteNotFound
}
delete(cfg.Remotes, name)
return r.Storer.SetConfig(cfg)
}
// Branch return a Branch if exists
func (r *Repository) Branch(name string) (*config.Branch, error) {
cfg, err := r.Config()
if err != nil {
return nil, err
}
b, ok := cfg.Branches[name]
if !ok {
return nil, ErrBranchNotFound
}
return b, nil
}
// CreateBranch creates a new Branch
func (r *Repository) CreateBranch(c *config.Branch) error {
if err := c.Validate(); err != nil {
return err
}
cfg, err := r.Config()
if err != nil {
return err
}
if _, ok := cfg.Branches[c.Name]; ok {
return ErrBranchExists
}
cfg.Branches[c.Name] = c
return r.Storer.SetConfig(cfg)
}
// DeleteBranch delete a Branch from the repository and delete the config
func (r *Repository) DeleteBranch(name string) error {
cfg, err := r.Config()
if err != nil {
return err
}
if _, ok := cfg.Branches[name]; !ok {
return ErrBranchNotFound
}
delete(cfg.Branches, name)
return r.Storer.SetConfig(cfg)
}
// CreateTag creates a tag. If opts is included, the tag is an annotated tag,
// otherwise a lightweight tag is created.
func (r *Repository) CreateTag(name string, hash plumbing.Hash, opts *CreateTagOptions) (*plumbing.Reference, error) {
rname := plumbing.NewTagReferenceName(name)
if err := rname.Validate(); err != nil {
return nil, err
}
_, err := r.Storer.Reference(rname)
switch err {
case nil:
// Tag exists, this is an error
return nil, ErrTagExists
case plumbing.ErrReferenceNotFound:
// Tag missing, available for creation, pass this
default:
// Some other error
return nil, err
}
var target plumbing.Hash
if opts != nil {
target, err = r.createTagObject(name, hash, opts)
if err != nil {
return nil, err
}
} else {
target = hash
}
ref := plumbing.NewHashReference(rname, target)
if err = r.Storer.SetReference(ref); err != nil {
return nil, err
}
return ref, nil
}
func (r *Repository) createTagObject(name string, hash plumbing.Hash, opts *CreateTagOptions) (plumbing.Hash, error) {
if err := opts.Validate(r, hash); err != nil {
return plumbing.ZeroHash, err
}
rawobj, err := object.GetObject(r.Storer, hash)
if err != nil {
return plumbing.ZeroHash, err
}
tag := &object.Tag{
Name: name,
Tagger: *opts.Tagger,
Message: opts.Message,
TargetType: rawobj.Type(),
Target: hash,
}
if opts.SignKey != nil {
sig, err := r.buildTagSignature(tag, opts.SignKey)
if err != nil {
return plumbing.ZeroHash, err
}
tag.PGPSignature = sig
}
obj := r.Storer.NewEncodedObject()
if err := tag.Encode(obj); err != nil {
return plumbing.ZeroHash, err
}
return r.Storer.SetEncodedObject(obj)
}
func (r *Repository) buildTagSignature(tag *object.Tag, signKey *openpgp.Entity) (string, error) {
encoded := &plumbing.MemoryObject{}
if err := tag.Encode(encoded); err != nil {
return "", err
}
rdr, err := encoded.Reader()
if err != nil {
return "", err
}
var b bytes.Buffer
if err := openpgp.ArmoredDetachSign(&b, signKey, rdr, nil); err != nil {
return "", err
}
return b.String(), nil
}
// Tag returns a tag from the repository.
//
// If you want to check to see if the tag is an annotated tag, you can call
// TagObject on the hash of the reference in ForEach:
//
// ref, err := r.Tag("v0.1.0")
// if err != nil {
// // Handle error
// }
//
// obj, err := r.TagObject(ref.Hash())
// switch err {
// case nil:
// // Tag object present
// case plumbing.ErrObjectNotFound:
// // Not a tag object
// default:
// // Some other error
// }
func (r *Repository) Tag(name string) (*plumbing.Reference, error) {
ref, err := r.Reference(plumbing.ReferenceName(path.Join("refs", "tags", name)), false)
if err != nil {
if err == plumbing.ErrReferenceNotFound {
// Return a friendly error for this one, versus just ReferenceNotFound.
return nil, ErrTagNotFound
}
return nil, err
}
return ref, nil
}
// DeleteTag deletes a tag from the repository.
func (r *Repository) DeleteTag(name string) error {
_, err := r.Tag(name)
if err != nil {
return err
}
return r.Storer.RemoveReference(plumbing.ReferenceName(path.Join("refs", "tags", name)))
}
func (r *Repository) resolveToCommitHash(h plumbing.Hash) (plumbing.Hash, error) {
obj, err := r.Storer.EncodedObject(plumbing.AnyObject, h)
if err != nil {
return plumbing.ZeroHash, err
}
switch obj.Type() {
case plumbing.TagObject:
t, err := object.DecodeTag(r.Storer, obj)
if err != nil {
return plumbing.ZeroHash, err
}
return r.resolveToCommitHash(t.Target)
case plumbing.CommitObject:
return h, nil
default:
return plumbing.ZeroHash, ErrUnableToResolveCommit
}
}
// Clone clones a remote repository
func (r *Repository) clone(ctx context.Context, o *CloneOptions) error {
if err := o.Validate(); err != nil {
return err
}
c := &config.RemoteConfig{
Name: o.RemoteName,
URLs: []string{o.URL},
Fetch: r.cloneRefSpec(o),
Mirror: o.Mirror,
}
if _, err := r.CreateRemote(c); err != nil {
return err
}
// When the repository to clone is on the local machine,
// instead of using hard links, automatically setup .git/objects/info/alternates
// to share the objects with the source repository
if o.Shared {
if !url.IsLocalEndpoint(o.URL) {
return ErrAlternatePathNotSupported
}
altpath := o.URL
remoteRepo, err := PlainOpen(o.URL)
if err != nil {
return fmt.Errorf("failed to open remote repository: %w", err)
}
conf, err := remoteRepo.Config()
if err != nil {
return fmt.Errorf("failed to read remote repository configuration: %w", err)
}
if !conf.Core.IsBare {
altpath = path.Join(altpath, GitDirName)
}
if err := r.Storer.AddAlternate(altpath); err != nil {
return fmt.Errorf("failed to add alternate file to git objects dir: %w", err)
}
}
ref, err := r.fetchAndUpdateReferences(ctx, &FetchOptions{
RefSpecs: c.Fetch,
Depth: o.Depth,
Auth: o.Auth,
Progress: o.Progress,
Tags: o.Tags,
RemoteName: o.RemoteName,
InsecureSkipTLS: o.InsecureSkipTLS,
CABundle: o.CABundle,
ProxyOptions: o.ProxyOptions,
}, o.ReferenceName)
if err != nil {
return err
}
if r.wt != nil && !o.NoCheckout {
w, err := r.Worktree()
if err != nil {
return err
}
head, err := r.Head()
if err != nil {
return err
}
if err := w.Reset(&ResetOptions{
Mode: MergeReset,
Commit: head.Hash(),
}); err != nil {
return err
}
if o.RecurseSubmodules != NoRecurseSubmodules {
if err := w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
RecurseSubmodules: o.RecurseSubmodules,
Depth: func() int {
if o.ShallowSubmodules {
return 1
}
return 0
}(),
Auth: o.Auth,
}); err != nil {
return err
}
}
}
if err := r.updateRemoteConfigIfNeeded(o, c, ref); err != nil {
return err
}
if !o.Mirror && ref.Name().IsBranch() {
branchRef := ref.Name()
branchName := strings.Split(string(branchRef), "refs/heads/")[1]
b := &config.Branch{
Name: branchName,
Merge: branchRef,
}
if o.RemoteName == "" {
b.Remote = "origin"
} else {
b.Remote = o.RemoteName
}
if err := r.CreateBranch(b); err != nil {
return err
}
}
return nil
}
const (
refspecTag = "+refs/tags/%s:refs/tags/%[1]s"
refspecSingleBranch = "+refs/heads/%s:refs/remotes/%s/%[1]s"
refspecSingleBranchHEAD = "+HEAD:refs/remotes/%s/HEAD"
)
func (r *Repository) cloneRefSpec(o *CloneOptions) []config.RefSpec {
switch {
case o.Mirror:
return []config.RefSpec{"+refs/*:refs/*"}
case o.ReferenceName.IsTag():
return []config.RefSpec{
config.RefSpec(fmt.Sprintf(refspecTag, o.ReferenceName.Short())),
}
case o.SingleBranch && o.ReferenceName == plumbing.HEAD:
return []config.RefSpec{
config.RefSpec(fmt.Sprintf(refspecSingleBranchHEAD, o.RemoteName)),
}
case o.SingleBranch:
return []config.RefSpec{
config.RefSpec(fmt.Sprintf(refspecSingleBranch, o.ReferenceName.Short(), o.RemoteName)),
}
default:
return []config.RefSpec{
config.RefSpec(fmt.Sprintf(config.DefaultFetchRefSpec, o.RemoteName)),
}
}
}
func (r *Repository) setIsBare(isBare bool) error {
cfg, err := r.Config()
if err != nil {
return err
}
cfg.Core.IsBare = isBare
return r.Storer.SetConfig(cfg)
}
func (r *Repository) updateRemoteConfigIfNeeded(o *CloneOptions, c *config.RemoteConfig, _ *plumbing.Reference) error {
if !o.SingleBranch {
return nil
}
c.Fetch = r.cloneRefSpec(o)
cfg, err := r.Config()
if err != nil {
return err
}
cfg.Remotes[c.Name] = c
return r.Storer.SetConfig(cfg)
}
func (r *Repository) fetchAndUpdateReferences(
ctx context.Context, o *FetchOptions, ref plumbing.ReferenceName,
) (*plumbing.Reference, error) {
if err := o.Validate(); err != nil {
return nil, err
}
remote, err := r.Remote(o.RemoteName)
if err != nil {
return nil, err
}
objsUpdated := true
remoteRefs, err := remote.fetch(ctx, o)
if err == NoErrAlreadyUpToDate {
objsUpdated = false
} else if err == packfile.ErrEmptyPackfile {
return nil, ErrFetching
} else if err != nil {
return nil, err
}
resolvedRef, err := expand_ref(remoteRefs, ref)
if err != nil {
return nil, err
}
refsUpdated, err := r.updateReferences(remote.c.Fetch, resolvedRef)
if err != nil {
return nil, err
}
if !objsUpdated && !refsUpdated {
return nil, NoErrAlreadyUpToDate
}
return resolvedRef, nil
}
func (r *Repository) updateReferences(spec []config.RefSpec,
resolvedRef *plumbing.Reference) (updated bool, err error) {
if !resolvedRef.Name().IsBranch() {
// Detached HEAD mode
h, err := r.resolveToCommitHash(resolvedRef.Hash())
if err != nil {
return false, err
}
head := plumbing.NewHashReference(plumbing.HEAD, h)
return updateReferenceStorerIfNeeded(r.Storer, head)
}
refs := []*plumbing.Reference{
// Create local reference for the resolved ref
resolvedRef,
// Create local symbolic HEAD
plumbing.NewSymbolicReference(plumbing.HEAD, resolvedRef.Name()),
}
refs = append(refs, r.calculateRemoteHeadReference(spec, resolvedRef)...)
for _, ref := range refs {
u, err := updateReferenceStorerIfNeeded(r.Storer, ref)
if err != nil {
return updated, err
}
if u {
updated = true
}
}
return
}
func (r *Repository) calculateRemoteHeadReference(spec []config.RefSpec,
resolvedHead *plumbing.Reference) []*plumbing.Reference {
var refs []*plumbing.Reference
// Create resolved HEAD reference with remote prefix if it does not
// exist. This is needed when using single branch and HEAD.
for _, rs := range spec {
name := resolvedHead.Name()
if !rs.Match(name) {
continue
}
name = rs.Dst(name)
_, err := r.Storer.Reference(name)
if err == plumbing.ErrReferenceNotFound {
refs = append(refs, plumbing.NewHashReference(name, resolvedHead.Hash()))
}
}
return refs
}
func checkAndUpdateReferenceStorerIfNeeded(
s storer.ReferenceStorer, r, old *plumbing.Reference) (
updated bool, err error) {
p, err := s.Reference(r.Name())
if err != nil && err != plumbing.ErrReferenceNotFound {
return false, err
}
// we use the string method to compare references, is the easiest way
if err == plumbing.ErrReferenceNotFound || r.String() != p.String() {
if err := s.CheckAndSetReference(r, old); err != nil {
return false, err
}
return true, nil
}
return false, nil
}
func updateReferenceStorerIfNeeded(
s storer.ReferenceStorer, r *plumbing.Reference) (updated bool, err error) {
return checkAndUpdateReferenceStorerIfNeeded(s, r, nil)
}
// Fetch fetches references along with the objects necessary to complete
// their histories, from the remote named as FetchOptions.RemoteName.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
func (r *Repository) Fetch(o *FetchOptions) error {
return r.FetchContext(context.Background(), o)
}
// FetchContext fetches references along with the objects necessary to complete
// their histories, from the remote named as FetchOptions.RemoteName.
//
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (r *Repository) FetchContext(ctx context.Context, o *FetchOptions) error {
if err := o.Validate(); err != nil {
return err
}
remote, err := r.Remote(o.RemoteName)
if err != nil {
return err
}
return remote.FetchContext(ctx, o)
}
// Push performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date, from the remote named as
// FetchOptions.RemoteName.
func (r *Repository) Push(o *PushOptions) error {
return r.PushContext(context.Background(), o)
}
// PushContext performs a push to the remote. Returns NoErrAlreadyUpToDate if
// the remote was already up-to-date, from the remote named as
// FetchOptions.RemoteName.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (r *Repository) PushContext(ctx context.Context, o *PushOptions) error {
if err := o.Validate(); err != nil {
return err
}
remote, err := r.Remote(o.RemoteName)
if err != nil {
return err
}
return remote.PushContext(ctx, o)
}
// Log returns the commit history from the given LogOptions.
func (r *Repository) Log(o *LogOptions) (object.CommitIter, error) {
fn := commitIterFunc(o.Order)
if fn == nil {
return nil, fmt.Errorf("invalid Order=%v", o.Order)
}
var (
it object.CommitIter
err error
)
if o.All {
it, err = r.logAll(fn)
} else {
it, err = r.log(o.From, fn)
}
if err != nil {
return nil, err
}
if o.FileName != nil {
// for `git log --all` also check parent (if the next commit comes from the real parent)
it = r.logWithFile(*o.FileName, it, o.All)
}
if o.PathFilter != nil {
it = r.logWithPathFilter(o.PathFilter, it, o.All)
}
if o.Since != nil || o.Until != nil {
limitOptions := object.LogLimitOptions{Since: o.Since, Until: o.Until}
it = r.logWithLimit(it, limitOptions)
}
return it, nil
}
func (r *Repository) log(from plumbing.Hash, commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) {
h := from
if from == plumbing.ZeroHash {
head, err := r.Head()
if err != nil {
return nil, err
}
h = head.Hash()
}
commit, err := r.CommitObject(h)
if err != nil {
return nil, err
}
return commitIterFunc(commit), nil
}
func (r *Repository) logAll(commitIterFunc func(*object.Commit) object.CommitIter) (object.CommitIter, error) {
return object.NewCommitAllIter(r.Storer, commitIterFunc)
}
func (*Repository) logWithFile(fileName string, commitIter object.CommitIter, checkParent bool) object.CommitIter {
return object.NewCommitPathIterFromIter(
func(path string) bool {
return path == fileName
},
commitIter,
checkParent,
)
}
func (*Repository) logWithPathFilter(pathFilter func(string) bool, commitIter object.CommitIter, checkParent bool) object.CommitIter {
return object.NewCommitPathIterFromIter(
pathFilter,
commitIter,
checkParent,
)
}
func (*Repository) logWithLimit(commitIter object.CommitIter, limitOptions object.LogLimitOptions) object.CommitIter {
return object.NewCommitLimitIterFromIter(commitIter, limitOptions)
}
func commitIterFunc(order LogOrder) func(c *object.Commit) object.CommitIter {
switch order {
case LogOrderDefault:
return func(c *object.Commit) object.CommitIter {
return object.NewCommitPreorderIter(c, nil, nil)
}
case LogOrderDFS:
return func(c *object.Commit) object.CommitIter {
return object.NewCommitPreorderIter(c, nil, nil)
}
case LogOrderDFSPost:
return func(c *object.Commit) object.CommitIter {
return object.NewCommitPostorderIter(c, nil)
}
case LogOrderBSF:
return func(c *object.Commit) object.CommitIter {
return object.NewCommitIterBSF(c, nil, nil)
}
case LogOrderCommitterTime:
return func(c *object.Commit) object.CommitIter {
return object.NewCommitIterCTime(c, nil, nil)
}
}
return nil
}
// Tags returns all the tag References in a repository.
//
// If you want to check to see if the tag is an annotated tag, you can call
// TagObject on the hash Reference passed in through ForEach:
//
// iter, err := r.Tags()
// if err != nil {
// // Handle error
// }
//
// if err := iter.ForEach(func (ref *plumbing.Reference) error {
// obj, err := r.TagObject(ref.Hash())
// switch err {
// case nil:
// // Tag object present
// case plumbing.ErrObjectNotFound:
// // Not a tag object
// default:
// // Some other error
// return err
// }
// }); err != nil {
// // Handle outer iterator error
// }
func (r *Repository) Tags() (storer.ReferenceIter, error) {
refIter, err := r.Storer.IterReferences()
if err != nil {
return nil, err
}
return storer.NewReferenceFilteredIter(
func(r *plumbing.Reference) bool {
return r.Name().IsTag()
}, refIter), nil
}
// Branches returns all the References that are Branches.
func (r *Repository) Branches() (storer.ReferenceIter, error) {
refIter, err := r.Storer.IterReferences()
if err != nil {
return nil, err
}
return storer.NewReferenceFilteredIter(
func(r *plumbing.Reference) bool {
return r.Name().IsBranch()
}, refIter), nil
}
// Notes returns all the References that are notes. For more information:
// https://git-scm.com/docs/git-notes
func (r *Repository) Notes() (storer.ReferenceIter, error) {
refIter, err := r.Storer.IterReferences()
if err != nil {
return nil, err
}
return storer.NewReferenceFilteredIter(
func(r *plumbing.Reference) bool {
return r.Name().IsNote()
}, refIter), nil
}
// TreeObject return a Tree with the given hash. If not found
// plumbing.ErrObjectNotFound is returned
func (r *Repository) TreeObject(h plumbing.Hash) (*object.Tree, error) {
return object.GetTree(r.Storer, h)
}
// TreeObjects returns an unsorted TreeIter with all the trees in the repository
func (r *Repository) TreeObjects() (*object.TreeIter, error) {
iter, err := r.Storer.IterEncodedObjects(plumbing.TreeObject)
if err != nil {
return nil, err
}
return object.NewTreeIter(r.Storer, iter), nil
}
// CommitObject return a Commit with the given hash. If not found
// plumbing.ErrObjectNotFound is returned.
func (r *Repository) CommitObject(h plumbing.Hash) (*object.Commit, error) {
return object.GetCommit(r.Storer, h)
}
// CommitObjects returns an unsorted CommitIter with all the commits in the repository.
func (r *Repository) CommitObjects() (object.CommitIter, error) {
iter, err := r.Storer.IterEncodedObjects(plumbing.CommitObject)
if err != nil {
return nil, err
}
return object.NewCommitIter(r.Storer, iter), nil
}
// BlobObject returns a Blob with the given hash. If not found
// plumbing.ErrObjectNotFound is returned.
func (r *Repository) BlobObject(h plumbing.Hash) (*object.Blob, error) {
return object.GetBlob(r.Storer, h)
}
// BlobObjects returns an unsorted BlobIter with all the blobs in the repository.
func (r *Repository) BlobObjects() (*object.BlobIter, error) {
iter, err := r.Storer.IterEncodedObjects(plumbing.BlobObject)
if err != nil {
return nil, err
}
return object.NewBlobIter(r.Storer, iter), nil
}
// TagObject returns a Tag with the given hash. If not found
// plumbing.ErrObjectNotFound is returned. This method only returns
// annotated Tags, no lightweight Tags.
func (r *Repository) TagObject(h plumbing.Hash) (*object.Tag, error) {
return object.GetTag(r.Storer, h)
}
// TagObjects returns a unsorted TagIter that can step through all of the annotated
// tags in the repository.
func (r *Repository) TagObjects() (*object.TagIter, error) {
iter, err := r.Storer.IterEncodedObjects(plumbing.TagObject)
if err != nil {
return nil, err
}
return object.NewTagIter(r.Storer, iter), nil
}
// Object returns an Object with the given hash. If not found
// plumbing.ErrObjectNotFound is returned.
func (r *Repository) Object(t plumbing.ObjectType, h plumbing.Hash) (object.Object, error) {
obj, err := r.Storer.EncodedObject(t, h)
if err != nil {
return nil, err
}
return object.DecodeObject(r.Storer, obj)
}
// Objects returns an unsorted ObjectIter with all the objects in the repository.
func (r *Repository) Objects() (*object.ObjectIter, error) {
iter, err := r.Storer.IterEncodedObjects(plumbing.AnyObject)
if err != nil {
return nil, err
}
return object.NewObjectIter(r.Storer, iter), nil
}
// Head returns the reference where HEAD is pointing to.
func (r *Repository) Head() (*plumbing.Reference, error) {
return storer.ResolveReference(r.Storer, plumbing.HEAD)
}
// Reference returns the reference for a given reference name. If resolved is
// true, any symbolic reference will be resolved.
func (r *Repository) Reference(name plumbing.ReferenceName, resolved bool) (
*plumbing.Reference, error) {
if resolved {
return storer.ResolveReference(r.Storer, name)
}
return r.Storer.Reference(name)
}
// References returns an unsorted ReferenceIter for all references.
func (r *Repository) References() (storer.ReferenceIter, error) {
return r.Storer.IterReferences()
}
// Worktree returns a worktree based on the given fs, if nil the default
// worktree will be used.
func (r *Repository) Worktree() (*Worktree, error) {
if r.wt == nil {
return nil, ErrIsBareRepository
}
return &Worktree{r: r, Filesystem: r.wt}, nil
}
func expand_ref(s storer.ReferenceStorer, ref plumbing.ReferenceName) (*plumbing.Reference, error) {
// For improving troubleshooting, this preserves the error for the provided `ref`,
// and returns the error for that specific ref in case all parse rules fails.
var ret error
for _, rule := range plumbing.RefRevParseRules {
resolvedRef, err := storer.ResolveReference(s, plumbing.ReferenceName(fmt.Sprintf(rule, ref)))
if err == nil {
return resolvedRef, nil
} else if ret == nil {
ret = err
}
}
return nil, ret
}
// ResolveRevision resolves revision to corresponding hash. It will always
// resolve to a commit hash, not a tree or annotated tag.
//
// Implemented resolvers : HEAD, branch, tag, heads/branch, refs/heads/branch,
// refs/tags/tag, refs/remotes/origin/branch, refs/remotes/origin/HEAD, tilde and caret (HEAD~1, master~^, tag~2, ref/heads/master~1, ...), selection by text (HEAD^{/fix nasty bug}), hash (prefix and full)
func (r *Repository) ResolveRevision(in plumbing.Revision) (*plumbing.Hash, error) {
rev := in.String()
if rev == "" {
return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound
}
p := revision.NewParserFromString(rev)
items, err := p.Parse()
if err != nil {
return nil, err
}
var commit *object.Commit
for _, item := range items {
switch item := item.(type) {
case revision.Ref:
revisionRef := item
var tryHashes []plumbing.Hash
tryHashes = append(tryHashes, r.resolveHashPrefix(string(revisionRef))...)
ref, err := expand_ref(r.Storer, plumbing.ReferenceName(revisionRef))
if err == nil {
tryHashes = append(tryHashes, ref.Hash())
}
// in ambiguous cases, `git rev-parse` will emit a warning, but
// will always return the oid in preference to a ref; we don't have
// the ability to emit a warning here, so (for speed purposes)
// don't bother to detect the ambiguity either, just return in the
// priority that git would.
gotOne := false
for _, hash := range tryHashes {
commitObj, err := r.CommitObject(hash)
if err == nil {
commit = commitObj
gotOne = true
break
}
tagObj, err := r.TagObject(hash)
if err == nil {
// If the tag target lookup fails here, this most likely
// represents some sort of repo corruption, so let the
// error bubble up.
tagCommit, err := tagObj.Commit()
if err != nil {
return &plumbing.ZeroHash, err
}
commit = tagCommit
gotOne = true
break
}
}
if !gotOne {
return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound
}
case revision.CaretPath:
depth := item.Depth
if depth == 0 {
break
}
iter := commit.Parents()
c, err := iter.Next()
if err != nil {
return &plumbing.ZeroHash, err
}
if depth == 1 {
commit = c
break
}
c, err = iter.Next()
if err != nil {
return &plumbing.ZeroHash, err
}
commit = c
case revision.TildePath:
for i := 0; i < item.Depth; i++ {
c, err := commit.Parents().Next()
if err != nil {
return &plumbing.ZeroHash, err
}
commit = c
}
case revision.CaretReg:
history := object.NewCommitPreorderIter(commit, nil, nil)
re := item.Regexp
negate := item.Negate
var c *object.Commit
err := history.ForEach(func(hc *object.Commit) error {
if !negate && re.MatchString(hc.Message) {
c = hc
return storer.ErrStop
}
if negate && !re.MatchString(hc.Message) {
c = hc
return storer.ErrStop
}
return nil
})
if err != nil {
return &plumbing.ZeroHash, err
}
if c == nil {
return &plumbing.ZeroHash, fmt.Errorf("no commit message match regexp: %q", re.String())
}
commit = c
}
}
if commit == nil {
return &plumbing.ZeroHash, plumbing.ErrReferenceNotFound
}
return &commit.Hash, nil
}
// resolveHashPrefix returns a list of potential hashes that the given string
// is a prefix of. It quietly swallows errors, returning nil.
func (r *Repository) resolveHashPrefix(hashStr string) []plumbing.Hash {
// Handle complete and partial hashes.
// plumbing.NewHash forces args into a full 20 byte hash, which isn't suitable
// for partial hashes since they will become zero-filled.
if hashStr == "" {
return nil
}
if len(hashStr) == len(plumbing.ZeroHash)*2 {
// Only a full hash is possible.
hexb, err := hex.DecodeString(hashStr)
if err != nil {
return nil
}
var h plumbing.Hash
copy(h[:], hexb)
return []plumbing.Hash{h}
}
// Partial hash.
// hex.DecodeString only decodes to complete bytes, so only works with pairs of hex digits.
evenHex := hashStr[:len(hashStr)&^1]
hexb, err := hex.DecodeString(evenHex)
if err != nil {
return nil
}
candidates := expandPartialHash(r.Storer, hexb)
if len(evenHex) == len(hashStr) {
// The prefix was an exact number of bytes.
return candidates
}
// Do another prefix check to ensure the dangling nybble is correct.
var hashes []plumbing.Hash
for _, h := range candidates {
if strings.HasPrefix(h.String(), hashStr) {
hashes = append(hashes, h)
}
}
return hashes
}
type RepackConfig struct {
// UseRefDeltas configures whether packfile encoder will use reference deltas.
// By default OFSDeltaObject is used.
UseRefDeltas bool
// OnlyDeletePacksOlderThan if set to non-zero value
// selects only objects older than the time provided.
OnlyDeletePacksOlderThan time.Time
}
func (r *Repository) RepackObjects(cfg *RepackConfig) (err error) {
pos, ok := r.Storer.(storer.PackedObjectStorer)
if !ok {
return ErrPackedObjectsNotSupported
}
// Get the existing object packs.
hs, err := pos.ObjectPacks()
if err != nil {
return err
}
// Create a new pack.
nh, err := r.createNewObjectPack(cfg)
if err != nil {
return err
}
// Delete old packs.
for _, h := range hs {
// Skip if new hash is the same as an old one.
if h == nh {
continue
}
err = pos.DeleteOldObjectPackAndIndex(h, cfg.OnlyDeletePacksOlderThan)
if err != nil {
return err
}
}
return nil
}
// Merge merges the reference branch into the current branch.
//
// If the merge is not possible (or supported) returns an error without changing
// the HEAD for the current branch. Possible errors include:
// - The merge strategy is not supported.
// - The specific strategy cannot be used (e.g. using FastForwardMerge when one is not possible).
func (r *Repository) Merge(ref plumbing.Reference, opts MergeOptions) error {
if opts.Strategy != FastForwardMerge {
return ErrUnsupportedMergeStrategy
}
// Ignore error as not having a shallow list is optional here.
shallowList, _ := r.Storer.Shallow()
var earliestShallow *plumbing.Hash
if len(shallowList) > 0 {
earliestShallow = &shallowList[0]
}
head, err := r.Head()
if err != nil {
return err
}
ff, err := isFastForward(r.Storer, head.Hash(), ref.Hash(), earliestShallow)
if err != nil {
return err
}
if !ff {
return ErrFastForwardMergeNotPossible
}
return r.Storer.SetReference(plumbing.NewHashReference(head.Name(), ref.Hash()))
}
// createNewObjectPack is a helper for RepackObjects taking care
// of creating a new pack. It is used so the PackfileWriter
// deferred close has the right scope.
func (r *Repository) createNewObjectPack(cfg *RepackConfig) (h plumbing.Hash, err error) {
ow := newObjectWalker(r.Storer)
err = ow.walkAllRefs()
if err != nil {
return h, err
}
objs := make([]plumbing.Hash, 0, len(ow.seen))
for h := range ow.seen {
objs = append(objs, h)
}
pfw, ok := r.Storer.(storer.PackfileWriter)
if !ok {
return h, fmt.Errorf("Repository storer is not a storer.PackfileWriter")
}
wc, err := pfw.PackfileWriter()
if err != nil {
return h, err
}
defer ioutil.CheckClose(wc, &err)
scfg, err := r.Config()
if err != nil {
return h, err
}
enc := packfile.NewEncoder(wc, r.Storer, cfg.UseRefDeltas)
h, err = enc.Encode(objs, scfg.Pack.Window)
if err != nil {
return h, err
}
// Delete the packed, loose objects.
if los, ok := r.Storer.(storer.LooseObjectStorer); ok {
err = los.ForEachObjectHash(func(hash plumbing.Hash) error {
if ow.isSeen(hash) {
err = los.DeleteLooseObject(hash)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return h, err
}
}
return h, err
}
func expandPartialHash(st storer.EncodedObjectStorer, prefix []byte) (hashes []plumbing.Hash) {
// The fast version is implemented by storage/filesystem.ObjectStorage.
type fastIter interface {
HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error)
}
if fi, ok := st.(fastIter); ok {
h, err := fi.HashesWithPrefix(prefix)
if err != nil {
return nil
}
return h
}
// Slow path.
iter, err := st.IterEncodedObjects(plumbing.AnyObject)
if err != nil {
return nil
}
iter.ForEach(func(obj plumbing.EncodedObject) error {
h := obj.Hash()
if bytes.HasPrefix(h[:], prefix) {
hashes = append(hashes, h)
}
return nil
})
return
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/signer.go
================================================
package git
import (
"io"
"github.com/go-git/go-git/v5/plumbing"
)
// signableObject is an object which can be signed.
type signableObject interface {
EncodeWithoutSignature(o plumbing.EncodedObject) error
}
// Signer is an interface for signing git objects.
// message is a reader containing the encoded object to be signed.
// Implementors should return the encoded signature and an error if any.
// See https://git-scm.com/docs/gitformat-signature for more information.
type Signer interface {
Sign(message io.Reader) ([]byte, error)
}
func signObject(signer Signer, obj signableObject) ([]byte, error) {
encoded := &plumbing.MemoryObject{}
if err := obj.EncodeWithoutSignature(encoded); err != nil {
return nil, err
}
r, err := encoded.Reader()
if err != nil {
return nil, err
}
return signer.Sign(r)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/status.go
================================================
package git
import (
"bytes"
"fmt"
"path/filepath"
mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// Status represents the current status of a Worktree.
// The key of the map is the path of the file.
type Status map[string]*FileStatus
// File returns the FileStatus for a given path, if the FileStatus doesn't
// exists a new FileStatus is added to the map using the path as key.
func (s Status) File(path string) *FileStatus {
if _, ok := (s)[path]; !ok {
s[path] = &FileStatus{Worktree: Untracked, Staging: Untracked}
}
return s[path]
}
// IsUntracked checks if file for given path is 'Untracked'
func (s Status) IsUntracked(path string) bool {
stat, ok := (s)[filepath.ToSlash(path)]
return ok && stat.Worktree == Untracked
}
// IsClean returns true if all the files are in Unmodified status.
func (s Status) IsClean() bool {
for _, status := range s {
if status.Worktree != Unmodified || status.Staging != Unmodified {
return false
}
}
return true
}
func (s Status) String() string {
buf := bytes.NewBuffer(nil)
for path, status := range s {
if status.Staging == Unmodified && status.Worktree == Unmodified {
continue
}
if status.Staging == Renamed {
path = fmt.Sprintf("%s -> %s", path, status.Extra)
}
fmt.Fprintf(buf, "%c%c %s\n", status.Staging, status.Worktree, path)
}
return buf.String()
}
// FileStatus contains the status of a file in the worktree
type FileStatus struct {
// Staging is the status of a file in the staging area
Staging StatusCode
// Worktree is the status of a file in the worktree
Worktree StatusCode
// Extra contains extra information, such as the previous name in a rename
Extra string
}
// StatusCode status code of a file in the Worktree
type StatusCode byte
const (
Unmodified StatusCode = ' '
Untracked StatusCode = '?'
Modified StatusCode = 'M'
Added StatusCode = 'A'
Deleted StatusCode = 'D'
Renamed StatusCode = 'R'
Copied StatusCode = 'C'
UpdatedButUnmerged StatusCode = 'U'
)
// StatusStrategy defines the different types of strategies when processing
// the worktree status.
type StatusStrategy int
const (
// TODO: (V6) Review the default status strategy.
// TODO: (V6) Review the type used to represent Status, to enable lazy
// processing of statuses going direct to the backing filesystem.
defaultStatusStrategy = Empty
// Empty starts its status map from empty. Missing entries for a given
// path means that the file is untracked. This causes a known issue (#119)
// whereby unmodified files can be incorrectly reported as untracked.
//
// This can be used when returning the changed state within a modified Worktree.
// For example, to check whether the current worktree is clean.
Empty StatusStrategy = 0
// Preload goes through all existing nodes from the index and add them to the
// status map as unmodified. This is currently the most reliable strategy
// although it comes at a performance cost in large repositories.
//
// This method is recommended when fetching the status of unmodified files.
// For example, to confirm the status of a specific file that is either
// untracked or unmodified.
Preload StatusStrategy = 1
)
func (s StatusStrategy) new(w *Worktree) (Status, error) {
switch s {
case Preload:
return preloadStatus(w)
case Empty:
return make(Status), nil
}
return nil, fmt.Errorf("%w: %+v", ErrUnsupportedStatusStrategy, s)
}
func preloadStatus(w *Worktree) (Status, error) {
idx, err := w.r.Storer.Index()
if err != nil {
return nil, err
}
idxRoot := mindex.NewRootNode(idx)
nodes := []noder.Noder{idxRoot}
status := make(Status)
for len(nodes) > 0 {
var node noder.Noder
node, nodes = nodes[0], nodes[1:]
if node.IsDir() {
children, err := node.Children()
if err != nil {
return nil, err
}
nodes = append(nodes, children...)
continue
}
fs := status.File(node.Name())
fs.Worktree = Unmodified
fs.Staging = Unmodified
}
return status, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/config.go
================================================
package filesystem
import (
"os"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-git/v5/utils/ioutil"
)
type ConfigStorage struct {
dir *dotgit.DotGit
}
func (c *ConfigStorage) Config() (conf *config.Config, err error) {
f, err := c.dir.Config()
if err != nil {
if os.IsNotExist(err) {
return config.NewConfig(), nil
}
return nil, err
}
defer ioutil.CheckClose(f, &err)
return config.ReadConfig(f)
}
func (c *ConfigStorage) SetConfig(cfg *config.Config) (err error) {
if err = cfg.Validate(); err != nil {
return err
}
f, err := c.dir.ConfigWriter()
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
b, err := cfg.Marshal()
if err != nil {
return err
}
_, err = f.Write(b)
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/deltaobject.go
================================================
package filesystem
import (
"github.com/go-git/go-git/v5/plumbing"
)
type deltaObject struct {
plumbing.EncodedObject
base plumbing.Hash
hash plumbing.Hash
size int64
}
func newDeltaObject(
obj plumbing.EncodedObject,
hash plumbing.Hash,
base plumbing.Hash,
size int64) plumbing.DeltaObject {
return &deltaObject{
EncodedObject: obj,
hash: hash,
base: base,
size: size,
}
}
func (o *deltaObject) BaseHash() plumbing.Hash {
return o.base
}
func (o *deltaObject) ActualSize() int64 {
return o.size
}
func (o *deltaObject) ActualHash() plumbing.Hash {
return o.hash
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit.go
================================================
// https://github.com/git/git/blob/master/Documentation/gitrepository-layout.txt
package dotgit
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
"path"
"path/filepath"
"reflect"
"runtime"
"sort"
"strings"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-git/v5/storage"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/helper/chroot"
)
const (
suffix = ".git"
packedRefsPath = "packed-refs"
configPath = "config"
indexPath = "index"
shallowPath = "shallow"
modulePath = "modules"
objectsPath = "objects"
packPath = "pack"
refsPath = "refs"
branchesPath = "branches"
hooksPath = "hooks"
infoPath = "info"
remotesPath = "remotes"
logsPath = "logs"
worktreesPath = "worktrees"
alternatesPath = "alternates"
tmpPackedRefsPrefix = "._packed-refs"
packPrefix = "pack-"
packExt = ".pack"
idxExt = ".idx"
)
var (
// ErrNotFound is returned by New when the path is not found.
ErrNotFound = errors.New("path not found")
// ErrIdxNotFound is returned by Idxfile when the idx file is not found
ErrIdxNotFound = errors.New("idx file not found")
// ErrPackfileNotFound is returned by Packfile when the packfile is not found
ErrPackfileNotFound = errors.New("packfile not found")
// ErrConfigNotFound is returned by Config when the config is not found
ErrConfigNotFound = errors.New("config file not found")
// ErrPackedRefsDuplicatedRef is returned when a duplicated reference is
// found in the packed-ref file. This is usually the case for corrupted git
// repositories.
ErrPackedRefsDuplicatedRef = errors.New("duplicated ref found in packed-ref file")
// ErrPackedRefsBadFormat is returned when the packed-ref file corrupt.
ErrPackedRefsBadFormat = errors.New("malformed packed-ref")
// ErrSymRefTargetNotFound is returned when a symbolic reference is
// targeting a non-existing object. This usually means the repository
// is corrupt.
ErrSymRefTargetNotFound = errors.New("symbolic reference target not found")
// ErrIsDir is returned when a reference file is attempting to be read,
// but the path specified is a directory.
ErrIsDir = errors.New("reference path is a directory")
// ErrEmptyRefFile is returned when a reference file is attempted to be read,
// but the file is empty
ErrEmptyRefFile = errors.New("ref file is empty")
)
// Options holds configuration for the storage.
type Options struct {
// ExclusiveAccess means that the filesystem is not modified externally
// while the repo is open.
ExclusiveAccess bool
// KeepDescriptors makes the file descriptors to be reused but they will
// need to be manually closed calling Close().
KeepDescriptors bool
// AlternatesFS provides the billy filesystem to be used for Git Alternates.
// If none is provided, it falls back to using the underlying instance used for
// DotGit.
AlternatesFS billy.Filesystem
}
// The DotGit type represents a local git repository on disk. This
// type is not zero-value-safe, use the New function to initialize it.
type DotGit struct {
options Options
fs billy.Filesystem
// incoming object directory information
incomingChecked bool
incomingDirName string
objectList []plumbing.Hash // sorted
objectMap map[plumbing.Hash]struct{}
packList []plumbing.Hash
packMap map[plumbing.Hash]struct{}
files map[plumbing.Hash]billy.File
}
// New returns a DotGit value ready to be used. The path argument must
// be the absolute path of a git repository directory (e.g.
// "/foo/bar/.git").
func New(fs billy.Filesystem) *DotGit {
return NewWithOptions(fs, Options{})
}
// NewWithOptions sets non default configuration options.
// See New for complete help.
func NewWithOptions(fs billy.Filesystem, o Options) *DotGit {
return &DotGit{
options: o,
fs: fs,
}
}
// Initialize creates all the folder scaffolding.
func (d *DotGit) Initialize() error {
mustExists := []string{
d.fs.Join("objects", "info"),
d.fs.Join("objects", "pack"),
d.fs.Join("refs", "heads"),
d.fs.Join("refs", "tags"),
}
for _, path := range mustExists {
_, err := d.fs.Stat(path)
if err == nil {
continue
}
if !os.IsNotExist(err) {
return err
}
if err := d.fs.MkdirAll(path, os.ModeDir|os.ModePerm); err != nil {
return err
}
}
return nil
}
// Close closes all opened files.
func (d *DotGit) Close() error {
var firstError error
if d.files != nil {
for _, f := range d.files {
err := f.Close()
if err != nil && firstError == nil {
firstError = err
continue
}
}
d.files = nil
}
if firstError != nil {
return firstError
}
return nil
}
// ConfigWriter returns a file pointer for write to the config file
func (d *DotGit) ConfigWriter() (billy.File, error) {
return d.fs.Create(configPath)
}
// Config returns a file pointer for read to the config file
func (d *DotGit) Config() (billy.File, error) {
return d.fs.Open(configPath)
}
// IndexWriter returns a file pointer for write to the index file
func (d *DotGit) IndexWriter() (billy.File, error) {
return d.fs.Create(indexPath)
}
// Index returns a file pointer for read to the index file
func (d *DotGit) Index() (billy.File, error) {
return d.fs.Open(indexPath)
}
// ShallowWriter returns a file pointer for write to the shallow file
func (d *DotGit) ShallowWriter() (billy.File, error) {
return d.fs.Create(shallowPath)
}
// Shallow returns a file pointer for read to the shallow file
func (d *DotGit) Shallow() (billy.File, error) {
f, err := d.fs.Open(shallowPath)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
return f, nil
}
// NewObjectPack return a writer for a new packfile, it saves the packfile to
// disk and also generates and save the index for the given packfile.
func (d *DotGit) NewObjectPack() (*PackWriter, error) {
d.cleanPackList()
return newPackWrite(d.fs)
}
// ObjectPacks returns the list of availables packfiles
func (d *DotGit) ObjectPacks() ([]plumbing.Hash, error) {
if !d.options.ExclusiveAccess {
return d.objectPacks()
}
err := d.genPackList()
if err != nil {
return nil, err
}
return d.packList, nil
}
func (d *DotGit) objectPacks() ([]plumbing.Hash, error) {
packDir := d.fs.Join(objectsPath, packPath)
files, err := d.fs.ReadDir(packDir)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
var packs []plumbing.Hash
for _, f := range files {
n := f.Name()
if !strings.HasSuffix(n, packExt) || !strings.HasPrefix(n, packPrefix) {
continue
}
h := plumbing.NewHash(n[5 : len(n)-5]) // pack-(hash).pack
if h.IsZero() {
// Ignore files with badly-formatted names.
continue
}
packs = append(packs, h)
}
return packs, nil
}
func (d *DotGit) objectPackPath(hash plumbing.Hash, extension string) string {
return d.fs.Join(objectsPath, packPath, fmt.Sprintf("pack-%s.%s", hash.String(), extension))
}
func (d *DotGit) objectPackOpen(hash plumbing.Hash, extension string) (billy.File, error) {
if d.options.KeepDescriptors && extension == "pack" {
if d.files == nil {
d.files = make(map[plumbing.Hash]billy.File)
}
f, ok := d.files[hash]
if ok {
return f, nil
}
}
err := d.hasPack(hash)
if err != nil {
return nil, err
}
path := d.objectPackPath(hash, extension)
pack, err := d.fs.Open(path)
if err != nil {
if os.IsNotExist(err) {
return nil, ErrPackfileNotFound
}
return nil, err
}
if d.options.KeepDescriptors && extension == "pack" {
d.files[hash] = pack
}
return pack, nil
}
// ObjectPack returns a fs.File of the given packfile
func (d *DotGit) ObjectPack(hash plumbing.Hash) (billy.File, error) {
err := d.hasPack(hash)
if err != nil {
return nil, err
}
return d.objectPackOpen(hash, `pack`)
}
// ObjectPackIdx returns a fs.File of the index file for a given packfile
func (d *DotGit) ObjectPackIdx(hash plumbing.Hash) (billy.File, error) {
err := d.hasPack(hash)
if err != nil {
return nil, err
}
return d.objectPackOpen(hash, `idx`)
}
func (d *DotGit) DeleteOldObjectPackAndIndex(hash plumbing.Hash, t time.Time) error {
d.cleanPackList()
path := d.objectPackPath(hash, `pack`)
if !t.IsZero() {
fi, err := d.fs.Stat(path)
if err != nil {
return err
}
// too new, skip deletion.
if !fi.ModTime().Before(t) {
return nil
}
}
err := d.fs.Remove(path)
if err != nil {
return err
}
return d.fs.Remove(d.objectPackPath(hash, `idx`))
}
// NewObject return a writer for a new object file.
func (d *DotGit) NewObject() (*ObjectWriter, error) {
d.cleanObjectList()
return newObjectWriter(d.fs)
}
// ObjectsWithPrefix returns the hashes of objects that have the given prefix.
func (d *DotGit) ObjectsWithPrefix(prefix []byte) ([]plumbing.Hash, error) {
// Handle edge cases.
if len(prefix) < 1 {
return d.Objects()
} else if len(prefix) > len(plumbing.ZeroHash) {
return nil, nil
}
if d.options.ExclusiveAccess {
err := d.genObjectList()
if err != nil {
return nil, err
}
// Rely on d.objectList being sorted.
// Figure out the half-open interval defined by the prefix.
first := sort.Search(len(d.objectList), func(i int) bool {
// Same as plumbing.HashSlice.Less.
return bytes.Compare(d.objectList[i][:], prefix) >= 0
})
lim := len(d.objectList)
if limPrefix, overflow := incBytes(prefix); !overflow {
lim = sort.Search(len(d.objectList), func(i int) bool {
// Same as plumbing.HashSlice.Less.
return bytes.Compare(d.objectList[i][:], limPrefix) >= 0
})
}
return d.objectList[first:lim], nil
}
// This is the slow path.
var objects []plumbing.Hash
var n int
err := d.ForEachObjectHash(func(hash plumbing.Hash) error {
n++
if bytes.HasPrefix(hash[:], prefix) {
objects = append(objects, hash)
}
return nil
})
if err != nil {
return nil, err
}
return objects, nil
}
// Objects returns a slice with the hashes of objects found under the
// .git/objects/ directory.
func (d *DotGit) Objects() ([]plumbing.Hash, error) {
if d.options.ExclusiveAccess {
err := d.genObjectList()
if err != nil {
return nil, err
}
return d.objectList, nil
}
var objects []plumbing.Hash
err := d.ForEachObjectHash(func(hash plumbing.Hash) error {
objects = append(objects, hash)
return nil
})
if err != nil {
return nil, err
}
return objects, nil
}
// ForEachObjectHash iterates over the hashes of objects found under the
// .git/objects/ directory and executes the provided function.
func (d *DotGit) ForEachObjectHash(fun func(plumbing.Hash) error) error {
if !d.options.ExclusiveAccess {
return d.forEachObjectHash(fun)
}
err := d.genObjectList()
if err != nil {
return err
}
for _, h := range d.objectList {
err := fun(h)
if err != nil {
return err
}
}
return nil
}
func (d *DotGit) forEachObjectHash(fun func(plumbing.Hash) error) error {
files, err := d.fs.ReadDir(objectsPath)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
for _, f := range files {
if f.IsDir() && len(f.Name()) == 2 && isHex(f.Name()) {
base := f.Name()
d, err := d.fs.ReadDir(d.fs.Join(objectsPath, base))
if err != nil {
return err
}
for _, o := range d {
h := plumbing.NewHash(base + o.Name())
if h.IsZero() {
// Ignore files with badly-formatted names.
continue
}
err = fun(h)
if err != nil {
return err
}
}
}
}
return nil
}
func (d *DotGit) cleanObjectList() {
d.objectMap = nil
d.objectList = nil
}
func (d *DotGit) genObjectList() error {
if d.objectMap != nil {
return nil
}
d.objectMap = make(map[plumbing.Hash]struct{})
populate := func(h plumbing.Hash) error {
d.objectList = append(d.objectList, h)
d.objectMap[h] = struct{}{}
return nil
}
if err := d.forEachObjectHash(populate); err != nil {
return err
}
plumbing.HashesSort(d.objectList)
return nil
}
func (d *DotGit) hasObject(h plumbing.Hash) error {
if !d.options.ExclusiveAccess {
return nil
}
err := d.genObjectList()
if err != nil {
return err
}
_, ok := d.objectMap[h]
if !ok {
return plumbing.ErrObjectNotFound
}
return nil
}
func (d *DotGit) cleanPackList() {
d.packMap = nil
d.packList = nil
}
func (d *DotGit) genPackList() error {
if d.packMap != nil {
return nil
}
op, err := d.objectPacks()
if err != nil {
return err
}
d.packMap = make(map[plumbing.Hash]struct{})
d.packList = nil
for _, h := range op {
d.packList = append(d.packList, h)
d.packMap[h] = struct{}{}
}
return nil
}
func (d *DotGit) hasPack(h plumbing.Hash) error {
if !d.options.ExclusiveAccess {
return nil
}
err := d.genPackList()
if err != nil {
return err
}
_, ok := d.packMap[h]
if !ok {
return ErrPackfileNotFound
}
return nil
}
func (d *DotGit) objectPath(h plumbing.Hash) string {
hex := h.String()
return d.fs.Join(objectsPath, hex[0:2], hex[2:hash.HexSize])
}
// incomingObjectPath is intended to add support for a git pre-receive hook
// to be written it adds support for go-git to find objects in an "incoming"
// directory, so that the library can be used to write a pre-receive hook
// that deals with the incoming objects.
//
// More on git hooks found here : https://git-scm.com/docs/githooks
// More on 'quarantine'/incoming directory here:
//
// https://git-scm.com/docs/git-receive-pack
func (d *DotGit) incomingObjectPath(h plumbing.Hash) string {
hString := h.String()
if d.incomingDirName == "" {
return d.fs.Join(objectsPath, hString[0:2], hString[2:hash.HexSize])
}
return d.fs.Join(objectsPath, d.incomingDirName, hString[0:2], hString[2:hash.HexSize])
}
// hasIncomingObjects searches for an incoming directory and keeps its name
// so it doesn't have to be found each time an object is accessed.
func (d *DotGit) hasIncomingObjects() bool {
if !d.incomingChecked {
directoryContents, err := d.fs.ReadDir(objectsPath)
if err == nil {
for _, file := range directoryContents {
if file.IsDir() && (strings.HasPrefix(file.Name(), "tmp_objdir-incoming-") ||
// Before Git 2.35 incoming commits directory had another prefix
strings.HasPrefix(file.Name(), "incoming-")) {
d.incomingDirName = file.Name()
}
}
}
d.incomingChecked = true
}
return d.incomingDirName != ""
}
// Object returns a fs.File pointing the object file, if exists
func (d *DotGit) Object(h plumbing.Hash) (billy.File, error) {
err := d.hasObject(h)
if err != nil {
return nil, err
}
obj1, err1 := d.fs.Open(d.objectPath(h))
if os.IsNotExist(err1) && d.hasIncomingObjects() {
obj2, err2 := d.fs.Open(d.incomingObjectPath(h))
if err2 != nil {
return obj1, err1
}
return obj2, err2
}
return obj1, err1
}
// ObjectStat returns a os.FileInfo pointing the object file, if exists
func (d *DotGit) ObjectStat(h plumbing.Hash) (os.FileInfo, error) {
err := d.hasObject(h)
if err != nil {
return nil, err
}
obj1, err1 := d.fs.Stat(d.objectPath(h))
if os.IsNotExist(err1) && d.hasIncomingObjects() {
obj2, err2 := d.fs.Stat(d.incomingObjectPath(h))
if err2 != nil {
return obj1, err1
}
return obj2, err2
}
return obj1, err1
}
// ObjectDelete removes the object file, if exists
func (d *DotGit) ObjectDelete(h plumbing.Hash) error {
d.cleanObjectList()
err1 := d.fs.Remove(d.objectPath(h))
if os.IsNotExist(err1) && d.hasIncomingObjects() {
err2 := d.fs.Remove(d.incomingObjectPath(h))
if err2 != nil {
return err1
}
return err2
}
return err1
}
func (d *DotGit) readReferenceFrom(rd io.Reader, name string) (ref *plumbing.Reference, err error) {
b, err := io.ReadAll(rd)
if err != nil {
return nil, err
}
if len(b) == 0 {
return nil, ErrEmptyRefFile
}
line := strings.TrimSpace(string(b))
return plumbing.NewReferenceFromStrings(name, line), nil
}
// checkReferenceAndTruncate reads the reference from the given file, or the `pack-refs` file if
// the file was empty. Then it checks that the old reference matches the stored reference and
// truncates the file.
func (d *DotGit) checkReferenceAndTruncate(f billy.File, old *plumbing.Reference) error {
if old == nil {
return nil
}
ref, err := d.readReferenceFrom(f, old.Name().String())
if errors.Is(err, ErrEmptyRefFile) {
// This may happen if the reference is being read from a newly created file.
// In that case, try getting the reference from the packed refs file.
ref, err = d.packedRef(old.Name())
}
if err != nil {
return err
}
if ref.Hash() != old.Hash() {
return storage.ErrReferenceHasChanged
}
_, err = f.Seek(0, io.SeekStart)
if err != nil {
return err
}
return f.Truncate(0)
}
func (d *DotGit) SetRef(r, old *plumbing.Reference) error {
var content string
switch r.Type() {
case plumbing.SymbolicReference:
content = fmt.Sprintf("ref: %s\n", r.Target())
case plumbing.HashReference:
content = fmt.Sprintln(r.Hash().String())
}
fileName := r.Name().String()
return d.setRef(fileName, content, old)
}
// Refs scans the git directory collecting references, which it returns.
// Symbolic references are resolved and included in the output.
func (d *DotGit) Refs() ([]*plumbing.Reference, error) {
var refs []*plumbing.Reference
seen := make(map[plumbing.ReferenceName]bool)
if err := d.addRefFromHEAD(&refs); err != nil {
return nil, err
}
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
return nil, err
}
if err := d.addRefsFromPackedRefs(&refs, seen); err != nil {
return nil, err
}
return refs, nil
}
// Ref returns the reference for a given reference name.
func (d *DotGit) Ref(name plumbing.ReferenceName) (*plumbing.Reference, error) {
ref, err := d.readReferenceFile(".", name.String())
if err == nil {
return ref, nil
}
return d.packedRef(name)
}
func (d *DotGit) findPackedRefsInFile(f billy.File, recv refsRecv) error {
s := bufio.NewScanner(f)
for s.Scan() {
ref, err := d.processLine(s.Text())
if err != nil {
return err
}
if !recv(ref) {
// skip parse
return nil
}
}
if err := s.Err(); err != nil {
return err
}
return nil
}
// refsRecv: returning true means that the reference continues to be resolved, otherwise it is stopped, which will speed up the lookup of a single reference.
type refsRecv func(*plumbing.Reference) bool
func (d *DotGit) findPackedRefs(recv refsRecv) error {
f, err := d.fs.Open(packedRefsPath)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
defer ioutil.CheckClose(f, &err)
return d.findPackedRefsInFile(f, recv)
}
func (d *DotGit) packedRef(name plumbing.ReferenceName) (*plumbing.Reference, error) {
var ref *plumbing.Reference
if err := d.findPackedRefs(func(r *plumbing.Reference) bool {
if r != nil && r.Name() == name {
ref = r
// ref found
return false
}
return true
}); err != nil {
return nil, err
}
if ref != nil {
return ref, nil
}
return nil, plumbing.ErrReferenceNotFound
}
// RemoveRef removes a reference by name.
func (d *DotGit) RemoveRef(name plumbing.ReferenceName) error {
path := d.fs.Join(".", name.String())
_, err := d.fs.Stat(path)
if err == nil {
err = d.fs.Remove(path)
// Drop down to remove it from the packed refs file, too.
}
if err != nil && !os.IsNotExist(err) {
return err
}
return d.rewritePackedRefsWithoutRef(name)
}
func refsRecvFunc(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) refsRecv {
return func(r *plumbing.Reference) bool {
if r != nil && !seen[r.Name()] {
*refs = append(*refs, r)
seen[r.Name()] = true
}
return true
}
}
func (d *DotGit) addRefsFromPackedRefs(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) (err error) {
return d.findPackedRefs(refsRecvFunc(refs, seen))
}
func (d *DotGit) addRefsFromPackedRefsFile(refs *[]*plumbing.Reference, f billy.File, seen map[plumbing.ReferenceName]bool) (err error) {
return d.findPackedRefsInFile(f, refsRecvFunc(refs, seen))
}
func (d *DotGit) openAndLockPackedRefs(doCreate bool) (
pr billy.File, err error,
) {
var f billy.File
defer func() {
if err != nil && f != nil {
ioutil.CheckClose(f, &err)
}
}()
// File mode is retrieved from a constant defined in the target specific
// files (dotgit_rewrite_packed_refs_*). Some modes are not available
// in all filesystems.
openFlags := d.openAndLockPackedRefsMode()
if doCreate {
openFlags |= os.O_CREATE
}
// Keep trying to open and lock the file until we're sure the file
// didn't change between the open and the lock.
for {
f, err = d.fs.OpenFile(packedRefsPath, openFlags, 0600)
if err != nil {
if os.IsNotExist(err) && !doCreate {
return nil, nil
}
return nil, err
}
fi, err := d.fs.Stat(packedRefsPath)
if err != nil {
return nil, err
}
mtime := fi.ModTime()
err = f.Lock()
if err != nil {
return nil, err
}
fi, err = d.fs.Stat(packedRefsPath)
if err != nil {
return nil, err
}
if mtime.Equal(fi.ModTime()) {
break
}
// The file has changed since we opened it. Close and retry.
err = f.Close()
if err != nil {
return nil, err
}
}
return f, nil
}
func (d *DotGit) rewritePackedRefsWithoutRef(name plumbing.ReferenceName) (err error) {
pr, err := d.openAndLockPackedRefs(false)
if err != nil {
return err
}
if pr == nil {
return nil
}
defer ioutil.CheckClose(pr, &err)
// Creating the temp file in the same directory as the target file
// improves our chances for rename operation to be atomic.
tmp, err := d.fs.TempFile("", tmpPackedRefsPrefix)
if err != nil {
return err
}
tmpName := tmp.Name()
defer func() {
ioutil.CheckClose(tmp, &err)
_ = d.fs.Remove(tmpName) // don't check err, we might have renamed it
}()
s := bufio.NewScanner(pr)
found := false
for s.Scan() {
line := s.Text()
ref, err := d.processLine(line)
if err != nil {
return err
}
if ref != nil && ref.Name() == name {
found = true
continue
}
if _, err := fmt.Fprintln(tmp, line); err != nil {
return err
}
}
if err := s.Err(); err != nil {
return err
}
if !found {
return nil
}
return d.rewritePackedRefsWhileLocked(tmp, pr)
}
// process lines from a packed-refs file
func (d *DotGit) processLine(line string) (*plumbing.Reference, error) {
if len(line) == 0 {
return nil, nil
}
switch line[0] {
case '#': // comment - ignore
return nil, nil
case '^': // annotated tag commit of the previous line - ignore
return nil, nil
default:
ws := strings.Split(line, " ") // hash then ref
if len(ws) != 2 {
return nil, ErrPackedRefsBadFormat
}
return plumbing.NewReferenceFromStrings(ws[1], ws[0]), nil
}
}
func (d *DotGit) addRefsFromRefDir(refs *[]*plumbing.Reference, seen map[plumbing.ReferenceName]bool) error {
return d.walkReferencesTree(refs, []string{refsPath}, seen)
}
func (d *DotGit) walkReferencesTree(refs *[]*plumbing.Reference, relPath []string, seen map[plumbing.ReferenceName]bool) error {
files, err := d.fs.ReadDir(d.fs.Join(relPath...))
if err != nil {
if os.IsNotExist(err) {
// a race happened, and our directory is gone now
return nil
}
return err
}
for _, f := range files {
newRelPath := append(append([]string(nil), relPath...), f.Name())
if f.IsDir() {
if err = d.walkReferencesTree(refs, newRelPath, seen); err != nil {
return err
}
continue
}
ref, err := d.readReferenceFile(".", strings.Join(newRelPath, "/"))
if os.IsNotExist(err) {
// a race happened, and our file is gone now
continue
}
if err != nil {
return err
}
if ref != nil && !seen[ref.Name()] {
*refs = append(*refs, ref)
seen[ref.Name()] = true
}
}
return nil
}
func (d *DotGit) addRefFromHEAD(refs *[]*plumbing.Reference) error {
ref, err := d.readReferenceFile(".", "HEAD")
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
*refs = append(*refs, ref)
return nil
}
func (d *DotGit) readReferenceFile(path, name string) (ref *plumbing.Reference, err error) {
path = d.fs.Join(path, d.fs.Join(strings.Split(name, "/")...))
st, err := d.fs.Stat(path)
if err != nil {
return nil, err
}
if st.IsDir() {
return nil, ErrIsDir
}
f, err := d.fs.Open(path)
if err != nil {
return nil, err
}
defer ioutil.CheckClose(f, &err)
return d.readReferenceFrom(f, name)
}
func (d *DotGit) CountLooseRefs() (int, error) {
var refs []*plumbing.Reference
seen := make(map[plumbing.ReferenceName]bool)
if err := d.addRefsFromRefDir(&refs, seen); err != nil {
return 0, err
}
return len(refs), nil
}
// PackRefs packs all loose refs into the packed-refs file.
//
// This implementation only works under the assumption that the view
// of the file system won't be updated during this operation. This
// strategy would not work on a general file system though, without
// locking each loose reference and checking it again before deleting
// the file, because otherwise an updated reference could sneak in and
// then be deleted by the packed-refs process. Alternatively, every
// ref update could also lock packed-refs, so only one lock is
// required during ref-packing. But that would worsen performance in
// the common case.
//
// TODO: add an "all" boolean like the `git pack-refs --all` flag.
// When `all` is false, it would only pack refs that have already been
// packed, plus all tags.
func (d *DotGit) PackRefs() (err error) {
// Lock packed-refs, and create it if it doesn't exist yet.
f, err := d.openAndLockPackedRefs(true)
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
// Gather all refs using addRefsFromRefDir and addRefsFromPackedRefs.
var refs []*plumbing.Reference
seen := make(map[plumbing.ReferenceName]bool)
if err = d.addRefsFromRefDir(&refs, seen); err != nil {
return err
}
if len(refs) == 0 {
// Nothing to do!
return nil
}
numLooseRefs := len(refs)
if err = d.addRefsFromPackedRefsFile(&refs, f, seen); err != nil {
return err
}
// Write them all to a new temp packed-refs file.
tmp, err := d.fs.TempFile("", tmpPackedRefsPrefix)
if err != nil {
return err
}
tmpName := tmp.Name()
defer func() {
ioutil.CheckClose(tmp, &err)
_ = d.fs.Remove(tmpName) // don't check err, we might have renamed it
}()
w := bufio.NewWriter(tmp)
for _, ref := range refs {
_, err = w.WriteString(ref.String() + "\n")
if err != nil {
return err
}
}
err = w.Flush()
if err != nil {
return err
}
// Rename the temp packed-refs file.
err = d.rewritePackedRefsWhileLocked(tmp, f)
if err != nil {
return err
}
// Delete all the loose refs, while still holding the packed-refs
// lock.
for _, ref := range refs[:numLooseRefs] {
path := d.fs.Join(".", ref.Name().String())
err = d.fs.Remove(path)
if err != nil && !os.IsNotExist(err) {
return err
}
}
return nil
}
// Module return a billy.Filesystem pointing to the module folder
func (d *DotGit) Module(name string) (billy.Filesystem, error) {
return d.fs.Chroot(d.fs.Join(modulePath, name))
}
func (d *DotGit) AddAlternate(remote string) error {
altpath := d.fs.Join(objectsPath, infoPath, alternatesPath)
f, err := d.fs.OpenFile(altpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0640)
if err != nil {
return fmt.Errorf("cannot open file: %w", err)
}
defer f.Close()
// locking in windows throws an error, based on comments
// https://github.com/go-git/go-git/pull/860#issuecomment-1751823044
// do not lock on windows platform.
if runtime.GOOS != "windows" {
if err = f.Lock(); err != nil {
return fmt.Errorf("cannot lock file: %w", err)
}
defer f.Unlock()
}
line := path.Join(remote, objectsPath) + "\n"
_, err = io.WriteString(f, line)
if err != nil {
return fmt.Errorf("error writing 'alternates' file: %w", err)
}
return nil
}
// Alternates returns DotGit(s) based off paths in objects/info/alternates if
// available. This can be used to checks if it's a shared repository.
func (d *DotGit) Alternates() ([]*DotGit, error) {
altpath := d.fs.Join(objectsPath, infoPath, alternatesPath)
f, err := d.fs.Open(altpath)
if err != nil {
return nil, err
}
defer f.Close()
fs := d.options.AlternatesFS
if fs == nil {
fs = d.fs
}
var alternates []*DotGit
seen := make(map[string]struct{})
// Read alternate paths line-by-line and create DotGit objects.
scanner := bufio.NewScanner(f)
for scanner.Scan() {
path := scanner.Text()
// Avoid creating multiple dotgits for the same alternative path.
if _, ok := seen[path]; ok {
continue
}
seen[path] = struct{}{}
if filepath.IsAbs(path) {
// Handling absolute paths should be straight-forward. However, the default osfs (Chroot)
// tries to concatenate an abs path with the root path in some operations (e.g. Stat),
// which leads to unexpected errors. Therefore, make the path relative to the current FS instead.
if reflect.TypeOf(fs) == reflect.TypeOf(&chroot.ChrootHelper{}) {
path, err = filepath.Rel(fs.Root(), path)
if err != nil {
return nil, fmt.Errorf("cannot make path %q relative: %w", path, err)
}
}
} else {
// By Git conventions, relative paths should be based on the object database (.git/objects/info)
// location as per: https://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html
// However, due to the nature of go-git and its filesystem handling via Billy, paths cannot
// cross its "chroot boundaries". Therefore, ignore any "../" and treat the path from the
// fs root. If this is not correct based on the dotgit fs, set a different one via AlternatesFS.
abs := filepath.Join(string(filepath.Separator), filepath.ToSlash(path))
path = filepath.FromSlash(abs)
}
// Aligns with upstream behavior: exit if target path is not a valid directory.
if fi, err := fs.Stat(path); err != nil || !fi.IsDir() {
return nil, fmt.Errorf("invalid object directory %q: %w", path, err)
}
afs, err := fs.Chroot(filepath.Dir(path))
if err != nil {
return nil, fmt.Errorf("cannot chroot %q: %w", path, err)
}
alternates = append(alternates, New(afs))
}
if err = scanner.Err(); err != nil {
return nil, err
}
return alternates, nil
}
// Fs returns the underlying filesystem of the DotGit folder.
func (d *DotGit) Fs() billy.Filesystem {
return d.fs
}
func isHex(s string) bool {
for _, b := range []byte(s) {
if isNum(b) {
continue
}
if isHexAlpha(b) {
continue
}
return false
}
return true
}
func isNum(b byte) bool {
return b >= '0' && b <= '9'
}
func isHexAlpha(b byte) bool {
return b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F'
}
// incBytes increments a byte slice, which involves incrementing the
// right-most byte, and following carry leftward.
// It makes a copy so that the provided slice's underlying array is not modified.
// If the overall operation overflows (e.g. incBytes(0xff, 0xff)), the second return parameter indicates that.
func incBytes(in []byte) (out []byte, overflow bool) {
out = make([]byte, len(in))
copy(out, in)
for i := len(out) - 1; i >= 0; i-- {
out[i]++
if out[i] != 0 {
return // Didn't overflow.
}
}
overflow = true
return
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit_rewrite_packed_refs.go
================================================
package dotgit
import (
"io"
"os"
"runtime"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/utils/ioutil"
)
func (d *DotGit) openAndLockPackedRefsMode() int {
if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) {
return os.O_RDWR
}
return os.O_RDONLY
}
func (d *DotGit) rewritePackedRefsWhileLocked(
tmp billy.File, pr billy.File) error {
// Try plain rename. If we aren't using the bare Windows filesystem as the
// storage layer, we might be able to get away with a rename over a locked
// file.
err := d.fs.Rename(tmp.Name(), pr.Name())
if err == nil {
return nil
}
// If we are in a filesystem that does not support rename (e.g. sivafs)
// a full copy is done.
if err == billy.ErrNotSupported {
return d.copyNewFile(tmp, pr)
}
if runtime.GOOS != "windows" {
return err
}
// Otherwise, Windows doesn't let us rename over a locked file, so
// we have to do a straight copy. Unfortunately this could result
// in a partially-written file if the process fails before the
// copy completes.
return d.copyToExistingFile(tmp, pr)
}
func (d *DotGit) copyToExistingFile(tmp, pr billy.File) error {
_, err := pr.Seek(0, io.SeekStart)
if err != nil {
return err
}
err = pr.Truncate(0)
if err != nil {
return err
}
_, err = tmp.Seek(0, io.SeekStart)
if err != nil {
return err
}
_, err = io.Copy(pr, tmp)
return err
}
func (d *DotGit) copyNewFile(tmp billy.File, pr billy.File) (err error) {
prWrite, err := d.fs.Create(pr.Name())
if err != nil {
return err
}
defer ioutil.CheckClose(prWrite, &err)
_, err = tmp.Seek(0, io.SeekStart)
if err != nil {
return err
}
_, err = io.Copy(prWrite, tmp)
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/dotgit_setref.go
================================================
package dotgit
import (
"fmt"
"os"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-billy/v5"
)
func (d *DotGit) setRef(fileName, content string, old *plumbing.Reference) (err error) {
if billy.CapabilityCheck(d.fs, billy.ReadAndWriteCapability) {
return d.setRefRwfs(fileName, content, old)
}
return d.setRefNorwfs(fileName, content, old)
}
func (d *DotGit) setRefRwfs(fileName, content string, old *plumbing.Reference) (err error) {
// If we are not checking an old ref, just truncate the file.
mode := os.O_RDWR | os.O_CREATE
if old == nil {
mode |= os.O_TRUNC
}
f, err := d.fs.OpenFile(fileName, mode, 0666)
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
// Lock is unlocked by the deferred Close above. This is because Unlock
// does not imply a fsync and thus there would be a race between
// Unlock+Close and other concurrent writers. Adding Sync to go-billy
// could work, but this is better (and avoids superfluous syncs).
err = f.Lock()
if err != nil {
return err
}
// this is a no-op to call even when old is nil.
err = d.checkReferenceAndTruncate(f, old)
if err != nil {
return err
}
_, err = f.Write([]byte(content))
return err
}
// There are some filesystems that don't support opening files in RDWD mode.
// In these filesystems the standard SetRef function can not be used as it
// reads the reference file to check that it's not modified before updating it.
//
// This version of the function writes the reference without extra checks
// making it compatible with these simple filesystems. This is usually not
// a problem as they should be accessed by only one process at a time.
func (d *DotGit) setRefNorwfs(fileName, content string, old *plumbing.Reference) error {
_, err := d.fs.Stat(fileName)
if err == nil && old != nil {
fRead, err := d.fs.Open(fileName)
if err != nil {
return err
}
ref, err := d.readReferenceFrom(fRead, old.Name().String())
fRead.Close()
if err != nil {
return err
}
if ref.Hash() != old.Hash() {
return fmt.Errorf("reference has changed concurrently")
}
}
f, err := d.fs.Create(fileName)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write([]byte(content))
return err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/reader.go
================================================
package dotgit
import (
"fmt"
"io"
"os"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/objfile"
"github.com/go-git/go-git/v5/utils/ioutil"
)
var _ (plumbing.EncodedObject) = &EncodedObject{}
type EncodedObject struct {
dir *DotGit
h plumbing.Hash
t plumbing.ObjectType
sz int64
}
func (e *EncodedObject) Hash() plumbing.Hash {
return e.h
}
func (e *EncodedObject) Reader() (io.ReadCloser, error) {
f, err := e.dir.Object(e.h)
if err != nil {
if os.IsNotExist(err) {
return nil, plumbing.ErrObjectNotFound
}
return nil, err
}
r, err := objfile.NewReader(f)
if err != nil {
return nil, err
}
t, size, err := r.Header()
if err != nil {
_ = r.Close()
return nil, err
}
if t != e.t {
_ = r.Close()
return nil, objfile.ErrHeader
}
if size != e.sz {
_ = r.Close()
return nil, objfile.ErrHeader
}
return ioutil.NewReadCloserWithCloser(r, f.Close), nil
}
func (e *EncodedObject) SetType(plumbing.ObjectType) {}
func (e *EncodedObject) Type() plumbing.ObjectType {
return e.t
}
func (e *EncodedObject) Size() int64 {
return e.sz
}
func (e *EncodedObject) SetSize(int64) {}
func (e *EncodedObject) Writer() (io.WriteCloser, error) {
return nil, fmt.Errorf("not supported")
}
func NewEncodedObject(dir *DotGit, h plumbing.Hash, t plumbing.ObjectType, size int64) *EncodedObject {
return &EncodedObject{
dir: dir,
h: h,
t: t,
sz: size,
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/repository_filesystem.go
================================================
package dotgit
import (
"os"
"path/filepath"
"strings"
"github.com/go-git/go-billy/v5"
)
// RepositoryFilesystem is a billy.Filesystem compatible object wrapper
// which handles dot-git filesystem operations and supports commondir according to git scm layout:
// https://github.com/git/git/blob/master/Documentation/gitrepository-layout.txt
type RepositoryFilesystem struct {
dotGitFs billy.Filesystem
commonDotGitFs billy.Filesystem
}
func NewRepositoryFilesystem(dotGitFs, commonDotGitFs billy.Filesystem) *RepositoryFilesystem {
return &RepositoryFilesystem{
dotGitFs: dotGitFs,
commonDotGitFs: commonDotGitFs,
}
}
func (fs *RepositoryFilesystem) mapToRepositoryFsByPath(path string) billy.Filesystem {
// Nothing to decide if commondir not defined
if fs.commonDotGitFs == nil {
return fs.dotGitFs
}
cleanPath := filepath.Clean(path)
// Check exceptions for commondir (https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt)
switch cleanPath {
case fs.dotGitFs.Join(logsPath, "HEAD"):
return fs.dotGitFs
case fs.dotGitFs.Join(refsPath, "bisect"), fs.dotGitFs.Join(refsPath, "rewritten"), fs.dotGitFs.Join(refsPath, "worktree"):
return fs.dotGitFs
}
// Determine dot-git root by first path element.
// There are some elements which should always use commondir when commondir defined.
// Usual dot-git root will be used for the rest of files.
switch strings.Split(cleanPath, string(filepath.Separator))[0] {
case objectsPath, refsPath, packedRefsPath, configPath, branchesPath, hooksPath, infoPath, remotesPath, logsPath, shallowPath, worktreesPath:
return fs.commonDotGitFs
default:
return fs.dotGitFs
}
}
func (fs *RepositoryFilesystem) Create(filename string) (billy.File, error) {
return fs.mapToRepositoryFsByPath(filename).Create(filename)
}
func (fs *RepositoryFilesystem) Open(filename string) (billy.File, error) {
return fs.mapToRepositoryFsByPath(filename).Open(filename)
}
func (fs *RepositoryFilesystem) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
return fs.mapToRepositoryFsByPath(filename).OpenFile(filename, flag, perm)
}
func (fs *RepositoryFilesystem) Stat(filename string) (os.FileInfo, error) {
return fs.mapToRepositoryFsByPath(filename).Stat(filename)
}
func (fs *RepositoryFilesystem) Rename(oldpath, newpath string) error {
return fs.mapToRepositoryFsByPath(oldpath).Rename(oldpath, newpath)
}
func (fs *RepositoryFilesystem) Remove(filename string) error {
return fs.mapToRepositoryFsByPath(filename).Remove(filename)
}
func (fs *RepositoryFilesystem) Join(elem ...string) string {
return fs.dotGitFs.Join(elem...)
}
func (fs *RepositoryFilesystem) TempFile(dir, prefix string) (billy.File, error) {
return fs.mapToRepositoryFsByPath(dir).TempFile(dir, prefix)
}
func (fs *RepositoryFilesystem) ReadDir(path string) ([]os.FileInfo, error) {
return fs.mapToRepositoryFsByPath(path).ReadDir(path)
}
func (fs *RepositoryFilesystem) MkdirAll(filename string, perm os.FileMode) error {
return fs.mapToRepositoryFsByPath(filename).MkdirAll(filename, perm)
}
func (fs *RepositoryFilesystem) Lstat(filename string) (os.FileInfo, error) {
return fs.mapToRepositoryFsByPath(filename).Lstat(filename)
}
func (fs *RepositoryFilesystem) Symlink(target, link string) error {
return fs.mapToRepositoryFsByPath(target).Symlink(target, link)
}
func (fs *RepositoryFilesystem) Readlink(link string) (string, error) {
return fs.mapToRepositoryFsByPath(link).Readlink(link)
}
func (fs *RepositoryFilesystem) Chroot(path string) (billy.Filesystem, error) {
return fs.mapToRepositoryFsByPath(path).Chroot(path)
}
func (fs *RepositoryFilesystem) Root() string {
return fs.dotGitFs.Root()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/dotgit/writers.go
================================================
package dotgit
import (
"fmt"
"io"
"sync/atomic"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
"github.com/go-git/go-git/v5/plumbing/format/objfile"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/hash"
"github.com/go-git/go-billy/v5"
)
// PackWriter is a io.Writer that generates the packfile index simultaneously,
// a packfile.Decoder is used with a file reader to read the file being written
// this operation is synchronized with the write operations.
// The packfile is written in a temp file, when Close is called this file
// is renamed/moved (depends on the Filesystem implementation) to the final
// location, if the PackWriter is not used, nothing is written
type PackWriter struct {
Notify func(plumbing.Hash, *idxfile.Writer)
fs billy.Filesystem
fr, fw billy.File
synced *syncedReader
checksum plumbing.Hash
parser *packfile.Parser
writer *idxfile.Writer
result chan error
}
func newPackWrite(fs billy.Filesystem) (*PackWriter, error) {
fw, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_pack_")
if err != nil {
return nil, err
}
fr, err := fs.Open(fw.Name())
if err != nil {
return nil, err
}
writer := &PackWriter{
fs: fs,
fw: fw,
fr: fr,
synced: newSyncedReader(fw, fr),
result: make(chan error),
}
go writer.buildIndex()
return writer, nil
}
func (w *PackWriter) buildIndex() {
s := packfile.NewScanner(w.synced)
w.writer = new(idxfile.Writer)
var err error
w.parser, err = packfile.NewParser(s, w.writer)
if err != nil {
w.result <- err
return
}
checksum, err := w.parser.Parse()
if err != nil {
w.result <- err
return
}
w.checksum = checksum
w.result <- err
}
// waitBuildIndex waits until buildIndex function finishes, this can terminate
// with a packfile.ErrEmptyPackfile, this means that nothing was written so we
// ignore the error
func (w *PackWriter) waitBuildIndex() error {
err := <-w.result
if err == packfile.ErrEmptyPackfile {
return nil
}
return err
}
func (w *PackWriter) Write(p []byte) (int, error) {
return w.synced.Write(p)
}
// Close closes all the file descriptors and save the final packfile, if nothing
// was written, the tempfiles are deleted without writing a packfile.
func (w *PackWriter) Close() error {
defer func() {
if w.Notify != nil && w.writer != nil && w.writer.Finished() {
w.Notify(w.checksum, w.writer)
}
close(w.result)
}()
if err := w.synced.Close(); err != nil {
return err
}
if err := w.waitBuildIndex(); err != nil {
return err
}
if err := w.fr.Close(); err != nil {
return err
}
if err := w.fw.Close(); err != nil {
return err
}
if w.writer == nil || !w.writer.Finished() {
return w.clean()
}
return w.save()
}
func (w *PackWriter) clean() error {
return w.fs.Remove(w.fw.Name())
}
func (w *PackWriter) save() error {
base := w.fs.Join(objectsPath, packPath, fmt.Sprintf("pack-%s", w.checksum))
idx, err := w.fs.Create(fmt.Sprintf("%s.idx", base))
if err != nil {
return err
}
if err := w.encodeIdx(idx); err != nil {
return err
}
if err := idx.Close(); err != nil {
return err
}
return w.fs.Rename(w.fw.Name(), fmt.Sprintf("%s.pack", base))
}
func (w *PackWriter) encodeIdx(writer io.Writer) error {
idx, err := w.writer.Index()
if err != nil {
return err
}
e := idxfile.NewEncoder(writer)
_, err = e.Encode(idx)
return err
}
type syncedReader struct {
w io.Writer
r io.ReadSeeker
blocked, done uint32
written, read uint64
news chan bool
}
func newSyncedReader(w io.Writer, r io.ReadSeeker) *syncedReader {
return &syncedReader{
w: w,
r: r,
news: make(chan bool),
}
}
func (s *syncedReader) Write(p []byte) (n int, err error) {
defer func() {
written := atomic.AddUint64(&s.written, uint64(n))
read := atomic.LoadUint64(&s.read)
if written > read {
s.wake()
}
}()
n, err = s.w.Write(p)
return
}
func (s *syncedReader) Read(p []byte) (n int, err error) {
defer func() { atomic.AddUint64(&s.read, uint64(n)) }()
for {
s.sleep()
n, err = s.r.Read(p)
if err == io.EOF && !s.isDone() && n == 0 {
continue
}
break
}
return
}
func (s *syncedReader) isDone() bool {
return atomic.LoadUint32(&s.done) == 1
}
func (s *syncedReader) isBlocked() bool {
return atomic.LoadUint32(&s.blocked) == 1
}
func (s *syncedReader) wake() {
if s.isBlocked() {
atomic.StoreUint32(&s.blocked, 0)
s.news <- true
}
}
func (s *syncedReader) sleep() {
read := atomic.LoadUint64(&s.read)
written := atomic.LoadUint64(&s.written)
if read >= written {
atomic.StoreUint32(&s.blocked, 1)
<-s.news
}
}
func (s *syncedReader) Seek(offset int64, whence int) (int64, error) {
if whence == io.SeekCurrent {
return s.r.Seek(offset, whence)
}
p, err := s.r.Seek(offset, whence)
atomic.StoreUint64(&s.read, uint64(p))
return p, err
}
func (s *syncedReader) Close() error {
atomic.StoreUint32(&s.done, 1)
close(s.news)
return nil
}
type ObjectWriter struct {
objfile.Writer
fs billy.Filesystem
f billy.File
}
func newObjectWriter(fs billy.Filesystem) (*ObjectWriter, error) {
f, err := fs.TempFile(fs.Join(objectsPath, packPath), "tmp_obj_")
if err != nil {
return nil, err
}
return &ObjectWriter{
Writer: (*objfile.NewWriter(f)),
fs: fs,
f: f,
}, nil
}
func (w *ObjectWriter) Close() error {
if err := w.Writer.Close(); err != nil {
return err
}
if err := w.f.Close(); err != nil {
return err
}
return w.save()
}
func (w *ObjectWriter) save() error {
hex := w.Hash().String()
file := w.fs.Join(objectsPath, hex[0:2], hex[2:hash.HexSize])
return w.fs.Rename(w.f.Name(), file)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/index.go
================================================
package filesystem
import (
"bufio"
"os"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-git/v5/utils/ioutil"
)
type IndexStorage struct {
dir *dotgit.DotGit
}
func (s *IndexStorage) SetIndex(idx *index.Index) (err error) {
f, err := s.dir.IndexWriter()
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
bw := bufio.NewWriter(f)
defer func() {
if e := bw.Flush(); err == nil && e != nil {
err = e
}
}()
e := index.NewEncoder(bw)
err = e.Encode(idx)
return err
}
func (s *IndexStorage) Index() (i *index.Index, err error) {
idx := &index.Index{
Version: 2,
}
f, err := s.dir.Index()
if err != nil {
if os.IsNotExist(err) {
return idx, nil
}
return nil, err
}
defer ioutil.CheckClose(f, &err)
d := index.NewDecoder(f)
err = d.Decode(idx)
return idx, err
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/module.go
================================================
package filesystem
import (
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/storage"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
)
type ModuleStorage struct {
dir *dotgit.DotGit
}
func (s *ModuleStorage) Module(name string) (storage.Storer, error) {
fs, err := s.dir.Module(name)
if err != nil {
return nil, err
}
return NewStorage(fs, cache.NewObjectLRUDefault()), nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/object.go
================================================
package filesystem
import (
"bytes"
"io"
"os"
"sync"
"time"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
"github.com/go-git/go-git/v5/plumbing/format/objfile"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-billy/v5"
)
type ObjectStorage struct {
options Options
// objectCache is an object cache uses to cache delta's bases and also recently
// loaded loose objects
objectCache cache.Object
dir *dotgit.DotGit
index map[plumbing.Hash]idxfile.Index
packList []plumbing.Hash
packListIdx int
packfiles map[plumbing.Hash]*packfile.Packfile
}
// NewObjectStorage creates a new ObjectStorage with the given .git directory and cache.
func NewObjectStorage(dir *dotgit.DotGit, objectCache cache.Object) *ObjectStorage {
return NewObjectStorageWithOptions(dir, objectCache, Options{})
}
// NewObjectStorageWithOptions creates a new ObjectStorage with the given .git directory, cache and extra options
func NewObjectStorageWithOptions(dir *dotgit.DotGit, objectCache cache.Object, ops Options) *ObjectStorage {
return &ObjectStorage{
options: ops,
objectCache: objectCache,
dir: dir,
}
}
func (s *ObjectStorage) requireIndex() error {
if s.index != nil {
return nil
}
s.index = make(map[plumbing.Hash]idxfile.Index)
packs, err := s.dir.ObjectPacks()
if err != nil {
return err
}
for _, h := range packs {
if err := s.loadIdxFile(h); err != nil {
return err
}
}
return nil
}
// Reindex indexes again all packfiles. Useful if git changed packfiles externally
func (s *ObjectStorage) Reindex() {
s.index = nil
}
func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) (err error) {
f, err := s.dir.ObjectPackIdx(h)
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
idxf := idxfile.NewMemoryIndex()
d := idxfile.NewDecoder(f)
if err = d.Decode(idxf); err != nil {
return err
}
s.index[h] = idxf
return err
}
func (s *ObjectStorage) NewEncodedObject() plumbing.EncodedObject {
return &plumbing.MemoryObject{}
}
func (s *ObjectStorage) PackfileWriter() (io.WriteCloser, error) {
if err := s.requireIndex(); err != nil {
return nil, err
}
w, err := s.dir.NewObjectPack()
if err != nil {
return nil, err
}
w.Notify = func(h plumbing.Hash, writer *idxfile.Writer) {
index, err := writer.Index()
if err == nil {
s.index[h] = index
}
}
return w, nil
}
// SetEncodedObject adds a new object to the storage.
func (s *ObjectStorage) SetEncodedObject(o plumbing.EncodedObject) (h plumbing.Hash, err error) {
if o.Type() == plumbing.OFSDeltaObject || o.Type() == plumbing.REFDeltaObject {
return plumbing.ZeroHash, plumbing.ErrInvalidType
}
ow, err := s.dir.NewObject()
if err != nil {
return plumbing.ZeroHash, err
}
defer ioutil.CheckClose(ow, &err)
or, err := o.Reader()
if err != nil {
return plumbing.ZeroHash, err
}
defer ioutil.CheckClose(or, &err)
if err = ow.WriteHeader(o.Type(), o.Size()); err != nil {
return plumbing.ZeroHash, err
}
if _, err = io.Copy(ow, or); err != nil {
return plumbing.ZeroHash, err
}
return o.Hash(), err
}
// LazyWriter returns a lazy ObjectWriter that is bound to a DotGit file.
// It first write the header passing on the object type and size, so
// that the object contents can be written later, without the need to
// create a MemoryObject and buffering its entire contents into memory.
func (s *ObjectStorage) LazyWriter() (w io.WriteCloser, wh func(typ plumbing.ObjectType, sz int64) error, err error) {
ow, err := s.dir.NewObject()
if err != nil {
return nil, nil, err
}
return ow, ow.WriteHeader, nil
}
// HasEncodedObject returns nil if the object exists, without actually
// reading the object data from storage.
func (s *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
// Check unpacked objects
f, err := s.dir.Object(h)
if err != nil {
if !os.IsNotExist(err) {
return err
}
// Fall through to check packed objects.
} else {
defer ioutil.CheckClose(f, &err)
return nil
}
// Check packed objects.
if err := s.requireIndex(); err != nil {
return err
}
_, _, offset := s.findObjectInPackfile(h)
if offset == -1 {
return plumbing.ErrObjectNotFound
}
return nil
}
func (s *ObjectStorage) encodedObjectSizeFromUnpacked(h plumbing.Hash) (
size int64, err error) {
f, err := s.dir.Object(h)
if err != nil {
if os.IsNotExist(err) {
return 0, plumbing.ErrObjectNotFound
}
return 0, err
}
r, err := objfile.NewReader(f)
if err != nil {
return 0, err
}
defer ioutil.CheckClose(r, &err)
_, size, err = r.Header()
return size, err
}
func (s *ObjectStorage) packfile(idx idxfile.Index, pack plumbing.Hash) (*packfile.Packfile, error) {
if p := s.packfileFromCache(pack); p != nil {
return p, nil
}
f, err := s.dir.ObjectPack(pack)
if err != nil {
return nil, err
}
var p *packfile.Packfile
if s.objectCache != nil {
p = packfile.NewPackfileWithCache(idx, s.dir.Fs(), f, s.objectCache, s.options.LargeObjectThreshold)
} else {
p = packfile.NewPackfile(idx, s.dir.Fs(), f, s.options.LargeObjectThreshold)
}
return p, s.storePackfileInCache(pack, p)
}
func (s *ObjectStorage) packfileFromCache(hash plumbing.Hash) *packfile.Packfile {
if s.packfiles == nil {
if s.options.KeepDescriptors {
s.packfiles = make(map[plumbing.Hash]*packfile.Packfile)
} else if s.options.MaxOpenDescriptors > 0 {
s.packList = make([]plumbing.Hash, s.options.MaxOpenDescriptors)
s.packfiles = make(map[plumbing.Hash]*packfile.Packfile, s.options.MaxOpenDescriptors)
}
}
return s.packfiles[hash]
}
func (s *ObjectStorage) storePackfileInCache(hash plumbing.Hash, p *packfile.Packfile) error {
if s.options.KeepDescriptors {
s.packfiles[hash] = p
return nil
}
if s.options.MaxOpenDescriptors <= 0 {
return nil
}
// start over as the limit of packList is hit
if s.packListIdx >= len(s.packList) {
s.packListIdx = 0
}
// close the existing packfile if open
if next := s.packList[s.packListIdx]; !next.IsZero() {
open := s.packfiles[next]
delete(s.packfiles, next)
if open != nil {
if err := open.Close(); err != nil {
return err
}
}
}
// cache newly open packfile
s.packList[s.packListIdx] = hash
s.packfiles[hash] = p
s.packListIdx++
return nil
}
func (s *ObjectStorage) encodedObjectSizeFromPackfile(h plumbing.Hash) (
size int64, err error) {
if err := s.requireIndex(); err != nil {
return 0, err
}
pack, _, offset := s.findObjectInPackfile(h)
if offset == -1 {
return 0, plumbing.ErrObjectNotFound
}
idx := s.index[pack]
hash, err := idx.FindHash(offset)
if err == nil {
obj, ok := s.objectCache.Get(hash)
if ok {
return obj.Size(), nil
}
} else if err != nil && err != plumbing.ErrObjectNotFound {
return 0, err
}
p, err := s.packfile(idx, pack)
if err != nil {
return 0, err
}
if !s.options.KeepDescriptors && s.options.MaxOpenDescriptors == 0 {
defer ioutil.CheckClose(p, &err)
}
return p.GetSizeByOffset(offset)
}
// EncodedObjectSize returns the plaintext size of the given object,
// without actually reading the full object data from storage.
func (s *ObjectStorage) EncodedObjectSize(h plumbing.Hash) (
size int64, err error) {
size, err = s.encodedObjectSizeFromUnpacked(h)
if err != nil && err != plumbing.ErrObjectNotFound {
return 0, err
} else if err == nil {
return size, nil
}
return s.encodedObjectSizeFromPackfile(h)
}
// EncodedObject returns the object with the given hash, by searching for it in
// the packfile and the git object directories.
func (s *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) {
var obj plumbing.EncodedObject
var err error
if s.index != nil {
obj, err = s.getFromPackfile(h, false)
if err == plumbing.ErrObjectNotFound {
obj, err = s.getFromUnpacked(h)
}
} else {
obj, err = s.getFromUnpacked(h)
if err == plumbing.ErrObjectNotFound {
obj, err = s.getFromPackfile(h, false)
}
}
// If the error is still object not found, check if it's a shared object
// repository.
if err == plumbing.ErrObjectNotFound {
dotgits, e := s.dir.Alternates()
if e == nil {
// Create a new object storage with the DotGit(s) and check for the
// required hash object. Skip when not found.
for _, dg := range dotgits {
o := NewObjectStorage(dg, s.objectCache)
enobj, enerr := o.EncodedObject(t, h)
if enerr != nil {
continue
}
return enobj, nil
}
}
}
if err != nil {
return nil, err
}
if plumbing.AnyObject != t && obj.Type() != t {
return nil, plumbing.ErrObjectNotFound
}
return obj, nil
}
// DeltaObject returns the object with the given hash, by searching for
// it in the packfile and the git object directories.
func (s *ObjectStorage) DeltaObject(t plumbing.ObjectType,
h plumbing.Hash) (plumbing.EncodedObject, error) {
obj, err := s.getFromUnpacked(h)
if err == plumbing.ErrObjectNotFound {
obj, err = s.getFromPackfile(h, true)
}
if err != nil {
return nil, err
}
if plumbing.AnyObject != t && obj.Type() != t {
return nil, plumbing.ErrObjectNotFound
}
return obj, nil
}
func (s *ObjectStorage) getFromUnpacked(h plumbing.Hash) (obj plumbing.EncodedObject, err error) {
f, err := s.dir.Object(h)
if err != nil {
if os.IsNotExist(err) {
return nil, plumbing.ErrObjectNotFound
}
return nil, err
}
defer ioutil.CheckClose(f, &err)
if cacheObj, found := s.objectCache.Get(h); found {
return cacheObj, nil
}
r, err := objfile.NewReader(f)
if err != nil {
return nil, err
}
defer ioutil.CheckClose(r, &err)
t, size, err := r.Header()
if err != nil {
return nil, err
}
if s.options.LargeObjectThreshold > 0 && size > s.options.LargeObjectThreshold {
obj = dotgit.NewEncodedObject(s.dir, h, t, size)
return obj, nil
}
obj = s.NewEncodedObject()
obj.SetType(t)
obj.SetSize(size)
w, err := obj.Writer()
if err != nil {
return nil, err
}
defer ioutil.CheckClose(w, &err)
bufp := copyBufferPool.Get().(*[]byte)
buf := *bufp
_, err = io.CopyBuffer(w, r, buf)
copyBufferPool.Put(bufp)
s.objectCache.Put(obj)
return obj, err
}
var copyBufferPool = sync.Pool{
New: func() interface{} {
b := make([]byte, 32*1024)
return &b
},
}
// Get returns the object with the given hash, by searching for it in
// the packfile.
func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) (
plumbing.EncodedObject, error) {
if err := s.requireIndex(); err != nil {
return nil, err
}
pack, hash, offset := s.findObjectInPackfile(h)
if offset == -1 {
return nil, plumbing.ErrObjectNotFound
}
idx := s.index[pack]
p, err := s.packfile(idx, pack)
if err != nil {
return nil, err
}
if !s.options.KeepDescriptors && s.options.MaxOpenDescriptors == 0 {
defer ioutil.CheckClose(p, &err)
}
if canBeDelta {
return s.decodeDeltaObjectAt(p, offset, hash)
}
return s.decodeObjectAt(p, offset)
}
func (s *ObjectStorage) decodeObjectAt(
p *packfile.Packfile,
offset int64,
) (plumbing.EncodedObject, error) {
hash, err := p.FindHash(offset)
if err == nil {
obj, ok := s.objectCache.Get(hash)
if ok {
return obj, nil
}
}
if err != nil && err != plumbing.ErrObjectNotFound {
return nil, err
}
return p.GetByOffset(offset)
}
func (s *ObjectStorage) decodeDeltaObjectAt(
p *packfile.Packfile,
offset int64,
hash plumbing.Hash,
) (plumbing.EncodedObject, error) {
scan := p.Scanner()
header, err := scan.SeekObjectHeader(offset)
if err != nil {
return nil, err
}
var (
base plumbing.Hash
)
switch header.Type {
case plumbing.REFDeltaObject:
base = header.Reference
case plumbing.OFSDeltaObject:
base, err = p.FindHash(header.OffsetReference)
if err != nil {
return nil, err
}
default:
return s.decodeObjectAt(p, offset)
}
obj := &plumbing.MemoryObject{}
obj.SetType(header.Type)
w, err := obj.Writer()
if err != nil {
return nil, err
}
if _, _, err := scan.NextObject(w); err != nil {
return nil, err
}
return newDeltaObject(obj, hash, base, header.Length), nil
}
func (s *ObjectStorage) findObjectInPackfile(h plumbing.Hash) (plumbing.Hash, plumbing.Hash, int64) {
for packfile, index := range s.index {
offset, err := index.FindOffset(h)
if err == nil {
return packfile, h, offset
}
}
return plumbing.ZeroHash, plumbing.ZeroHash, -1
}
// HashesWithPrefix returns all objects with a hash that starts with a prefix by searching for
// them in the packfile and the git object directories.
func (s *ObjectStorage) HashesWithPrefix(prefix []byte) ([]plumbing.Hash, error) {
hashes, err := s.dir.ObjectsWithPrefix(prefix)
if err != nil {
return nil, err
}
seen := hashListAsMap(hashes)
// TODO: This could be faster with some idxfile changes,
// or diving into the packfile.
if err := s.requireIndex(); err != nil {
return nil, err
}
for _, index := range s.index {
ei, err := index.Entries()
if err != nil {
return nil, err
}
for {
e, err := ei.Next()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
if bytes.HasPrefix(e.Hash[:], prefix) {
if _, ok := seen[e.Hash]; ok {
continue
}
hashes = append(hashes, e.Hash)
}
}
ei.Close()
}
return hashes, nil
}
// IterEncodedObjects returns an iterator for all the objects in the packfile
// with the given type.
func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) {
objects, err := s.dir.Objects()
if err != nil {
return nil, err
}
seen := make(map[plumbing.Hash]struct{})
var iters []storer.EncodedObjectIter
if len(objects) != 0 {
iters = append(iters, &objectsIter{s: s, t: t, h: objects})
seen = hashListAsMap(objects)
}
packi, err := s.buildPackfileIters(t, seen)
if err != nil {
return nil, err
}
iters = append(iters, packi)
return storer.NewMultiEncodedObjectIter(iters), nil
}
func (s *ObjectStorage) buildPackfileIters(
t plumbing.ObjectType,
seen map[plumbing.Hash]struct{},
) (storer.EncodedObjectIter, error) {
if err := s.requireIndex(); err != nil {
return nil, err
}
packs, err := s.dir.ObjectPacks()
if err != nil {
return nil, err
}
return &lazyPackfilesIter{
hashes: packs,
open: func(h plumbing.Hash) (storer.EncodedObjectIter, error) {
pack, err := s.dir.ObjectPack(h)
if err != nil {
return nil, err
}
return newPackfileIter(
s.dir.Fs(), pack, t, seen, s.index[h],
s.objectCache, s.options.KeepDescriptors,
s.options.LargeObjectThreshold,
)
},
}, nil
}
// Close closes all opened files.
func (s *ObjectStorage) Close() error {
var firstError error
if s.options.KeepDescriptors || s.options.MaxOpenDescriptors > 0 {
for _, packfile := range s.packfiles {
err := packfile.Close()
if firstError == nil && err != nil {
firstError = err
}
}
}
s.packfiles = nil
s.dir.Close()
return firstError
}
type lazyPackfilesIter struct {
hashes []plumbing.Hash
open func(h plumbing.Hash) (storer.EncodedObjectIter, error)
cur storer.EncodedObjectIter
}
func (it *lazyPackfilesIter) Next() (plumbing.EncodedObject, error) {
for {
if it.cur == nil {
if len(it.hashes) == 0 {
return nil, io.EOF
}
h := it.hashes[0]
it.hashes = it.hashes[1:]
sub, err := it.open(h)
if err == io.EOF {
continue
} else if err != nil {
return nil, err
}
it.cur = sub
}
ob, err := it.cur.Next()
if err == io.EOF {
it.cur.Close()
it.cur = nil
continue
} else if err != nil {
return nil, err
}
return ob, nil
}
}
func (it *lazyPackfilesIter) ForEach(cb func(plumbing.EncodedObject) error) error {
return storer.ForEachIterator(it, cb)
}
func (it *lazyPackfilesIter) Close() {
if it.cur != nil {
it.cur.Close()
it.cur = nil
}
it.hashes = nil
}
type packfileIter struct {
pack billy.File
iter storer.EncodedObjectIter
seen map[plumbing.Hash]struct{}
// tells whether the pack file should be left open after iteration or not
keepPack bool
}
// NewPackfileIter returns a new EncodedObjectIter for the provided packfile
// and object type. Packfile and index file will be closed after they're
// used. If keepPack is true the packfile won't be closed after the iteration
// finished.
func NewPackfileIter(
fs billy.Filesystem,
f billy.File,
idxFile billy.File,
t plumbing.ObjectType,
keepPack bool,
largeObjectThreshold int64,
) (storer.EncodedObjectIter, error) {
idx := idxfile.NewMemoryIndex()
if err := idxfile.NewDecoder(idxFile).Decode(idx); err != nil {
return nil, err
}
if err := idxFile.Close(); err != nil {
return nil, err
}
seen := make(map[plumbing.Hash]struct{})
return newPackfileIter(fs, f, t, seen, idx, nil, keepPack, largeObjectThreshold)
}
func newPackfileIter(
fs billy.Filesystem,
f billy.File,
t plumbing.ObjectType,
seen map[plumbing.Hash]struct{},
index idxfile.Index,
cache cache.Object,
keepPack bool,
largeObjectThreshold int64,
) (storer.EncodedObjectIter, error) {
var p *packfile.Packfile
if cache != nil {
p = packfile.NewPackfileWithCache(index, fs, f, cache, largeObjectThreshold)
} else {
p = packfile.NewPackfile(index, fs, f, largeObjectThreshold)
}
iter, err := p.GetByType(t)
if err != nil {
return nil, err
}
return &packfileIter{
pack: f,
iter: iter,
seen: seen,
keepPack: keepPack,
}, nil
}
func (iter *packfileIter) Next() (plumbing.EncodedObject, error) {
for {
obj, err := iter.iter.Next()
if err != nil {
return nil, err
}
if _, ok := iter.seen[obj.Hash()]; ok {
continue
}
return obj, nil
}
}
func (iter *packfileIter) ForEach(cb func(plumbing.EncodedObject) error) error {
for {
o, err := iter.Next()
if err != nil {
if err == io.EOF {
iter.Close()
return nil
}
return err
}
if err := cb(o); err != nil {
return err
}
}
}
func (iter *packfileIter) Close() {
iter.iter.Close()
if !iter.keepPack {
_ = iter.pack.Close()
}
}
type objectsIter struct {
s *ObjectStorage
t plumbing.ObjectType
h []plumbing.Hash
}
func (iter *objectsIter) Next() (plumbing.EncodedObject, error) {
if len(iter.h) == 0 {
return nil, io.EOF
}
obj, err := iter.s.getFromUnpacked(iter.h[0])
iter.h = iter.h[1:]
if err != nil {
return nil, err
}
if iter.t != plumbing.AnyObject && iter.t != obj.Type() {
return iter.Next()
}
return obj, err
}
func (iter *objectsIter) ForEach(cb func(plumbing.EncodedObject) error) error {
for {
o, err := iter.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if err := cb(o); err != nil {
return err
}
}
}
func (iter *objectsIter) Close() {
iter.h = []plumbing.Hash{}
}
func hashListAsMap(l []plumbing.Hash) map[plumbing.Hash]struct{} {
m := make(map[plumbing.Hash]struct{}, len(l))
for _, h := range l {
m[h] = struct{}{}
}
return m
}
func (s *ObjectStorage) ForEachObjectHash(fun func(plumbing.Hash) error) error {
err := s.dir.ForEachObjectHash(fun)
if err == storer.ErrStop {
return nil
}
return err
}
func (s *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) {
fi, err := s.dir.ObjectStat(hash)
if err != nil {
return time.Time{}, err
}
return fi.ModTime(), nil
}
func (s *ObjectStorage) DeleteLooseObject(hash plumbing.Hash) error {
return s.dir.ObjectDelete(hash)
}
func (s *ObjectStorage) ObjectPacks() ([]plumbing.Hash, error) {
return s.dir.ObjectPacks()
}
func (s *ObjectStorage) DeleteOldObjectPackAndIndex(h plumbing.Hash, t time.Time) error {
return s.dir.DeleteOldObjectPackAndIndex(h, t)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/reference.go
================================================
package filesystem
import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
)
type ReferenceStorage struct {
dir *dotgit.DotGit
}
func (r *ReferenceStorage) SetReference(ref *plumbing.Reference) error {
return r.dir.SetRef(ref, nil)
}
func (r *ReferenceStorage) CheckAndSetReference(ref, old *plumbing.Reference) error {
return r.dir.SetRef(ref, old)
}
func (r *ReferenceStorage) Reference(n plumbing.ReferenceName) (*plumbing.Reference, error) {
return r.dir.Ref(n)
}
func (r *ReferenceStorage) IterReferences() (storer.ReferenceIter, error) {
refs, err := r.dir.Refs()
if err != nil {
return nil, err
}
return storer.NewReferenceSliceIter(refs), nil
}
func (r *ReferenceStorage) RemoveReference(n plumbing.ReferenceName) error {
return r.dir.RemoveRef(n)
}
func (r *ReferenceStorage) CountLooseRefs() (int, error) {
return r.dir.CountLooseRefs()
}
func (r *ReferenceStorage) PackRefs() error {
return r.dir.PackRefs()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/shallow.go
================================================
package filesystem
import (
"bufio"
"fmt"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-git/v5/utils/ioutil"
)
// ShallowStorage where the shallow commits are stored, an internal to
// manipulate the shallow file
type ShallowStorage struct {
dir *dotgit.DotGit
}
// SetShallow save the shallows in the shallow file in the .git folder as one
// commit per line represented by 40-byte hexadecimal object terminated by a
// newline.
func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error {
f, err := s.dir.ShallowWriter()
if err != nil {
return err
}
defer ioutil.CheckClose(f, &err)
for _, h := range commits {
if _, err := fmt.Fprintf(f, "%s\n", h); err != nil {
return err
}
}
return err
}
// Shallow returns the shallow commits reading from shallo file from .git
func (s *ShallowStorage) Shallow() ([]plumbing.Hash, error) {
f, err := s.dir.Shallow()
if f == nil || err != nil {
return nil, err
}
defer ioutil.CheckClose(f, &err)
var hash []plumbing.Hash
scn := bufio.NewScanner(f)
for scn.Scan() {
hash = append(hash, plumbing.NewHash(scn.Text()))
}
return hash, scn.Err()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/filesystem/storage.go
================================================
// Package filesystem is a storage backend base on filesystems
package filesystem
import (
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/storage/filesystem/dotgit"
"github.com/go-git/go-billy/v5"
)
// Storage is an implementation of git.Storer that stores data on disk in the
// standard git format (this is, the .git directory). Zero values of this type
// are not safe to use, see the NewStorage function below.
type Storage struct {
fs billy.Filesystem
dir *dotgit.DotGit
ObjectStorage
ReferenceStorage
IndexStorage
ShallowStorage
ConfigStorage
ModuleStorage
}
// Options holds configuration for the storage.
type Options struct {
// ExclusiveAccess means that the filesystem is not modified externally
// while the repo is open.
ExclusiveAccess bool
// KeepDescriptors makes the file descriptors to be reused but they will
// need to be manually closed calling Close().
KeepDescriptors bool
// MaxOpenDescriptors is the max number of file descriptors to keep
// open. If KeepDescriptors is true, all file descriptors will remain open.
MaxOpenDescriptors int
// LargeObjectThreshold maximum object size (in bytes) that will be read in to memory.
// If left unset or set to 0 there is no limit
LargeObjectThreshold int64
// AlternatesFS provides the billy filesystem to be used for Git Alternates.
// If none is provided, it falls back to using the underlying instance used for
// DotGit.
AlternatesFS billy.Filesystem
}
// NewStorage returns a new Storage backed by a given `fs.Filesystem` and cache.
func NewStorage(fs billy.Filesystem, cache cache.Object) *Storage {
return NewStorageWithOptions(fs, cache, Options{})
}
// NewStorageWithOptions returns a new Storage with extra options,
// backed by a given `fs.Filesystem` and cache.
func NewStorageWithOptions(fs billy.Filesystem, cache cache.Object, ops Options) *Storage {
dirOps := dotgit.Options{
ExclusiveAccess: ops.ExclusiveAccess,
AlternatesFS: ops.AlternatesFS,
}
dir := dotgit.NewWithOptions(fs, dirOps)
return &Storage{
fs: fs,
dir: dir,
ObjectStorage: *NewObjectStorageWithOptions(dir, cache, ops),
ReferenceStorage: ReferenceStorage{dir: dir},
IndexStorage: IndexStorage{dir: dir},
ShallowStorage: ShallowStorage{dir: dir},
ConfigStorage: ConfigStorage{dir: dir},
ModuleStorage: ModuleStorage{dir: dir},
}
}
// Filesystem returns the underlying filesystem
func (s *Storage) Filesystem() billy.Filesystem {
return s.fs
}
// Init initializes .git directory
func (s *Storage) Init() error {
return s.dir.Initialize()
}
func (s *Storage) AddAlternate(remote string) error {
return s.dir.AddAlternate(remote)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/memory/storage.go
================================================
// Package memory is a storage backend base on memory
package memory
import (
"fmt"
"time"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/storage"
)
var ErrUnsupportedObjectType = fmt.Errorf("unsupported object type")
// Storage is an implementation of git.Storer that stores data on memory, being
// ephemeral. The use of this storage should be done in controlled environments,
// since the representation in memory of some repository can fill the machine
// memory. in the other hand this storage has the best performance.
type Storage struct {
ConfigStorage
ObjectStorage
ShallowStorage
IndexStorage
ReferenceStorage
ModuleStorage
}
// NewStorage returns a new Storage base on memory
func NewStorage() *Storage {
return &Storage{
ReferenceStorage: make(ReferenceStorage),
ConfigStorage: ConfigStorage{},
ShallowStorage: ShallowStorage{},
ObjectStorage: ObjectStorage{
Objects: make(map[plumbing.Hash]plumbing.EncodedObject),
Commits: make(map[plumbing.Hash]plumbing.EncodedObject),
Trees: make(map[plumbing.Hash]plumbing.EncodedObject),
Blobs: make(map[plumbing.Hash]plumbing.EncodedObject),
Tags: make(map[plumbing.Hash]plumbing.EncodedObject),
},
ModuleStorage: make(ModuleStorage),
}
}
type ConfigStorage struct {
config *config.Config
}
func (c *ConfigStorage) SetConfig(cfg *config.Config) error {
if err := cfg.Validate(); err != nil {
return err
}
c.config = cfg
return nil
}
func (c *ConfigStorage) Config() (*config.Config, error) {
if c.config == nil {
c.config = config.NewConfig()
}
return c.config, nil
}
type IndexStorage struct {
index *index.Index
}
func (c *IndexStorage) SetIndex(idx *index.Index) error {
c.index = idx
return nil
}
func (c *IndexStorage) Index() (*index.Index, error) {
if c.index == nil {
c.index = &index.Index{Version: 2}
}
return c.index, nil
}
type ObjectStorage struct {
Objects map[plumbing.Hash]plumbing.EncodedObject
Commits map[plumbing.Hash]plumbing.EncodedObject
Trees map[plumbing.Hash]plumbing.EncodedObject
Blobs map[plumbing.Hash]plumbing.EncodedObject
Tags map[plumbing.Hash]plumbing.EncodedObject
}
func (o *ObjectStorage) NewEncodedObject() plumbing.EncodedObject {
return &plumbing.MemoryObject{}
}
func (o *ObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) {
h := obj.Hash()
o.Objects[h] = obj
switch obj.Type() {
case plumbing.CommitObject:
o.Commits[h] = o.Objects[h]
case plumbing.TreeObject:
o.Trees[h] = o.Objects[h]
case plumbing.BlobObject:
o.Blobs[h] = o.Objects[h]
case plumbing.TagObject:
o.Tags[h] = o.Objects[h]
default:
return h, ErrUnsupportedObjectType
}
return h, nil
}
func (o *ObjectStorage) HasEncodedObject(h plumbing.Hash) (err error) {
if _, ok := o.Objects[h]; !ok {
return plumbing.ErrObjectNotFound
}
return nil
}
func (o *ObjectStorage) EncodedObjectSize(h plumbing.Hash) (
size int64, err error) {
obj, ok := o.Objects[h]
if !ok {
return 0, plumbing.ErrObjectNotFound
}
return obj.Size(), nil
}
func (o *ObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) {
obj, ok := o.Objects[h]
if !ok || (plumbing.AnyObject != t && obj.Type() != t) {
return nil, plumbing.ErrObjectNotFound
}
return obj, nil
}
func (o *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.EncodedObjectIter, error) {
var series []plumbing.EncodedObject
switch t {
case plumbing.AnyObject:
series = flattenObjectMap(o.Objects)
case plumbing.CommitObject:
series = flattenObjectMap(o.Commits)
case plumbing.TreeObject:
series = flattenObjectMap(o.Trees)
case plumbing.BlobObject:
series = flattenObjectMap(o.Blobs)
case plumbing.TagObject:
series = flattenObjectMap(o.Tags)
}
return storer.NewEncodedObjectSliceIter(series), nil
}
func flattenObjectMap(m map[plumbing.Hash]plumbing.EncodedObject) []plumbing.EncodedObject {
objects := make([]plumbing.EncodedObject, 0, len(m))
for _, obj := range m {
objects = append(objects, obj)
}
return objects
}
func (o *ObjectStorage) Begin() storer.Transaction {
return &TxObjectStorage{
Storage: o,
Objects: make(map[plumbing.Hash]plumbing.EncodedObject),
}
}
func (o *ObjectStorage) ForEachObjectHash(fun func(plumbing.Hash) error) error {
for h := range o.Objects {
err := fun(h)
if err != nil {
if err == storer.ErrStop {
return nil
}
return err
}
}
return nil
}
func (o *ObjectStorage) ObjectPacks() ([]plumbing.Hash, error) {
return nil, nil
}
func (o *ObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error {
return nil
}
var errNotSupported = fmt.Errorf("not supported")
func (o *ObjectStorage) LooseObjectTime(hash plumbing.Hash) (time.Time, error) {
return time.Time{}, errNotSupported
}
func (o *ObjectStorage) DeleteLooseObject(plumbing.Hash) error {
return errNotSupported
}
func (o *ObjectStorage) AddAlternate(remote string) error {
return errNotSupported
}
type TxObjectStorage struct {
Storage *ObjectStorage
Objects map[plumbing.Hash]plumbing.EncodedObject
}
func (tx *TxObjectStorage) SetEncodedObject(obj plumbing.EncodedObject) (plumbing.Hash, error) {
h := obj.Hash()
tx.Objects[h] = obj
return h, nil
}
func (tx *TxObjectStorage) EncodedObject(t plumbing.ObjectType, h plumbing.Hash) (plumbing.EncodedObject, error) {
obj, ok := tx.Objects[h]
if !ok || (plumbing.AnyObject != t && obj.Type() != t) {
return nil, plumbing.ErrObjectNotFound
}
return obj, nil
}
func (tx *TxObjectStorage) Commit() error {
for h, obj := range tx.Objects {
delete(tx.Objects, h)
if _, err := tx.Storage.SetEncodedObject(obj); err != nil {
return err
}
}
return nil
}
func (tx *TxObjectStorage) Rollback() error {
tx.Objects = make(map[plumbing.Hash]plumbing.EncodedObject)
return nil
}
type ReferenceStorage map[plumbing.ReferenceName]*plumbing.Reference
func (r ReferenceStorage) SetReference(ref *plumbing.Reference) error {
if ref != nil {
r[ref.Name()] = ref
}
return nil
}
func (r ReferenceStorage) CheckAndSetReference(ref, old *plumbing.Reference) error {
if ref == nil {
return nil
}
if old != nil {
tmp := r[ref.Name()]
if tmp != nil && tmp.Hash() != old.Hash() {
return storage.ErrReferenceHasChanged
}
}
r[ref.Name()] = ref
return nil
}
func (r ReferenceStorage) Reference(n plumbing.ReferenceName) (*plumbing.Reference, error) {
ref, ok := r[n]
if !ok {
return nil, plumbing.ErrReferenceNotFound
}
return ref, nil
}
func (r ReferenceStorage) IterReferences() (storer.ReferenceIter, error) {
var refs []*plumbing.Reference
for _, ref := range r {
refs = append(refs, ref)
}
return storer.NewReferenceSliceIter(refs), nil
}
func (r ReferenceStorage) CountLooseRefs() (int, error) {
return len(r), nil
}
func (r ReferenceStorage) PackRefs() error {
return nil
}
func (r ReferenceStorage) RemoveReference(n plumbing.ReferenceName) error {
delete(r, n)
return nil
}
type ShallowStorage []plumbing.Hash
func (s *ShallowStorage) SetShallow(commits []plumbing.Hash) error {
*s = commits
return nil
}
func (s ShallowStorage) Shallow() ([]plumbing.Hash, error) {
return s, nil
}
type ModuleStorage map[string]*Storage
func (s ModuleStorage) Module(name string) (storage.Storer, error) {
if m, ok := s[name]; ok {
return m, nil
}
m := NewStorage()
s[name] = m
return m, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/storage/storer.go
================================================
package storage
import (
"errors"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing/storer"
)
var ErrReferenceHasChanged = errors.New("reference has changed concurrently")
// Storer is a generic storage of objects, references and any information
// related to a particular repository. The package github.com/go-git/go-git/v5/storage
// contains two implementation a filesystem base implementation (such as `.git`)
// and a memory implementations being ephemeral
type Storer interface {
storer.EncodedObjectStorer
storer.ReferenceStorer
storer.ShallowStorer
storer.IndexStorer
config.ConfigStorer
ModuleStorer
}
// ModuleStorer allows interact with the modules' Storers
type ModuleStorer interface {
// Module returns a Storer representing a submodule, if not exists returns a
// new empty Storer is returned
Module(name string) (Storer, error)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/submodule.go
================================================
package git
import (
"bytes"
"context"
"errors"
"fmt"
"path"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/plumbing/transport"
)
var (
ErrSubmoduleAlreadyInitialized = errors.New("submodule already initialized")
ErrSubmoduleNotInitialized = errors.New("submodule not initialized")
)
// Submodule a submodule allows you to keep another Git repository in a
// subdirectory of your repository.
type Submodule struct {
// initialized defines if a submodule was already initialized.
initialized bool
c *config.Submodule
w *Worktree
}
// Config returns the submodule config
func (s *Submodule) Config() *config.Submodule {
return s.c
}
// Init initialize the submodule reading the recorded Entry in the index for
// the given submodule
func (s *Submodule) Init() error {
cfg, err := s.w.r.Config()
if err != nil {
return err
}
_, ok := cfg.Submodules[s.c.Name]
if ok {
return ErrSubmoduleAlreadyInitialized
}
s.initialized = true
cfg.Submodules[s.c.Name] = s.c
return s.w.r.Storer.SetConfig(cfg)
}
// Status returns the status of the submodule.
func (s *Submodule) Status() (*SubmoduleStatus, error) {
idx, err := s.w.r.Storer.Index()
if err != nil {
return nil, err
}
return s.status(idx)
}
func (s *Submodule) status(idx *index.Index) (*SubmoduleStatus, error) {
status := &SubmoduleStatus{
Path: s.c.Path,
}
e, err := idx.Entry(s.c.Path)
if err != nil && err != index.ErrEntryNotFound {
return nil, err
}
if e != nil {
status.Expected = e.Hash
}
if !s.initialized {
return status, nil
}
r, err := s.Repository()
if err != nil {
return nil, err
}
head, err := r.Head()
if err == nil {
status.Current = head.Hash()
}
if err != nil && err == plumbing.ErrReferenceNotFound {
err = nil
}
return status, err
}
// Repository returns the Repository represented by this submodule
func (s *Submodule) Repository() (*Repository, error) {
if !s.initialized {
return nil, ErrSubmoduleNotInitialized
}
storer, err := s.w.r.Storer.Module(s.c.Name)
if err != nil {
return nil, err
}
_, err = storer.Reference(plumbing.HEAD)
if err != nil && err != plumbing.ErrReferenceNotFound {
return nil, err
}
var exists bool
if err == nil {
exists = true
}
var worktree billy.Filesystem
if worktree, err = s.w.Filesystem.Chroot(s.c.Path); err != nil {
return nil, err
}
if exists {
return Open(storer, worktree)
}
r, err := Init(storer, worktree)
if err != nil {
return nil, err
}
moduleEndpoint, err := transport.NewEndpoint(s.c.URL)
if err != nil {
return nil, err
}
if !path.IsAbs(moduleEndpoint.Path) && moduleEndpoint.Protocol == "file" {
remotes, err := s.w.r.Remotes()
if err != nil {
return nil, err
}
rootEndpoint, err := transport.NewEndpoint(remotes[0].c.URLs[0])
if err != nil {
return nil, err
}
rootEndpoint.Path = path.Join(rootEndpoint.Path, moduleEndpoint.Path)
*moduleEndpoint = *rootEndpoint
}
_, err = r.CreateRemote(&config.RemoteConfig{
Name: DefaultRemoteName,
URLs: []string{moduleEndpoint.String()},
})
return r, err
}
// Update the registered submodule to match what the superproject expects, the
// submodule should be initialized first calling the Init method or setting in
// the options SubmoduleUpdateOptions.Init equals true
func (s *Submodule) Update(o *SubmoduleUpdateOptions) error {
return s.UpdateContext(context.Background(), o)
}
// UpdateContext the registered submodule to match what the superproject
// expects, the submodule should be initialized first calling the Init method or
// setting in the options SubmoduleUpdateOptions.Init equals true.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (s *Submodule) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error {
return s.update(ctx, o, plumbing.ZeroHash)
}
func (s *Submodule) update(ctx context.Context, o *SubmoduleUpdateOptions, forceHash plumbing.Hash) error {
if !s.initialized && !o.Init {
return ErrSubmoduleNotInitialized
}
if !s.initialized && o.Init {
if err := s.Init(); err != nil {
return err
}
}
idx, err := s.w.r.Storer.Index()
if err != nil {
return err
}
hash := forceHash
if hash.IsZero() {
e, err := idx.Entry(s.c.Path)
if err != nil {
return err
}
hash = e.Hash
}
r, err := s.Repository()
if err != nil {
return err
}
if err := s.fetchAndCheckout(ctx, r, o, hash); err != nil {
return err
}
return s.doRecursiveUpdate(ctx, r, o)
}
func (s *Submodule) doRecursiveUpdate(ctx context.Context, r *Repository, o *SubmoduleUpdateOptions) error {
if o.RecurseSubmodules == NoRecurseSubmodules {
return nil
}
w, err := r.Worktree()
if err != nil {
return err
}
l, err := w.Submodules()
if err != nil {
return err
}
new := &SubmoduleUpdateOptions{}
*new = *o
new.RecurseSubmodules--
return l.UpdateContext(ctx, new)
}
func (s *Submodule) fetchAndCheckout(
ctx context.Context, r *Repository, o *SubmoduleUpdateOptions, hash plumbing.Hash,
) error {
if !o.NoFetch {
err := r.FetchContext(ctx, &FetchOptions{Auth: o.Auth, Depth: o.Depth})
if err != nil && err != NoErrAlreadyUpToDate {
return err
}
}
w, err := r.Worktree()
if err != nil {
return err
}
// Handle a case when submodule refers to an orphaned commit that's still reachable
// through Git server using a special protocol capability[1].
//
// [1]: https://git-scm.com/docs/protocol-capabilities#_allow_reachable_sha1_in_want
if !o.NoFetch {
if _, err := w.r.Object(plumbing.AnyObject, hash); err != nil {
refSpec := config.RefSpec("+" + hash.String() + ":" + hash.String())
err := r.FetchContext(ctx, &FetchOptions{
Auth: o.Auth,
RefSpecs: []config.RefSpec{refSpec},
Depth: o.Depth,
})
if err != nil && err != NoErrAlreadyUpToDate && err != ErrExactSHA1NotSupported {
return err
}
}
}
if err := w.Checkout(&CheckoutOptions{Hash: hash}); err != nil {
return err
}
head := plumbing.NewHashReference(plumbing.HEAD, hash)
return r.Storer.SetReference(head)
}
// Submodules list of several submodules from the same repository.
type Submodules []*Submodule
// Init initializes the submodules in this list.
func (s Submodules) Init() error {
for _, sub := range s {
if err := sub.Init(); err != nil {
return err
}
}
return nil
}
// Update updates all the submodules in this list.
func (s Submodules) Update(o *SubmoduleUpdateOptions) error {
return s.UpdateContext(context.Background(), o)
}
// UpdateContext updates all the submodules in this list.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (s Submodules) UpdateContext(ctx context.Context, o *SubmoduleUpdateOptions) error {
for _, sub := range s {
if err := sub.UpdateContext(ctx, o); err != nil {
return err
}
}
return nil
}
// Status returns the status of the submodules.
func (s Submodules) Status() (SubmodulesStatus, error) {
var list SubmodulesStatus
var r *Repository
for _, sub := range s {
if r == nil {
r = sub.w.r
}
idx, err := r.Storer.Index()
if err != nil {
return nil, err
}
status, err := sub.status(idx)
if err != nil {
return nil, err
}
list = append(list, status)
}
return list, nil
}
// SubmodulesStatus contains the status for all submodiles in the worktree
type SubmodulesStatus []*SubmoduleStatus
// String is equivalent to `git submodule status`
func (s SubmodulesStatus) String() string {
buf := bytes.NewBuffer(nil)
for _, sub := range s {
fmt.Fprintln(buf, sub)
}
return buf.String()
}
// SubmoduleStatus contains the status for a submodule in the worktree
type SubmoduleStatus struct {
Path string
Current plumbing.Hash
Expected plumbing.Hash
Branch plumbing.ReferenceName
}
// IsClean is the HEAD of the submodule is equals to the expected commit
func (s *SubmoduleStatus) IsClean() bool {
return s.Current == s.Expected
}
// String is equivalent to `git submodule status `
//
// This will print the SHA-1 of the currently checked out commit for a
// submodule, along with the submodule path and the output of git describe fo
// the SHA-1. Each SHA-1 will be prefixed with - if the submodule is not
// initialized, + if the currently checked out submodule commit does not match
// the SHA-1 found in the index of the containing repository.
func (s *SubmoduleStatus) String() string {
var extra string
var status = ' '
if s.Current.IsZero() {
status = '-'
} else if !s.IsClean() {
status = '+'
}
if len(s.Branch) != 0 {
extra = string(s.Branch[5:])
} else if !s.Current.IsZero() {
extra = s.Current.String()[:7]
}
if extra != "" {
extra = fmt.Sprintf(" (%s)", extra)
}
return fmt.Sprintf("%c%s %s%s", status, s.Expected, s.Path, extra)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/binary/read.go
================================================
// Package binary implements syntax-sugar functions on top of the standard
// library binary package
package binary
import (
"bufio"
"encoding/binary"
"io"
"github.com/go-git/go-git/v5/plumbing"
)
// Read reads structured binary data from r into data. Bytes are read and
// decoded in BigEndian order
// https://golang.org/pkg/encoding/binary/#Read
func Read(r io.Reader, data ...interface{}) error {
for _, v := range data {
if err := binary.Read(r, binary.BigEndian, v); err != nil {
return err
}
}
return nil
}
// ReadUntil reads from r untin delim is found
func ReadUntil(r io.Reader, delim byte) ([]byte, error) {
if bufr, ok := r.(*bufio.Reader); ok {
return ReadUntilFromBufioReader(bufr, delim)
}
var buf [1]byte
value := make([]byte, 0, 16)
for {
if _, err := io.ReadFull(r, buf[:]); err != nil {
if err == io.EOF {
return nil, err
}
return nil, err
}
if buf[0] == delim {
return value, nil
}
value = append(value, buf[0])
}
}
// ReadUntilFromBufioReader is like bufio.ReadBytes but drops the delimiter
// from the result.
func ReadUntilFromBufioReader(r *bufio.Reader, delim byte) ([]byte, error) {
value, err := r.ReadBytes(delim)
if err != nil || len(value) == 0 {
return nil, err
}
return value[:len(value)-1], nil
}
// ReadVariableWidthInt reads and returns an int in Git VLQ special format:
//
// Ordinary VLQ has some redundancies, example: the number 358 can be
// encoded as the 2-octet VLQ 0x8166 or the 3-octet VLQ 0x808166 or the
// 4-octet VLQ 0x80808166 and so forth.
//
// To avoid these redundancies, the VLQ format used in Git removes this
// prepending redundancy and extends the representable range of shorter
// VLQs by adding an offset to VLQs of 2 or more octets in such a way
// that the lowest possible value for such an (N+1)-octet VLQ becomes
// exactly one more than the maximum possible value for an N-octet VLQ.
// In particular, since a 1-octet VLQ can store a maximum value of 127,
// the minimum 2-octet VLQ (0x8000) is assigned the value 128 instead of
// 0. Conversely, the maximum value of such a 2-octet VLQ (0xff7f) is
// 16511 instead of just 16383. Similarly, the minimum 3-octet VLQ
// (0x808000) has a value of 16512 instead of zero, which means
// that the maximum 3-octet VLQ (0xffff7f) is 2113663 instead of
// just 2097151. And so forth.
//
// This is how the offset is saved in C:
//
// dheader[pos] = ofs & 127;
// while (ofs >>= 7)
// dheader[--pos] = 128 | (--ofs & 127);
//
func ReadVariableWidthInt(r io.Reader) (int64, error) {
var c byte
if err := Read(r, &c); err != nil {
return 0, err
}
var v = int64(c & maskLength)
for c&maskContinue > 0 {
v++
if err := Read(r, &c); err != nil {
return 0, err
}
v = (v << lengthBits) + int64(c&maskLength)
}
return v, nil
}
const (
maskContinue = uint8(128) // 1000 000
maskLength = uint8(127) // 0111 1111
lengthBits = uint8(7) // subsequent bytes has 7 bits to store the length
)
// ReadUint64 reads 8 bytes and returns them as a BigEndian uint32
func ReadUint64(r io.Reader) (uint64, error) {
var v uint64
if err := binary.Read(r, binary.BigEndian, &v); err != nil {
return 0, err
}
return v, nil
}
// ReadUint32 reads 4 bytes and returns them as a BigEndian uint32
func ReadUint32(r io.Reader) (uint32, error) {
var v uint32
if err := binary.Read(r, binary.BigEndian, &v); err != nil {
return 0, err
}
return v, nil
}
// ReadUint16 reads 2 bytes and returns them as a BigEndian uint16
func ReadUint16(r io.Reader) (uint16, error) {
var v uint16
if err := binary.Read(r, binary.BigEndian, &v); err != nil {
return 0, err
}
return v, nil
}
// ReadHash reads a plumbing.Hash from r
func ReadHash(r io.Reader) (plumbing.Hash, error) {
var h plumbing.Hash
if err := binary.Read(r, binary.BigEndian, h[:]); err != nil {
return plumbing.ZeroHash, err
}
return h, nil
}
const sniffLen = 8000
// IsBinary detects if data is a binary value based on:
// http://git.kernel.org/cgit/git/git.git/tree/xdiff-interface.c?id=HEAD#n198
func IsBinary(r io.Reader) (bool, error) {
reader := bufio.NewReader(r)
c := 0
for {
if c == sniffLen {
break
}
b, err := reader.ReadByte()
if err == io.EOF {
break
}
if err != nil {
return false, err
}
if b == byte(0) {
return true, nil
}
c++
}
return false, nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/binary/write.go
================================================
package binary
import (
"encoding/binary"
"io"
)
// Write writes the binary representation of data into w, using BigEndian order
// https://golang.org/pkg/encoding/binary/#Write
func Write(w io.Writer, data ...interface{}) error {
for _, v := range data {
if err := binary.Write(w, binary.BigEndian, v); err != nil {
return err
}
}
return nil
}
func WriteVariableWidthInt(w io.Writer, n int64) error {
buf := []byte{byte(n & 0x7f)}
n >>= 7
for n != 0 {
n--
buf = append([]byte{0x80 | (byte(n & 0x7f))}, buf...)
n >>= 7
}
_, err := w.Write(buf)
return err
}
// WriteUint64 writes the binary representation of a uint64 into w, in BigEndian
// order
func WriteUint64(w io.Writer, value uint64) error {
return binary.Write(w, binary.BigEndian, value)
}
// WriteUint32 writes the binary representation of a uint32 into w, in BigEndian
// order
func WriteUint32(w io.Writer, value uint32) error {
return binary.Write(w, binary.BigEndian, value)
}
// WriteUint16 writes the binary representation of a uint16 into w, in BigEndian
// order
func WriteUint16(w io.Writer, value uint16) error {
return binary.Write(w, binary.BigEndian, value)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/diff/diff.go
================================================
// Package diff implements line oriented diffs, similar to the ancient
// Unix diff command.
//
// The current implementation is just a wrapper around Sergi's
// go-diff/diffmatchpatch library, which is a go port of Neil
// Fraser's google-diff-match-patch code
package diff
import (
"bytes"
"time"
"github.com/sergi/go-diff/diffmatchpatch"
)
// Do computes the (line oriented) modifications needed to turn the src
// string into the dst string. The underlying algorithm is Meyers,
// its complexity is O(N*d) where N is min(lines(src), lines(dst)) and d
// is the size of the diff.
func Do(src, dst string) (diffs []diffmatchpatch.Diff) {
// the default timeout is time.Second which may be too small under heavy load
return DoWithTimeout(src, dst, time.Hour)
}
// DoWithTimeout computes the (line oriented) modifications needed to turn the src
// string into the dst string. The `timeout` argument specifies the maximum
// amount of time it is allowed to spend in this function. If the timeout
// is exceeded, the parts of the strings which were not considered are turned into
// a bulk delete+insert and the half-baked suboptimal result is returned at once.
// The underlying algorithm is Meyers, its complexity is O(N*d) where N is
// min(lines(src), lines(dst)) and d is the size of the diff.
func DoWithTimeout(src, dst string, timeout time.Duration) (diffs []diffmatchpatch.Diff) {
dmp := diffmatchpatch.New()
dmp.DiffTimeout = timeout
wSrc, wDst, warray := dmp.DiffLinesToRunes(src, dst)
diffs = dmp.DiffMainRunes(wSrc, wDst, false)
diffs = dmp.DiffCharsToLines(diffs, warray)
return diffs
}
// Dst computes and returns the destination text.
func Dst(diffs []diffmatchpatch.Diff) string {
var text bytes.Buffer
for _, d := range diffs {
if d.Type != diffmatchpatch.DiffDelete {
text.WriteString(d.Text)
}
}
return text.String()
}
// Src computes and returns the source text
func Src(diffs []diffmatchpatch.Diff) string {
var text bytes.Buffer
for _, d := range diffs {
if d.Type != diffmatchpatch.DiffInsert {
text.WriteString(d.Text)
}
}
return text.String()
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/ioutil/common.go
================================================
// Package ioutil implements some I/O utility functions.
package ioutil
import (
"bufio"
"context"
"errors"
"io"
ctxio "github.com/jbenet/go-context/io"
)
type readPeeker interface {
io.Reader
Peek(int) ([]byte, error)
}
var (
ErrEmptyReader = errors.New("reader is empty")
)
// NonEmptyReader takes a reader and returns it if it is not empty, or
// `ErrEmptyReader` if it is empty. If there is an error when reading the first
// byte of the given reader, it will be propagated.
func NonEmptyReader(r io.Reader) (io.Reader, error) {
pr, ok := r.(readPeeker)
if !ok {
pr = bufio.NewReader(r)
}
_, err := pr.Peek(1)
if err == io.EOF {
return nil, ErrEmptyReader
}
if err != nil {
return nil, err
}
return pr, nil
}
type readCloser struct {
io.Reader
closer io.Closer
}
func (r *readCloser) Close() error {
return r.closer.Close()
}
// NewReadCloser creates an `io.ReadCloser` with the given `io.Reader` and
// `io.Closer`.
func NewReadCloser(r io.Reader, c io.Closer) io.ReadCloser {
return &readCloser{Reader: r, closer: c}
}
type readCloserCloser struct {
io.ReadCloser
closer func() error
}
func (r *readCloserCloser) Close() (err error) {
defer func() {
if err == nil {
err = r.closer()
return
}
_ = r.closer()
}()
return r.ReadCloser.Close()
}
// NewReadCloserWithCloser creates an `io.ReadCloser` with the given `io.ReaderCloser` and
// `io.Closer` that ensures that the closer is closed on close
func NewReadCloserWithCloser(r io.ReadCloser, c func() error) io.ReadCloser {
return &readCloserCloser{ReadCloser: r, closer: c}
}
type writeCloser struct {
io.Writer
closer io.Closer
}
func (r *writeCloser) Close() error {
return r.closer.Close()
}
// NewWriteCloser creates an `io.WriteCloser` with the given `io.Writer` and
// `io.Closer`.
func NewWriteCloser(w io.Writer, c io.Closer) io.WriteCloser {
return &writeCloser{Writer: w, closer: c}
}
type writeNopCloser struct {
io.Writer
}
func (writeNopCloser) Close() error { return nil }
// WriteNopCloser returns a WriteCloser with a no-op Close method wrapping
// the provided Writer w.
func WriteNopCloser(w io.Writer) io.WriteCloser {
return writeNopCloser{w}
}
type readerAtAsReader struct {
io.ReaderAt
offset int64
}
func (r *readerAtAsReader) Read(bs []byte) (int, error) {
n, err := r.ReaderAt.ReadAt(bs, r.offset)
r.offset += int64(n)
return n, err
}
func NewReaderUsingReaderAt(r io.ReaderAt, offset int64) io.Reader {
return &readerAtAsReader{
ReaderAt: r,
offset: offset,
}
}
// CheckClose calls Close on the given io.Closer. If the given *error points to
// nil, it will be assigned the error returned by Close. Otherwise, any error
// returned by Close will be ignored. CheckClose is usually called with defer.
func CheckClose(c io.Closer, err *error) {
if cerr := c.Close(); cerr != nil && *err == nil {
*err = cerr
}
}
// NewContextWriter wraps a writer to make it respect given Context.
// If there is a blocking write, the returned Writer will return whenever the
// context is cancelled (the return values are n=0 and err=ctx.Err()).
func NewContextWriter(ctx context.Context, w io.Writer) io.Writer {
return ctxio.NewWriter(ctx, w)
}
// NewContextReader wraps a reader to make it respect given Context.
// If there is a blocking read, the returned Reader will return whenever the
// context is cancelled (the return values are n=0 and err=ctx.Err()).
func NewContextReader(ctx context.Context, r io.Reader) io.Reader {
return ctxio.NewReader(ctx, r)
}
// NewContextWriteCloser as NewContextWriter but with io.Closer interface.
func NewContextWriteCloser(ctx context.Context, w io.WriteCloser) io.WriteCloser {
ctxw := ctxio.NewWriter(ctx, w)
return NewWriteCloser(ctxw, w)
}
// NewContextReadCloser as NewContextReader but with io.Closer interface.
func NewContextReadCloser(ctx context.Context, r io.ReadCloser) io.ReadCloser {
ctxr := ctxio.NewReader(ctx, r)
return NewReadCloser(ctxr, r)
}
type readerOnError struct {
io.Reader
notify func(error)
}
// NewReaderOnError returns a io.Reader that call the notify function when an
// unexpected (!io.EOF) error happens, after call Read function.
func NewReaderOnError(r io.Reader, notify func(error)) io.Reader {
return &readerOnError{r, notify}
}
// NewReadCloserOnError returns a io.ReadCloser that call the notify function
// when an unexpected (!io.EOF) error happens, after call Read function.
func NewReadCloserOnError(r io.ReadCloser, notify func(error)) io.ReadCloser {
return NewReadCloser(NewReaderOnError(r, notify), r)
}
func (r *readerOnError) Read(buf []byte) (n int, err error) {
n, err = r.Reader.Read(buf)
if err != nil && err != io.EOF {
r.notify(err)
}
return
}
type writerOnError struct {
io.Writer
notify func(error)
}
// NewWriterOnError returns a io.Writer that call the notify function when an
// unexpected (!io.EOF) error happens, after call Write function.
func NewWriterOnError(w io.Writer, notify func(error)) io.Writer {
return &writerOnError{w, notify}
}
// NewWriteCloserOnError returns a io.WriteCloser that call the notify function
// when an unexpected (!io.EOF) error happens, after call Write function.
func NewWriteCloserOnError(w io.WriteCloser, notify func(error)) io.WriteCloser {
return NewWriteCloser(NewWriterOnError(w, notify), w)
}
func (r *writerOnError) Write(p []byte) (n int, err error) {
n, err = r.Writer.Write(p)
if err != nil && err != io.EOF {
r.notify(err)
}
return
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/change.go
================================================
package merkletrie
import (
"errors"
"fmt"
"io"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
var (
ErrEmptyFileName = errors.New("empty filename in tree entry")
)
// Action values represent the kind of things a Change can represent:
// insertion, deletions or modifications of files.
type Action int
// The set of possible actions in a change.
const (
_ Action = iota
Insert
Delete
Modify
)
// String returns the action as a human readable text.
func (a Action) String() string {
switch a {
case Insert:
return "Insert"
case Delete:
return "Delete"
case Modify:
return "Modify"
default:
panic(fmt.Sprintf("unsupported action: %d", a))
}
}
// A Change value represent how a noder has change between to merkletries.
type Change struct {
// The noder before the change or nil if it was inserted.
From noder.Path
// The noder after the change or nil if it was deleted.
To noder.Path
}
// Action is convenience method that returns what Action c represents.
func (c *Change) Action() (Action, error) {
if c.From == nil && c.To == nil {
return Action(0), fmt.Errorf("malformed change: nil from and to")
}
if c.From == nil {
return Insert, nil
}
if c.To == nil {
return Delete, nil
}
return Modify, nil
}
// NewInsert returns a new Change representing the insertion of n.
func NewInsert(n noder.Path) Change { return Change{To: n} }
// NewDelete returns a new Change representing the deletion of n.
func NewDelete(n noder.Path) Change { return Change{From: n} }
// NewModify returns a new Change representing that a has been modified and
// it is now b.
func NewModify(a, b noder.Path) Change {
return Change{
From: a,
To: b,
}
}
// String returns a single change in human readable form, using the
// format: '<' + action + space + path + '>'. The contents of the file
// before or after the change are not included in this format.
//
// Example: inserting a file at the path a/b/c.txt will return "".
func (c Change) String() string {
action, err := c.Action()
if err != nil {
panic(err)
}
var path string
if action == Delete {
path = c.From.String()
} else {
path = c.To.String()
}
return fmt.Sprintf("<%s %s>", action, path)
}
// Changes is a list of changes between to merkletries.
type Changes []Change
// NewChanges returns an empty list of changes.
func NewChanges() Changes {
return Changes{}
}
// Add adds the change c to the list of changes.
func (l *Changes) Add(c Change) {
*l = append(*l, c)
}
// AddRecursiveInsert adds the required changes to insert all the
// file-like noders found in root, recursively.
func (l *Changes) AddRecursiveInsert(root noder.Path) error {
return l.addRecursive(root, NewInsert)
}
// AddRecursiveDelete adds the required changes to delete all the
// file-like noders found in root, recursively.
func (l *Changes) AddRecursiveDelete(root noder.Path) error {
return l.addRecursive(root, NewDelete)
}
type noderToChangeFn func(noder.Path) Change // NewInsert or NewDelete
func (l *Changes) addRecursive(root noder.Path, ctor noderToChangeFn) error {
if root.String() == "" {
return ErrEmptyFileName
}
if !root.IsDir() {
l.Add(ctor(root))
return nil
}
i, err := NewIterFromPath(root)
if err != nil {
return err
}
var current noder.Path
for {
if current, err = i.Step(); err != nil {
if err == io.EOF {
break
}
return err
}
if current.IsDir() {
continue
}
l.Add(ctor(current))
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/difftree.go
================================================
package merkletrie
// The focus of this difftree implementation is to save time by
// skipping whole directories if their hash is the same in both
// trees.
//
// The diff algorithm implemented here is based on the doubleiter
// type defined in this same package; we will iterate over both
// trees at the same time, while comparing the current noders in
// each iterator. Depending on how they differ we will output the
// corresponding changes and move the iterators further over both
// trees.
//
// The table below shows all the possible comparison results, along
// with what changes should we produce and how to advance the
// iterators.
//
// The table is implemented by the switches in this function,
// diffTwoNodes, diffTwoNodesSameName and diffTwoDirs.
//
// Many Bothans died to bring us this information, make sure you
// understand the table before modifying this code.
// # Cases
//
// When comparing noders in both trees you will find yourself in
// one of 169 possible cases, but if we ignore moves, we can
// simplify a lot the search space into the following table:
//
// - "-": nothing, no file or directory
// - a<>: an empty file named "a".
// - a<1>: a file named "a", with "1" as its contents.
// - a<2>: a file named "a", with "2" as its contents.
// - a(): an empty dir named "a".
// - a(...): a dir named "a", with some files and/or dirs inside (possibly
// empty).
// - a(;;;): a dir named "a", with some other files and/or dirs inside
// (possibly empty), which different from the ones in "a(...)".
//
// \ to - a<> a<1> a<2> a() a(...) a(;;;)
// from \
// - 00 01 02 03 04 05 06
// a<> 10 11 12 13 14 15 16
// a<1> 20 21 22 23 24 25 26
// a<2> 30 31 32 33 34 35 36
// a() 40 41 42 43 44 45 46
// a(...) 50 51 52 53 54 55 56
// a(;;;) 60 61 62 63 64 65 66
//
// Every (from, to) combination in the table is a special case, but
// some of them can be merged into some more general cases, for
// instance 11 and 22 can be merged into the general case: both
// noders are equal.
//
// Here is a full list of all the cases that are similar and how to
// merge them together into more general cases. Each general case
// is labeled with an uppercase letter for further reference, and it
// is followed by the pseudocode of the checks you have to perform
// on both noders to see if you are in such a case, the actions to
// perform (i.e. what changes to output) and how to advance the
// iterators of each tree to continue the comparison process.
//
// ## A. Impossible: 00
//
// ## B. Same thing on both sides: 11, 22, 33, 44, 55, 66
// - check: `SameName() && SameHash()`
// - action: do nothing.
// - advance: `FromNext(); ToNext()`
//
// ### C. To was created: 01, 02, 03, 04, 05, 06
// - check: `DifferentName() && ToBeforeFrom()`
// - action: insertRecursively(to)
// - advance: `ToNext()`
//
// ### D. From was deleted: 10, 20, 30, 40, 50, 60
// - check: `DifferentName() && FromBeforeTo()`
// - action: `DeleteRecursively(from)`
// - advance: `FromNext()`
//
// ### E. Empty file to file with contents: 12, 13
// - check: `SameName() && DifferentHash() && FromIsFile() &&
// ToIsFile() && FromIsEmpty()`
// - action: `modifyFile(from, to)`
// - advance: `FromNext()` or `FromStep()`
//
// ### E'. file with contents to empty file: 21, 31
// - check: `SameName() && DifferentHash() && FromIsFile() &&
// ToIsFile() && ToIsEmpty()`
// - action: `modifyFile(from, to)`
// - advance: `FromNext()` or `FromStep()`
//
// ### F. empty file to empty dir with the same name: 14
// - check: `SameName() && FromIsFile() && FromIsEmpty() &&
// ToIsDir() && ToIsEmpty()`
// - action: `DeleteFile(from); InsertEmptyDir(to)`
// - advance: `FromNext(); ToNext()`
//
// ### F'. empty dir to empty file of the same name: 41
// - check: `SameName() && FromIsDir() && FromIsEmpty &&
// ToIsFile() && ToIsEmpty()`
// - action: `DeleteEmptyDir(from); InsertFile(to)`
// - advance: `FromNext(); ToNext()` or step for any of them.
//
// ### G. empty file to non-empty dir of the same name: 15, 16
// - check: `SameName() && FromIsFile() && ToIsDir() &&
// FromIsEmpty() && ToIsNotEmpty()`
// - action: `DeleteFile(from); InsertDirRecursively(to)`
// - advance: `FromNext(); ToNext()`
//
// ### G'. non-empty dir to empty file of the same name: 51, 61
// - check: `SameName() && FromIsDir() && FromIsNotEmpty() &&
// ToIsFile() && FromIsEmpty()`
// - action: `DeleteDirRecursively(from); InsertFile(to)`
// - advance: `FromNext(); ToNext()`
//
// ### H. modify file contents: 23, 32
// - check: `SameName() && FromIsFile() && ToIsFile() &&
// FromIsNotEmpty() && ToIsNotEmpty()`
// - action: `ModifyFile(from, to)`
// - advance: `FromNext(); ToNext()`
//
// ### I. file with contents to empty dir: 24, 34
// - check: `SameName() && DifferentHash() && FromIsFile() &&
// FromIsNotEmpty() && ToIsDir() && ToIsEmpty()`
// - action: `DeleteFile(from); InsertEmptyDir(to)`
// - advance: `FromNext(); ToNext()`
//
// ### I'. empty dir to file with contents: 42, 43
// - check: `SameName() && DifferentHash() && FromIsDir() &&
// FromIsEmpty() && ToIsFile() && ToIsEmpty()`
// - action: `DeleteDir(from); InsertFile(to)`
// - advance: `FromNext(); ToNext()`
//
// ### J. file with contents to dir with contents: 25, 26, 35, 36
// - check: `SameName() && DifferentHash() && FromIsFile() &&
// FromIsNotEmpty() && ToIsDir() && ToIsNotEmpty()`
// - action: `DeleteFile(from); InsertDirRecursively(to)`
// - advance: `FromNext(); ToNext()`
//
// ### J'. dir with contents to file with contents: 52, 62, 53, 63
// - check: `SameName() && DifferentHash() && FromIsDir() &&
// FromIsNotEmpty() && ToIsFile() && ToIsNotEmpty()`
// - action: `DeleteDirRecursively(from); InsertFile(to)`
// - advance: `FromNext(); ToNext()`
//
// ### K. empty dir to dir with contents: 45, 46
// - check: `SameName() && DifferentHash() && FromIsDir() &&
// FromIsEmpty() && ToIsDir() && ToIsNotEmpty()`
// - action: `InsertChildrenRecursively(to)`
// - advance: `FromNext(); ToNext()`
//
// ### K'. dir with contents to empty dir: 54, 64
// - check: `SameName() && DifferentHash() && FromIsDir() &&
// FromIsEmpty() && ToIsDir() && ToIsNotEmpty()`
// - action: `DeleteChildrenRecursively(from)`
// - advance: `FromNext(); ToNext()`
//
// ### L. dir with contents to dir with different contents: 56, 65
// - check: `SameName() && DifferentHash() && FromIsDir() &&
// FromIsNotEmpty() && ToIsDir() && ToIsNotEmpty()`
// - action: nothing
// - advance: `FromStep(); ToStep()`
//
//
// All these cases can be further simplified by a truth table
// reduction process, in which we gather similar checks together to
// make the final code easier to read and understand.
//
// The first 6 columns are the outputs of the checks to perform on
// both noders. I have labeled them 1 to 6, this is what they mean:
//
// 1: SameName()
// 2: SameHash()
// 3: FromIsDir()
// 4: ToIsDir()
// 5: FromIsEmpty()
// 6: ToIsEmpty()
//
// The from and to columns are a fsnoder example of the elements
// that you will find on each tree under the specified comparison
// results (columns 1 to 6).
//
// The type column identifies the case we are into, from the list above.
//
// The type' column identifies the new set of reduced cases, using
// lowercase letters, and they are explained after the table.
//
// The last column is the set of actions and advances for each case.
//
// "---" means impossible except in case of hash collision.
//
// advance meaning:
// - NN: from.Next(); to.Next()
// - SS: from.Step(); to.Step()
//
// 1 2 3 4 5 6 | from | to |type|type'|action ; advance
// ------------+--------+--------+----+------------------------------------
// 0 0 0 0 0 0 | | | | | if !SameName() {
// . | | | | | if FromBeforeTo() {
// . | | | D | d | delete(from); from.Next()
// . | | | | | } else {
// . | | | C | c | insert(to); to.Next()
// . | | | | | }
// 0 1 1 1 1 1 | | | | | }
// 1 0 0 0 0 0 | a<1> | a<2> | H | e | modify(from, to); NN
// 1 0 0 0 0 1 | a<1> | a<> | E' | e | modify(from, to); NN
// 1 0 0 0 1 0 | a<> | a<1> | E | e | modify(from, to); NN
// 1 0 0 0 1 1 | ---- | ---- | | e |
// 1 0 0 1 0 0 | a<1> | a(...) | J | f | delete(from); insert(to); NN
// 1 0 0 1 0 1 | a<1> | a() | I | f | delete(from); insert(to); NN
// 1 0 0 1 1 0 | a<> | a(...) | G | f | delete(from); insert(to); NN
// 1 0 0 1 1 1 | a<> | a() | F | f | delete(from); insert(to); NN
// 1 0 1 0 0 0 | a(...) | a<1> | J' | f | delete(from); insert(to); NN
// 1 0 1 0 0 1 | a(...) | a<> | G' | f | delete(from); insert(to); NN
// 1 0 1 0 1 0 | a() | a<1> | I' | f | delete(from); insert(to); NN
// 1 0 1 0 1 1 | a() | a<> | F' | f | delete(from); insert(to); NN
// 1 0 1 1 0 0 | a(...) | a(;;;) | L | g | nothing; SS
// 1 0 1 1 0 1 | a(...) | a() | K' | h | deleteChildren(from); NN
// 1 0 1 1 1 0 | a() | a(...) | K | i | insertChildren(to); NN
// 1 0 1 1 1 1 | ---- | ---- | | |
// 1 1 0 0 0 0 | a<1> | a<1> | B | b | nothing; NN
// 1 1 0 0 0 1 | ---- | ---- | | b |
// 1 1 0 0 1 0 | ---- | ---- | | b |
// 1 1 0 0 1 1 | a<> | a<> | B | b | nothing; NN
// 1 1 0 1 0 0 | ---- | ---- | | b |
// 1 1 0 1 0 1 | ---- | ---- | | b |
// 1 1 0 1 1 0 | ---- | ---- | | b |
// 1 1 0 1 1 1 | ---- | ---- | | b |
// 1 1 1 0 0 0 | ---- | ---- | | b |
// 1 1 1 0 0 1 | ---- | ---- | | b |
// 1 1 1 0 1 0 | ---- | ---- | | b |
// 1 1 1 0 1 1 | ---- | ---- | | b |
// 1 1 1 1 0 0 | a(...) | a(...) | B | b | nothing; NN
// 1 1 1 1 0 1 | ---- | ---- | | b |
// 1 1 1 1 1 0 | ---- | ---- | | b |
// 1 1 1 1 1 1 | a() | a() | B | b | nothing; NN
//
// c and d:
// if !SameName()
// d if FromBeforeTo()
// c else
// b: SameName) && sameHash()
// e: SameName() && !sameHash() && BothAreFiles()
// f: SameName() && !sameHash() && FileAndDir()
// g: SameName() && !sameHash() && BothAreDirs() && NoneIsEmpty
// i: SameName() && !sameHash() && BothAreDirs() && FromIsEmpty
// h: else of i
import (
"context"
"errors"
"fmt"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
var (
// ErrCanceled is returned whenever the operation is canceled.
ErrCanceled = errors.New("operation canceled")
)
// DiffTree calculates the list of changes between two merkletries. It
// uses the provided hashEqual callback to compare noders.
func DiffTree(
fromTree,
toTree noder.Noder,
hashEqual noder.Equal,
) (Changes, error) {
return DiffTreeContext(context.Background(), fromTree, toTree, hashEqual)
}
// DiffTreeContext calculates the list of changes between two merkletries. It
// uses the provided hashEqual callback to compare noders.
// Error will be returned if context expires
// Provided context must be non nil
func DiffTreeContext(ctx context.Context, fromTree, toTree noder.Noder,
hashEqual noder.Equal) (Changes, error) {
ret := NewChanges()
ii, err := newDoubleIter(fromTree, toTree, hashEqual)
if err != nil {
return nil, err
}
for {
select {
case <-ctx.Done():
return nil, ErrCanceled
default:
}
from := ii.from.current
to := ii.to.current
switch r := ii.remaining(); r {
case noMoreNoders:
return ret, nil
case onlyFromRemains:
if err = ret.AddRecursiveDelete(from); err != nil {
return nil, err
}
if err = ii.nextFrom(); err != nil {
return nil, err
}
case onlyToRemains:
if to.Skip() {
if err = ret.AddRecursiveDelete(to); err != nil {
return nil, err
}
} else {
if err = ret.AddRecursiveInsert(to); err != nil {
return nil, err
}
}
if err = ii.nextTo(); err != nil {
return nil, err
}
case bothHaveNodes:
if from.Skip() {
if err = ret.AddRecursiveDelete(from); err != nil {
return nil, err
}
if err := ii.nextBoth(); err != nil {
return nil, err
}
break
}
if to.Skip() {
if err = ret.AddRecursiveDelete(to); err != nil {
return nil, err
}
if err := ii.nextBoth(); err != nil {
return nil, err
}
break
}
if err = diffNodes(&ret, ii); err != nil {
return nil, err
}
default:
panic(fmt.Sprintf("unknown remaining value: %d", r))
}
}
}
func diffNodes(changes *Changes, ii *doubleIter) error {
from := ii.from.current
to := ii.to.current
var err error
// compare their full paths as strings
switch from.Compare(to) {
case -1:
if err = changes.AddRecursiveDelete(from); err != nil {
return err
}
if err = ii.nextFrom(); err != nil {
return err
}
case 1:
if err = changes.AddRecursiveInsert(to); err != nil {
return err
}
if err = ii.nextTo(); err != nil {
return err
}
default:
if err := diffNodesSameName(changes, ii); err != nil {
return err
}
}
return nil
}
func diffNodesSameName(changes *Changes, ii *doubleIter) error {
from := ii.from.current
to := ii.to.current
status, err := ii.compare()
if err != nil {
return err
}
switch {
case status.sameHash:
// do nothing
if err = ii.nextBoth(); err != nil {
return err
}
case status.bothAreFiles:
changes.Add(NewModify(from, to))
if err = ii.nextBoth(); err != nil {
return err
}
case status.fileAndDir:
if err = changes.AddRecursiveDelete(from); err != nil {
return err
}
if err = changes.AddRecursiveInsert(to); err != nil {
return err
}
if err = ii.nextBoth(); err != nil {
return err
}
case status.bothAreDirs:
if err = diffDirs(changes, ii); err != nil {
return err
}
default:
return fmt.Errorf("bad status from double iterator")
}
return nil
}
func diffDirs(changes *Changes, ii *doubleIter) error {
from := ii.from.current
to := ii.to.current
status, err := ii.compare()
if err != nil {
return err
}
switch {
case status.fromIsEmptyDir:
if err = changes.AddRecursiveInsert(to); err != nil {
return err
}
if err = ii.nextBoth(); err != nil {
return err
}
case status.toIsEmptyDir:
if err = changes.AddRecursiveDelete(from); err != nil {
return err
}
if err = ii.nextBoth(); err != nil {
return err
}
case !status.fromIsEmptyDir && !status.toIsEmptyDir:
// do nothing
if err = ii.stepBoth(); err != nil {
return err
}
default:
return fmt.Errorf("both dirs are empty but has different hash")
}
return nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/doc.go
================================================
/*
Package merkletrie provides support for n-ary trees that are at the same
time Merkle trees and Radix trees (tries).
Git trees are Radix n-ary trees in virtue of the names of their
tree entries. At the same time, git trees are Merkle trees thanks to
their hashes.
This package defines Merkle tries as nodes that should have:
- a hash: the Merkle part of the Merkle trie
- a key: the Radix part of the Merkle trie
The Merkle hash condition is not enforced by this package though. This
means that the hash of a node doesn't have to take into account the hashes of
their children, which is good for testing purposes.
Nodes in the Merkle trie are abstracted by the Noder interface. The
intended use is that git trees implements this interface, either
directly or using a simple wrapper.
This package provides an iterator for merkletries that can skip whole
directory-like noders and an efficient merkletrie comparison algorithm.
When comparing git trees, the simple approach of alphabetically sorting
their elements and comparing the resulting lists is too slow as it
depends linearly on the number of files in the trees: When a directory
has lots of files but none of them has been modified, this approach is
very expensive. We can do better by prunning whole directories that
have not change, just by looking at their hashes. This package provides
the tools to do exactly that.
*/
package merkletrie
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/doubleiter.go
================================================
package merkletrie
import (
"fmt"
"io"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// A doubleIter is a convenience type to keep track of the current
// noders in two merkletries that are going to be iterated in parallel.
// It has methods for:
//
// - iterating over the merkletries, both at the same time or
// individually: nextFrom, nextTo, nextBoth, stepBoth
//
// - checking if there are noders left in one or both of them with the
// remaining method and its associated returned type.
//
// - comparing the current noders of both merkletries in several ways,
// with the compare method and its associated returned type.
type doubleIter struct {
from struct {
iter *Iter
current noder.Path // nil if no more nodes
}
to struct {
iter *Iter
current noder.Path // nil if no more nodes
}
hashEqual noder.Equal
}
// NewdoubleIter returns a new doubleIter for the merkletries "from" and
// "to". The hashEqual callback function will be used by the doubleIter
// to compare the hash of the noders in the merkletries. The doubleIter
// will be initialized to the first elements in each merkletrie if any.
func newDoubleIter(from, to noder.Noder, hashEqual noder.Equal) (
*doubleIter, error) {
var ii doubleIter
var err error
if ii.from.iter, err = NewIter(from); err != nil {
return nil, fmt.Errorf("from: %s", err)
}
if ii.from.current, err = ii.from.iter.Next(); turnEOFIntoNil(err) != nil {
return nil, fmt.Errorf("from: %s", err)
}
if ii.to.iter, err = NewIter(to); err != nil {
return nil, fmt.Errorf("to: %s", err)
}
if ii.to.current, err = ii.to.iter.Next(); turnEOFIntoNil(err) != nil {
return nil, fmt.Errorf("to: %s", err)
}
ii.hashEqual = hashEqual
return &ii, nil
}
func turnEOFIntoNil(e error) error {
if e != nil && e != io.EOF {
return e
}
return nil
}
// NextBoth makes d advance to the next noder in both merkletries. If
// any of them is a directory, it skips its contents.
func (d *doubleIter) nextBoth() error {
if err := d.nextFrom(); err != nil {
return err
}
if err := d.nextTo(); err != nil {
return err
}
return nil
}
// NextFrom makes d advance to the next noder in the "from" merkletrie,
// skipping its contents if it is a directory.
func (d *doubleIter) nextFrom() (err error) {
d.from.current, err = d.from.iter.Next()
return turnEOFIntoNil(err)
}
// NextTo makes d advance to the next noder in the "to" merkletrie,
// skipping its contents if it is a directory.
func (d *doubleIter) nextTo() (err error) {
d.to.current, err = d.to.iter.Next()
return turnEOFIntoNil(err)
}
// StepBoth makes d advance to the next noder in both merkletries,
// getting deeper into directories if that is the case.
func (d *doubleIter) stepBoth() (err error) {
if d.from.current, err = d.from.iter.Step(); turnEOFIntoNil(err) != nil {
return err
}
if d.to.current, err = d.to.iter.Step(); turnEOFIntoNil(err) != nil {
return err
}
return nil
}
// Remaining returns if there are no more noders in the tree, if both
// have noders or if one of them doesn't.
func (d *doubleIter) remaining() remaining {
if d.from.current == nil && d.to.current == nil {
return noMoreNoders
}
if d.from.current == nil && d.to.current != nil {
return onlyToRemains
}
if d.from.current != nil && d.to.current == nil {
return onlyFromRemains
}
return bothHaveNodes
}
// Remaining values tells you whether both trees still have noders, or
// only one of them or none of them.
type remaining int
const (
noMoreNoders remaining = iota
onlyToRemains
onlyFromRemains
bothHaveNodes
)
// Compare returns the comparison between the current elements in the
// merkletries.
func (d *doubleIter) compare() (s comparison, err error) {
s.sameHash = d.hashEqual(d.from.current, d.to.current)
fromIsDir := d.from.current.IsDir()
toIsDir := d.to.current.IsDir()
s.bothAreDirs = fromIsDir && toIsDir
s.bothAreFiles = !fromIsDir && !toIsDir
s.fileAndDir = !s.bothAreDirs && !s.bothAreFiles
fromNumChildren, err := d.from.current.NumChildren()
if err != nil {
return comparison{}, fmt.Errorf("from: %s", err)
}
toNumChildren, err := d.to.current.NumChildren()
if err != nil {
return comparison{}, fmt.Errorf("to: %s", err)
}
s.fromIsEmptyDir = fromIsDir && fromNumChildren == 0
s.toIsEmptyDir = toIsDir && toNumChildren == 0
return
}
// Answers to a lot of questions you can ask about how to noders are
// equal or different.
type comparison struct {
// the following are only valid if both nodes have the same name
// (i.e. nameComparison == 0)
// Do both nodes have the same hash?
sameHash bool
// Are both nodes files?
bothAreFiles bool
// the following are only valid if any of the noders are dirs,
// this is, if !bothAreFiles
// Is one a file and the other a dir?
fileAndDir bool
// Are both nodes dirs?
bothAreDirs bool
// Is the from node an empty dir?
fromIsEmptyDir bool
// Is the to Node an empty dir?
toIsEmptyDir bool
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/filesystem/node.go
================================================
package filesystem
import (
"io"
"os"
"path"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
"github.com/go-git/go-billy/v5"
)
var ignore = map[string]bool{
".git": true,
}
// The node represents a file or a directory in a billy.Filesystem. It
// implements the interface noder.Noder of merkletrie package.
//
// This implementation implements a "standard" hash method being able to be
// compared with any other noder.Noder implementation inside of go-git.
type node struct {
fs billy.Filesystem
submodules map[string]plumbing.Hash
path string
hash []byte
children []noder.Noder
isDir bool
mode os.FileMode
size int64
}
// NewRootNode returns the root node based on a given billy.Filesystem.
//
// In order to provide the submodule hash status, a map[string]plumbing.Hash
// should be provided where the key is the path of the submodule and the commit
// of the submodule HEAD
func NewRootNode(
fs billy.Filesystem,
submodules map[string]plumbing.Hash,
) noder.Noder {
return &node{fs: fs, submodules: submodules, isDir: true}
}
// Hash the hash of a filesystem is the result of concatenating the computed
// plumbing.Hash of the file as a Blob and its plumbing.FileMode; that way the
// difftree algorithm will detect changes in the contents of files and also in
// their mode.
//
// Please note that the hash is calculated on first invocation of Hash(),
// meaning that it will not update when the underlying file changes
// between invocations.
//
// The hash of a directory is always a 24-bytes slice of zero values
func (n *node) Hash() []byte {
if n.hash == nil {
n.calculateHash()
}
return n.hash
}
func (n *node) Name() string {
return path.Base(n.path)
}
func (n *node) IsDir() bool {
return n.isDir
}
func (n *node) Skip() bool {
return false
}
func (n *node) Children() ([]noder.Noder, error) {
if err := n.calculateChildren(); err != nil {
return nil, err
}
return n.children, nil
}
func (n *node) NumChildren() (int, error) {
if err := n.calculateChildren(); err != nil {
return -1, err
}
return len(n.children), nil
}
func (n *node) calculateChildren() error {
if !n.IsDir() {
return nil
}
if len(n.children) != 0 {
return nil
}
files, err := n.fs.ReadDir(n.path)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return err
}
for _, file := range files {
if _, ok := ignore[file.Name()]; ok {
continue
}
if file.Mode()&os.ModeSocket != 0 {
continue
}
c, err := n.newChildNode(file)
if err != nil {
return err
}
n.children = append(n.children, c)
}
return nil
}
func (n *node) newChildNode(file os.FileInfo) (*node, error) {
path := path.Join(n.path, file.Name())
node := &node{
fs: n.fs,
submodules: n.submodules,
path: path,
isDir: file.IsDir(),
size: file.Size(),
mode: file.Mode(),
}
if _, isSubmodule := n.submodules[path]; isSubmodule {
node.isDir = false
}
return node, nil
}
func (n *node) calculateHash() {
if n.isDir {
n.hash = make([]byte, 24)
return
}
mode, err := filemode.NewFromOSFileMode(n.mode)
if err != nil {
n.hash = plumbing.ZeroHash[:]
return
}
if submoduleHash, isSubmodule := n.submodules[n.path]; isSubmodule {
n.hash = append(submoduleHash[:], filemode.Submodule.Bytes()...)
return
}
var hash plumbing.Hash
if n.mode&os.ModeSymlink != 0 {
hash = n.doCalculateHashForSymlink()
} else {
hash = n.doCalculateHashForRegular()
}
n.hash = append(hash[:], mode.Bytes()...)
}
func (n *node) doCalculateHashForRegular() plumbing.Hash {
f, err := n.fs.Open(n.path)
if err != nil {
return plumbing.ZeroHash
}
defer f.Close()
h := plumbing.NewHasher(plumbing.BlobObject, n.size)
if _, err := io.Copy(h, f); err != nil {
return plumbing.ZeroHash
}
return h.Sum()
}
func (n *node) doCalculateHashForSymlink() plumbing.Hash {
target, err := n.fs.Readlink(n.path)
if err != nil {
return plumbing.ZeroHash
}
h := plumbing.NewHasher(plumbing.BlobObject, n.size)
if _, err := h.Write([]byte(target)); err != nil {
return plumbing.ZeroHash
}
return h.Sum()
}
func (n *node) String() string {
return n.path
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/index/node.go
================================================
package index
import (
"path"
"strings"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// The node represents a index.Entry or a directory inferred from the path
// of all entries. It implements the interface noder.Noder of merkletrie
// package.
//
// This implementation implements a "standard" hash method being able to be
// compared with any other noder.Noder implementation inside of go-git
type node struct {
path string
entry *index.Entry
children []noder.Noder
isDir bool
skip bool
}
// NewRootNode returns the root node of a computed tree from a index.Index,
func NewRootNode(idx *index.Index) noder.Noder {
const rootNode = ""
m := map[string]*node{rootNode: {isDir: true}}
for _, e := range idx.Entries {
parts := strings.Split(e.Name, string("/"))
var fullpath string
for _, part := range parts {
parent := fullpath
fullpath = path.Join(fullpath, part)
if _, ok := m[fullpath]; ok {
continue
}
n := &node{path: fullpath, skip: e.SkipWorktree}
if fullpath == e.Name {
n.entry = e
} else {
n.isDir = true
}
m[n.path] = n
m[parent].children = append(m[parent].children, n)
}
}
return m[rootNode]
}
func (n *node) String() string {
return n.path
}
func (n *node) Skip() bool {
return n.skip
}
// Hash the hash of a filesystem is a 24-byte slice, is the result of
// concatenating the computed plumbing.Hash of the file as a Blob and its
// plumbing.FileMode; that way the difftree algorithm will detect changes in the
// contents of files and also in their mode.
//
// If the node is computed and not based on a index.Entry the hash is equals
// to a 24-bytes slices of zero values.
func (n *node) Hash() []byte {
if n.entry == nil {
return make([]byte, 24)
}
return append(n.entry.Hash[:], n.entry.Mode.Bytes()...)
}
func (n *node) Name() string {
return path.Base(n.path)
}
func (n *node) IsDir() bool {
return n.isDir
}
func (n *node) Children() ([]noder.Noder, error) {
return n.children, nil
}
func (n *node) NumChildren() (int, error) {
return len(n.children), nil
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/internal/frame/frame.go
================================================
package frame
import (
"bytes"
"fmt"
"sort"
"strings"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// A Frame is a collection of siblings in a trie, sorted alphabetically
// by name.
type Frame struct {
// siblings, sorted in reverse alphabetical order by name
stack []noder.Noder
}
type byName []noder.Noder
func (a byName) Len() int { return len(a) }
func (a byName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a byName) Less(i, j int) bool {
return strings.Compare(a[i].Name(), a[j].Name()) < 0
}
// New returns a frame with the children of the provided node.
func New(n noder.Noder) (*Frame, error) {
children, err := n.Children()
if err != nil {
return nil, err
}
sort.Sort(sort.Reverse(byName(children)))
return &Frame{
stack: children,
}, nil
}
// String returns the quoted names of the noders in the frame sorted in
// alphabetical order by name, surrounded by square brackets and
// separated by comas.
//
// Examples:
// []
// ["a", "b"]
func (f *Frame) String() string {
var buf bytes.Buffer
_ = buf.WriteByte('[')
sep := ""
for i := f.Len() - 1; i >= 0; i-- {
_, _ = buf.WriteString(sep)
sep = ", "
_, _ = buf.WriteString(fmt.Sprintf("%q", f.stack[i].Name()))
}
_ = buf.WriteByte(']')
return buf.String()
}
// First returns, but dont extract, the noder with the alphabetically
// smaller name in the frame and true if the frame was not empty.
// Otherwise it returns nil and false.
func (f *Frame) First() (noder.Noder, bool) {
if f.Len() == 0 {
return nil, false
}
top := f.Len() - 1
return f.stack[top], true
}
// Drop extracts the noder with the alphabetically smaller name in the
// frame or does nothing if the frame was empty.
func (f *Frame) Drop() {
if f.Len() == 0 {
return
}
top := f.Len() - 1
f.stack[top] = nil
f.stack = f.stack[:top]
}
// Len returns the number of noders in the frame.
func (f *Frame) Len() int {
return len(f.stack)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/iter.go
================================================
package merkletrie
import (
"fmt"
"io"
"github.com/go-git/go-git/v5/utils/merkletrie/internal/frame"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
// Iter is an iterator for merkletries (only the trie part of the
// merkletrie is relevant here, it does not use the Hasher interface).
//
// The iteration is performed in depth-first pre-order. Entries at each
// depth are traversed in (case-sensitive) alphabetical order.
//
// This is the kind of traversal you will expect when listing ordinary
// files and directories recursively, for example:
//
// Trie Traversal order
// ---- ---------------
// .
// / | \ c
// / | \ d/
// d c z ===> d/a
// / \ d/b
// b a z
//
//
// This iterator is somewhat especial as you can chose to skip whole
// "directories" when iterating:
//
// - The Step method will iterate normally.
//
// - the Next method will not descend deeper into the tree.
//
// For example, if the iterator is at `d/`, the Step method will return
// `d/a` while the Next would have returned `z` instead (skipping `d/`
// and its descendants). The name of the these two methods are based on
// the well known "next" and "step" operations, quite common in
// debuggers, like gdb.
//
// The paths returned by the iterator will be relative, if the iterator
// was created from a single node, or absolute, if the iterator was
// created from the path to the node (the path will be prefixed to all
// returned paths).
type Iter struct {
// Tells if the iteration has started.
hasStarted bool
// The top of this stack has the current node and its siblings. The
// rest of the stack keeps the ancestors of the current node and
// their corresponding siblings. The current element is always the
// top element of the top frame.
//
// When "step"ping into a node, its children are pushed as a new
// frame.
//
// When "next"ing pass a node, the current element is dropped by
// popping the top frame.
frameStack []*frame.Frame
// The base path used to turn the relative paths used internally by
// the iterator into absolute paths used by external applications.
// For relative iterator this will be nil.
base noder.Path
}
// NewIter returns a new relative iterator using the provider noder as
// its unnamed root. When iterating, all returned paths will be
// relative to node.
func NewIter(n noder.Noder) (*Iter, error) {
return newIter(n, nil)
}
// NewIterFromPath returns a new absolute iterator from the noder at the
// end of the path p. When iterating, all returned paths will be
// absolute, using the root of the path p as their root.
func NewIterFromPath(p noder.Path) (*Iter, error) {
return newIter(p, p) // Path implements Noder
}
func newIter(root noder.Noder, base noder.Path) (*Iter, error) {
ret := &Iter{
base: base,
}
if root == nil {
return ret, nil
}
frame, err := frame.New(root)
if err != nil {
return nil, err
}
ret.push(frame)
return ret, nil
}
func (iter *Iter) top() (*frame.Frame, bool) {
if len(iter.frameStack) == 0 {
return nil, false
}
top := len(iter.frameStack) - 1
return iter.frameStack[top], true
}
func (iter *Iter) push(f *frame.Frame) {
iter.frameStack = append(iter.frameStack, f)
}
const (
doDescend = true
dontDescend = false
)
// Next returns the path of the next node without descending deeper into
// the trie and nil. If there are no more entries in the trie it
// returns nil and io.EOF. In case of error, it will return nil and the
// error.
func (iter *Iter) Next() (noder.Path, error) {
return iter.advance(dontDescend)
}
// Step returns the path to the next node in the trie, descending deeper
// into it if needed, and nil. If there are no more nodes in the trie,
// it returns nil and io.EOF. In case of error, it will return nil and
// the error.
func (iter *Iter) Step() (noder.Path, error) {
return iter.advance(doDescend)
}
// Advances the iterator in the desired direction: descend or
// dontDescend.
//
// Returns the new current element and a nil error on success. If there
// are no more elements in the trie below the base, it returns nil, and
// io.EOF. Returns nil and an error in case of errors.
func (iter *Iter) advance(wantDescend bool) (noder.Path, error) {
current, err := iter.current()
if err != nil {
return nil, err
}
// The first time we just return the current node.
if !iter.hasStarted {
iter.hasStarted = true
return current, nil
}
// Advances means getting a next current node, either its first child or
// its next sibling, depending if we must descend or not.
numChildren, err := current.NumChildren()
if err != nil {
return nil, err
}
mustDescend := numChildren != 0 && wantDescend
if mustDescend {
// descend: add a new frame with the current's children.
frame, err := frame.New(current)
if err != nil {
return nil, err
}
iter.push(frame)
} else {
// don't descend: just drop the current node
iter.drop()
}
return iter.current()
}
// Returns the path to the current node, adding the base if there was
// one, and a nil error. If there were no noders left, it returns nil
// and io.EOF. If an error occurred, it returns nil and the error.
func (iter *Iter) current() (noder.Path, error) {
if topFrame, ok := iter.top(); !ok {
return nil, io.EOF
} else if _, ok := topFrame.First(); !ok {
return nil, io.EOF
}
ret := make(noder.Path, 0, len(iter.base)+len(iter.frameStack))
// concat the base...
ret = append(ret, iter.base...)
// ... and the current node and all its ancestors
for i, f := range iter.frameStack {
t, ok := f.First()
if !ok {
panic(fmt.Sprintf("frame %d is empty", i))
}
ret = append(ret, t)
}
return ret, nil
}
// removes the current node if any, and all the frames that become empty as a
// consequence of this action.
func (iter *Iter) drop() {
frame, ok := iter.top()
if !ok {
return
}
frame.Drop()
// if the frame is empty, remove it and its parent, recursively
if frame.Len() == 0 {
top := len(iter.frameStack) - 1
iter.frameStack[top] = nil
iter.frameStack = iter.frameStack[:top]
iter.drop()
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/noder/noder.go
================================================
// Package noder provide an interface for defining nodes in a
// merkletrie, their hashes and their paths (a noders and its
// ancestors).
//
// The hasher interface is easy to implement naively by elements that
// already have a hash, like git blobs and trees. More sophisticated
// implementations can implement the Equal function in exotic ways
// though: for instance, comparing the modification time of directories
// in a filesystem.
package noder
import "fmt"
// Hasher interface is implemented by types that can tell you
// their hash.
type Hasher interface {
Hash() []byte
}
// Equal functions take two hashers and return if they are equal.
//
// These functions are expected to be faster than reflect.Equal or
// reflect.DeepEqual because they can compare just the hash of the
// objects, instead of their contents, so they are expected to be O(1).
type Equal func(a, b Hasher) bool
// The Noder interface is implemented by the elements of a Merkle Trie.
//
// There are two types of elements in a Merkle Trie:
//
// - file-like nodes: they cannot have children.
//
// - directory-like nodes: they can have 0 or more children and their
// hash is calculated by combining their children hashes.
type Noder interface {
Hasher
fmt.Stringer // for testing purposes
// Name returns the name of an element (relative, not its full
// path).
Name() string
// IsDir returns true if the element is a directory-like node or
// false if it is a file-like node.
IsDir() bool
// Children returns the children of the element. Note that empty
// directory-like noders and file-like noders will both return
// NoChildren.
Children() ([]Noder, error)
// NumChildren returns the number of children this element has.
//
// This method is an optimization: the number of children is easily
// calculated as the length of the value returned by the Children
// method (above); yet, some implementations will be able to
// implement NumChildren in O(1) while Children is usually more
// complex.
NumChildren() (int, error)
Skip() bool
}
// NoChildren represents the children of a noder without children.
var NoChildren = []Noder{}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/merkletrie/noder/path.go
================================================
package noder
import (
"bytes"
"strings"
)
// Path values represent a noder and its ancestors. The root goes first
// and the actual final noder the path is referring to will be the last.
//
// A path implements the Noder interface, redirecting all the interface
// calls to its final noder.
//
// Paths build from an empty Noder slice are not valid paths and should
// not be used.
type Path []Noder
func (p Path) Skip() bool {
if len(p) > 0 {
return p.Last().Skip()
}
return false
}
// String returns the full path of the final noder as a string, using
// "/" as the separator.
func (p Path) String() string {
var buf bytes.Buffer
sep := ""
for _, e := range p {
_, _ = buf.WriteString(sep)
sep = "/"
_, _ = buf.WriteString(e.Name())
}
return buf.String()
}
// Last returns the final noder in the path.
func (p Path) Last() Noder {
return p[len(p)-1]
}
// Hash returns the hash of the final noder of the path.
func (p Path) Hash() []byte {
return p.Last().Hash()
}
// Name returns the name of the final noder of the path.
func (p Path) Name() string {
return p.Last().Name()
}
// IsDir returns if the final noder of the path is a directory-like
// noder.
func (p Path) IsDir() bool {
return p.Last().IsDir()
}
// Children returns the children of the final noder in the path.
func (p Path) Children() ([]Noder, error) {
return p.Last().Children()
}
// NumChildren returns the number of children the final noder of the
// path has.
func (p Path) NumChildren() (int, error) {
return p.Last().NumChildren()
}
// Compare returns -1, 0 or 1 if the path p is smaller, equal or bigger
// than other, in "directory order"; for example:
//
// "a" < "b"
// "a/b/c/d/z" < "b"
// "a/b/a" > "a/b"
func (p Path) Compare(other Path) int {
i := 0
for {
switch {
case len(other) == len(p) && i == len(p):
return 0
case i == len(other):
return 1
case i == len(p):
return -1
default:
// We do *not* normalize Unicode here. CGit doesn't.
// https://github.com/src-d/go-git/issues/1057
cmp := strings.Compare(p[i].Name(), other[i].Name())
if cmp != 0 {
return cmp
}
}
i++
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/sync/bufio.go
================================================
package sync
import (
"bufio"
"io"
"sync"
)
var bufioReader = sync.Pool{
New: func() interface{} {
return bufio.NewReader(nil)
},
}
// GetBufioReader returns a *bufio.Reader that is managed by a sync.Pool.
// Returns a bufio.Reader that is reset with reader and ready for use.
//
// After use, the *bufio.Reader should be put back into the sync.Pool
// by calling PutBufioReader.
func GetBufioReader(reader io.Reader) *bufio.Reader {
r := bufioReader.Get().(*bufio.Reader)
r.Reset(reader)
return r
}
// PutBufioReader puts reader back into its sync.Pool.
func PutBufioReader(reader *bufio.Reader) {
bufioReader.Put(reader)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/sync/bytes.go
================================================
package sync
import (
"bytes"
"sync"
)
var (
byteSlice = sync.Pool{
New: func() interface{} {
b := make([]byte, 16*1024)
return &b
},
}
bytesBuffer = sync.Pool{
New: func() interface{} {
return bytes.NewBuffer(nil)
},
}
)
// GetByteSlice returns a *[]byte that is managed by a sync.Pool.
// The initial slice length will be 16384 (16kb).
//
// After use, the *[]byte should be put back into the sync.Pool
// by calling PutByteSlice.
func GetByteSlice() *[]byte {
buf := byteSlice.Get().(*[]byte)
return buf
}
// PutByteSlice puts buf back into its sync.Pool.
func PutByteSlice(buf *[]byte) {
byteSlice.Put(buf)
}
// GetBytesBuffer returns a *bytes.Buffer that is managed by a sync.Pool.
// Returns a buffer that is reset and ready for use.
//
// After use, the *bytes.Buffer should be put back into the sync.Pool
// by calling PutBytesBuffer.
func GetBytesBuffer() *bytes.Buffer {
buf := bytesBuffer.Get().(*bytes.Buffer)
buf.Reset()
return buf
}
// PutBytesBuffer puts buf back into its sync.Pool.
func PutBytesBuffer(buf *bytes.Buffer) {
bytesBuffer.Put(buf)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/sync/zlib.go
================================================
package sync
import (
"bytes"
"compress/zlib"
"io"
"sync"
)
var (
zlibInitBytes = []byte{0x78, 0x9c, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}
zlibReader = sync.Pool{
New: func() interface{} {
r, _ := zlib.NewReader(bytes.NewReader(zlibInitBytes))
return ZLibReader{
Reader: r.(zlibReadCloser),
}
},
}
zlibWriter = sync.Pool{
New: func() interface{} {
return zlib.NewWriter(nil)
},
}
)
type zlibReadCloser interface {
io.ReadCloser
zlib.Resetter
}
type ZLibReader struct {
dict *[]byte
Reader zlibReadCloser
}
// GetZlibReader returns a ZLibReader that is managed by a sync.Pool.
// Returns a ZLibReader that is reset using a dictionary that is
// also managed by a sync.Pool.
//
// After use, the ZLibReader should be put back into the sync.Pool
// by calling PutZlibReader.
func GetZlibReader(r io.Reader) (ZLibReader, error) {
z := zlibReader.Get().(ZLibReader)
z.dict = GetByteSlice()
err := z.Reader.Reset(r, *z.dict)
return z, err
}
// PutZlibReader puts z back into its sync.Pool, first closing the reader.
// The Byte slice dictionary is also put back into its sync.Pool.
func PutZlibReader(z ZLibReader) {
z.Reader.Close()
PutByteSlice(z.dict)
zlibReader.Put(z)
}
// GetZlibWriter returns a *zlib.Writer that is managed by a sync.Pool.
// Returns a writer that is reset with w and ready for use.
//
// After use, the *zlib.Writer should be put back into the sync.Pool
// by calling PutZlibWriter.
func GetZlibWriter(w io.Writer) *zlib.Writer {
z := zlibWriter.Get().(*zlib.Writer)
z.Reset(w)
return z
}
// PutZlibWriter puts w back into its sync.Pool.
func PutZlibWriter(w *zlib.Writer) {
zlibWriter.Put(w)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/utils/trace/trace.go
================================================
package trace
import (
"fmt"
"log"
"os"
"sync/atomic"
)
var (
// logger is the logger to use for tracing.
logger = newLogger()
// current is the targets that are enabled for tracing.
current atomic.Int32
)
func newLogger() *log.Logger {
return log.New(os.Stderr, "", log.Ltime|log.Lmicroseconds|log.Lshortfile)
}
// Target is a tracing target.
type Target int32
const (
// General traces general operations.
General Target = 1 << iota
// Packet traces git packets.
Packet
)
// SetTarget sets the tracing targets.
func SetTarget(target Target) {
current.Store(int32(target))
}
// SetLogger sets the logger to use for tracing.
func SetLogger(l *log.Logger) {
logger = l
}
// Print prints the given message only if the target is enabled.
func (t Target) Print(args ...interface{}) {
if int32(t)¤t.Load() != 0 {
logger.Output(2, fmt.Sprint(args...)) // nolint: errcheck
}
}
// Printf prints the given message only if the target is enabled.
func (t Target) Printf(format string, args ...interface{}) {
if int32(t)¤t.Load() != 0 {
logger.Output(2, fmt.Sprintf(format, args...)) // nolint: errcheck
}
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree.go
================================================
package git
import (
"context"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/go-git/go-billy/v5"
"github.com/go-git/go-billy/v5/util"
"github.com/go-git/go-git/v5/config"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/merkletrie"
"github.com/go-git/go-git/v5/utils/sync"
)
var (
ErrWorktreeNotClean = errors.New("worktree is not clean")
ErrSubmoduleNotFound = errors.New("submodule not found")
ErrUnstagedChanges = errors.New("worktree contains unstaged changes")
ErrGitModulesSymlink = errors.New(gitmodulesFile + " is a symlink")
ErrNonFastForwardUpdate = errors.New("non-fast-forward update")
ErrRestoreWorktreeOnlyNotSupported = errors.New("worktree only is not supported")
)
// Worktree represents a git worktree.
type Worktree struct {
// Filesystem underlying filesystem.
Filesystem billy.Filesystem
// External excludes not found in the repository .gitignore
Excludes []gitignore.Pattern
r *Repository
}
// Pull incorporates changes from a remote repository into the current branch.
// Returns nil if the operation is successful, NoErrAlreadyUpToDate if there are
// no changes to be fetched, or an error.
//
// Pull only supports merges where the can be resolved as a fast-forward.
func (w *Worktree) Pull(o *PullOptions) error {
return w.PullContext(context.Background(), o)
}
// PullContext incorporates changes from a remote repository into the current
// branch. Returns nil if the operation is successful, NoErrAlreadyUpToDate if
// there are no changes to be fetched, or an error.
//
// Pull only supports merges where the can be resolved as a fast-forward.
//
// The provided Context must be non-nil. If the context expires before the
// operation is complete, an error is returned. The context only affects the
// transport operations.
func (w *Worktree) PullContext(ctx context.Context, o *PullOptions) error {
if err := o.Validate(); err != nil {
return err
}
remote, err := w.r.Remote(o.RemoteName)
if err != nil {
return err
}
fetchHead, err := remote.fetch(ctx, &FetchOptions{
RemoteName: o.RemoteName,
RemoteURL: o.RemoteURL,
Depth: o.Depth,
Auth: o.Auth,
Progress: o.Progress,
Force: o.Force,
InsecureSkipTLS: o.InsecureSkipTLS,
CABundle: o.CABundle,
ProxyOptions: o.ProxyOptions,
})
updated := true
if err == NoErrAlreadyUpToDate {
updated = false
} else if err != nil {
return err
}
ref, err := storer.ResolveReference(fetchHead, o.ReferenceName)
if err != nil {
return err
}
head, err := w.r.Head()
if err == nil {
// if we don't have a shallows list, just ignore it
shallowList, _ := w.r.Storer.Shallow()
var earliestShallow *plumbing.Hash
if len(shallowList) > 0 {
earliestShallow = &shallowList[0]
}
headAheadOfRef, err := isFastForward(w.r.Storer, ref.Hash(), head.Hash(), earliestShallow)
if err != nil {
return err
}
if !updated && headAheadOfRef {
return NoErrAlreadyUpToDate
}
ff, err := isFastForward(w.r.Storer, head.Hash(), ref.Hash(), earliestShallow)
if err != nil {
return err
}
if !ff {
return ErrNonFastForwardUpdate
}
}
if err != nil && err != plumbing.ErrReferenceNotFound {
return err
}
if err := w.updateHEAD(ref.Hash()); err != nil {
return err
}
if err := w.Reset(&ResetOptions{
Mode: MergeReset,
Commit: ref.Hash(),
}); err != nil {
return err
}
if o.RecurseSubmodules != NoRecurseSubmodules {
return w.updateSubmodules(ctx, &SubmoduleUpdateOptions{
RecurseSubmodules: o.RecurseSubmodules,
Auth: o.Auth,
})
}
return nil
}
func (w *Worktree) updateSubmodules(ctx context.Context, o *SubmoduleUpdateOptions) error {
s, err := w.Submodules()
if err != nil {
return err
}
o.Init = true
return s.UpdateContext(ctx, o)
}
// Checkout switch branches or restore working tree files.
func (w *Worktree) Checkout(opts *CheckoutOptions) error {
if err := opts.Validate(); err != nil {
return err
}
if opts.Create {
if err := w.createBranch(opts); err != nil {
return err
}
}
c, err := w.getCommitFromCheckoutOptions(opts)
if err != nil {
return err
}
ro := &ResetOptions{Commit: c, Mode: MergeReset}
if opts.Force {
ro.Mode = HardReset
} else if opts.Keep {
ro.Mode = SoftReset
}
if !opts.Hash.IsZero() && !opts.Create {
err = w.setHEADToCommit(opts.Hash)
} else {
err = w.setHEADToBranch(opts.Branch, c)
}
if err != nil {
return err
}
if len(opts.SparseCheckoutDirectories) > 0 {
return w.ResetSparsely(ro, opts.SparseCheckoutDirectories)
}
return w.Reset(ro)
}
func (w *Worktree) createBranch(opts *CheckoutOptions) error {
if err := opts.Branch.Validate(); err != nil {
return err
}
_, err := w.r.Storer.Reference(opts.Branch)
if err == nil {
return fmt.Errorf("a branch named %q already exists", opts.Branch)
}
if err != plumbing.ErrReferenceNotFound {
return err
}
if opts.Hash.IsZero() {
ref, err := w.r.Head()
if err != nil {
return err
}
opts.Hash = ref.Hash()
}
return w.r.Storer.SetReference(
plumbing.NewHashReference(opts.Branch, opts.Hash),
)
}
func (w *Worktree) getCommitFromCheckoutOptions(opts *CheckoutOptions) (plumbing.Hash, error) {
hash := opts.Hash
if hash.IsZero() {
b, err := w.r.Reference(opts.Branch, true)
if err != nil {
return plumbing.ZeroHash, err
}
hash = b.Hash()
}
o, err := w.r.Object(plumbing.AnyObject, hash)
if err != nil {
return plumbing.ZeroHash, err
}
switch o := o.(type) {
case *object.Tag:
if o.TargetType != plumbing.CommitObject {
return plumbing.ZeroHash, fmt.Errorf("%w: tag target %q", object.ErrUnsupportedObject, o.TargetType)
}
return o.Target, nil
case *object.Commit:
return o.Hash, nil
}
return plumbing.ZeroHash, fmt.Errorf("%w: %q", object.ErrUnsupportedObject, o.Type())
}
func (w *Worktree) setHEADToCommit(commit plumbing.Hash) error {
head := plumbing.NewHashReference(plumbing.HEAD, commit)
return w.r.Storer.SetReference(head)
}
func (w *Worktree) setHEADToBranch(branch plumbing.ReferenceName, commit plumbing.Hash) error {
target, err := w.r.Storer.Reference(branch)
if err != nil {
return err
}
var head *plumbing.Reference
if target.Name().IsBranch() {
head = plumbing.NewSymbolicReference(plumbing.HEAD, target.Name())
} else {
head = plumbing.NewHashReference(plumbing.HEAD, commit)
}
return w.r.Storer.SetReference(head)
}
func (w *Worktree) ResetSparsely(opts *ResetOptions, dirs []string) error {
if err := opts.Validate(w.r); err != nil {
return err
}
if opts.Mode == MergeReset {
unstaged, err := w.containsUnstagedChanges()
if err != nil {
return err
}
if unstaged {
return ErrUnstagedChanges
}
}
if err := w.setHEADCommit(opts.Commit); err != nil {
return err
}
if opts.Mode == SoftReset {
return nil
}
t, err := w.r.getTreeFromCommitHash(opts.Commit)
if err != nil {
return err
}
if opts.Mode == MixedReset || opts.Mode == MergeReset || opts.Mode == HardReset {
if err := w.resetIndex(t, dirs, opts.Files); err != nil {
return err
}
}
if opts.Mode == MergeReset || opts.Mode == HardReset {
if err := w.resetWorktree(t, opts.Files); err != nil {
return err
}
}
return nil
}
// Restore restores specified files in the working tree or stage with contents from
// a restore source. If a path is tracked but does not exist in the restore,
// source, it will be removed to match the source.
//
// If Staged and Worktree are true, then the restore source will be the index.
// If only Staged is true, then the restore source will be HEAD.
// If only Worktree is true or neither Staged nor Worktree are true, will
// result in ErrRestoreWorktreeOnlyNotSupported because restoring the working
// tree while leaving the stage untouched is not currently supported.
//
// Restore with no files specified will return ErrNoRestorePaths.
func (w *Worktree) Restore(o *RestoreOptions) error {
if err := o.Validate(); err != nil {
return err
}
if o.Staged {
opts := &ResetOptions{
Files: o.Files,
}
if o.Worktree {
// If we are doing both Worktree and Staging then it is a hard reset
opts.Mode = HardReset
} else {
// If we are doing just staging then it is a mixed reset
opts.Mode = MixedReset
}
return w.Reset(opts)
}
return ErrRestoreWorktreeOnlyNotSupported
}
// Reset the worktree to a specified state.
func (w *Worktree) Reset(opts *ResetOptions) error {
return w.ResetSparsely(opts, nil)
}
func (w *Worktree) resetIndex(t *object.Tree, dirs []string, files []string) error {
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
b := newIndexBuilder(idx)
changes, err := w.diffTreeWithStaging(t, true)
if err != nil {
return err
}
for _, ch := range changes {
a, err := ch.Action()
if err != nil {
return err
}
var name string
var e *object.TreeEntry
switch a {
case merkletrie.Modify, merkletrie.Insert:
name = ch.To.String()
e, err = t.FindEntry(name)
if err != nil {
return err
}
case merkletrie.Delete:
name = ch.From.String()
}
if len(files) > 0 {
contains := inFiles(files, name)
if !contains {
continue
}
}
b.Remove(name)
if e == nil {
continue
}
b.Add(&index.Entry{
Name: name,
Hash: e.Hash,
Mode: e.Mode,
})
}
b.Write(idx)
if len(dirs) > 0 {
idx.SkipUnless(dirs)
}
return w.r.Storer.SetIndex(idx)
}
func inFiles(files []string, v string) bool {
v = filepath.Clean(v)
for _, s := range files {
if filepath.Clean(s) == v {
return true
}
}
return false
}
func (w *Worktree) resetWorktree(t *object.Tree, files []string) error {
changes, err := w.diffStagingWithWorktree(true, false)
if err != nil {
return err
}
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
b := newIndexBuilder(idx)
for _, ch := range changes {
if err := w.validChange(ch); err != nil {
return err
}
if len(files) > 0 {
file := ""
if ch.From != nil {
file = ch.From.String()
} else if ch.To != nil {
file = ch.To.String()
}
if file == "" {
continue
}
contains := inFiles(files, file)
if !contains {
continue
}
}
if err := w.checkoutChange(ch, t, b); err != nil {
return err
}
}
b.Write(idx)
return w.r.Storer.SetIndex(idx)
}
// worktreeDeny is a list of paths that are not allowed
// to be used when resetting the worktree.
var worktreeDeny = map[string]struct{}{
// .git
GitDirName: {},
// For other historical reasons, file names that do not conform to the 8.3
// format (up to eight characters for the basename, three for the file
// extension, certain characters not allowed such as `+`, etc) are associated
// with a so-called "short name", at least on the `C:` drive by default.
// Which means that `git~1/` is a valid way to refer to `.git/`.
"git~1": {},
}
// validPath checks whether paths are valid.
// The rules around invalid paths could differ from upstream based on how
// filesystems are managed within go-git, but they are largely the same.
//
// For upstream rules:
// https://github.com/git/git/blob/564d0252ca632e0264ed670534a51d18a689ef5d/read-cache.c#L946
// https://github.com/git/git/blob/564d0252ca632e0264ed670534a51d18a689ef5d/path.c#L1383
func validPath(paths ...string) error {
for _, p := range paths {
parts := strings.FieldsFunc(p, func(r rune) bool { return (r == '\\' || r == '/') })
if len(parts) == 0 {
return fmt.Errorf("invalid path: %q", p)
}
if _, denied := worktreeDeny[strings.ToLower(parts[0])]; denied {
return fmt.Errorf("invalid path prefix: %q", p)
}
if runtime.GOOS == "windows" {
// Volume names are not supported, in both formats: \\ and :.
if vol := filepath.VolumeName(p); vol != "" {
return fmt.Errorf("invalid path: %q", p)
}
if !windowsValidPath(parts[0]) {
return fmt.Errorf("invalid path: %q", p)
}
}
for _, part := range parts {
if part == ".." {
return fmt.Errorf("invalid path %q: cannot use '..'", p)
}
}
}
return nil
}
// windowsPathReplacer defines the chars that need to be replaced
// as part of windowsValidPath.
var windowsPathReplacer *strings.Replacer
func init() {
windowsPathReplacer = strings.NewReplacer(" ", "", ".", "")
}
func windowsValidPath(part string) bool {
if len(part) > 3 && strings.EqualFold(part[:4], GitDirName) {
// For historical reasons, file names that end in spaces or periods are
// automatically trimmed. Therefore, `.git . . ./` is a valid way to refer
// to `.git/`.
if windowsPathReplacer.Replace(part[4:]) == "" {
return false
}
// For yet other historical reasons, NTFS supports so-called "Alternate Data
// Streams", i.e. metadata associated with a given file, referred to via
// `::`. There exists a default stream
// type for directories, allowing `.git/` to be accessed via
// `.git::$INDEX_ALLOCATION/`.
//
// For performance reasons, _all_ Alternate Data Streams of `.git/` are
// forbidden, not just `::$INDEX_ALLOCATION`.
if len(part) > 4 && part[4:5] == ":" {
return false
}
}
return true
}
func (w *Worktree) validChange(ch merkletrie.Change) error {
action, err := ch.Action()
if err != nil {
return nil
}
switch action {
case merkletrie.Delete:
return validPath(ch.From.String())
case merkletrie.Insert:
return validPath(ch.To.String())
case merkletrie.Modify:
return validPath(ch.From.String(), ch.To.String())
}
return nil
}
func (w *Worktree) checkoutChange(ch merkletrie.Change, t *object.Tree, idx *indexBuilder) error {
a, err := ch.Action()
if err != nil {
return err
}
var e *object.TreeEntry
var name string
var isSubmodule bool
switch a {
case merkletrie.Modify, merkletrie.Insert:
name = ch.To.String()
e, err = t.FindEntry(name)
if err != nil {
return err
}
isSubmodule = e.Mode == filemode.Submodule
case merkletrie.Delete:
return rmFileAndDirsIfEmpty(w.Filesystem, ch.From.String())
}
if isSubmodule {
return w.checkoutChangeSubmodule(name, a, e, idx)
}
return w.checkoutChangeRegularFile(name, a, t, e, idx)
}
func (w *Worktree) containsUnstagedChanges() (bool, error) {
ch, err := w.diffStagingWithWorktree(false, true)
if err != nil {
return false, err
}
for _, c := range ch {
a, err := c.Action()
if err != nil {
return false, err
}
if a == merkletrie.Insert {
continue
}
return true, nil
}
return false, nil
}
func (w *Worktree) setHEADCommit(commit plumbing.Hash) error {
head, err := w.r.Reference(plumbing.HEAD, false)
if err != nil {
return err
}
if head.Type() == plumbing.HashReference {
head = plumbing.NewHashReference(plumbing.HEAD, commit)
return w.r.Storer.SetReference(head)
}
branch, err := w.r.Reference(head.Target(), false)
if err != nil {
return err
}
if !branch.Name().IsBranch() {
return fmt.Errorf("invalid HEAD target should be a branch, found %s", branch.Type())
}
branch = plumbing.NewHashReference(branch.Name(), commit)
return w.r.Storer.SetReference(branch)
}
func (w *Worktree) checkoutChangeSubmodule(name string,
a merkletrie.Action,
e *object.TreeEntry,
idx *indexBuilder,
) error {
switch a {
case merkletrie.Modify:
sub, err := w.Submodule(name)
if err != nil {
return err
}
if !sub.initialized {
return nil
}
return w.addIndexFromTreeEntry(name, e, idx)
case merkletrie.Insert:
mode, err := e.Mode.ToOSFileMode()
if err != nil {
return err
}
if err := w.Filesystem.MkdirAll(name, mode); err != nil {
return err
}
return w.addIndexFromTreeEntry(name, e, idx)
}
return nil
}
func (w *Worktree) checkoutChangeRegularFile(name string,
a merkletrie.Action,
t *object.Tree,
e *object.TreeEntry,
idx *indexBuilder,
) error {
switch a {
case merkletrie.Modify:
idx.Remove(name)
// to apply perm changes the file is deleted, billy doesn't implement
// chmod
if err := w.Filesystem.Remove(name); err != nil {
return err
}
fallthrough
case merkletrie.Insert:
f, err := t.File(name)
if err != nil {
return err
}
if err := w.checkoutFile(f); err != nil {
return err
}
return w.addIndexFromFile(name, e.Hash, f.Mode, idx)
}
return nil
}
func (w *Worktree) checkoutFile(f *object.File) (err error) {
mode, err := f.Mode.ToOSFileMode()
if err != nil {
return
}
if mode&os.ModeSymlink != 0 {
return w.checkoutFileSymlink(f)
}
from, err := f.Reader()
if err != nil {
return
}
defer ioutil.CheckClose(from, &err)
to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
if err != nil {
return
}
defer ioutil.CheckClose(to, &err)
buf := sync.GetByteSlice()
_, err = io.CopyBuffer(to, from, *buf)
sync.PutByteSlice(buf)
return
}
func (w *Worktree) checkoutFileSymlink(f *object.File) (err error) {
// https://github.com/git/git/commit/10ecfa76491e4923988337b2e2243b05376b40de
if strings.EqualFold(f.Name, gitmodulesFile) {
return ErrGitModulesSymlink
}
from, err := f.Reader()
if err != nil {
return
}
defer ioutil.CheckClose(from, &err)
bytes, err := io.ReadAll(from)
if err != nil {
return
}
err = w.Filesystem.Symlink(string(bytes), f.Name)
// On windows, this might fail.
// Follow Git on Windows behavior by writing the link as it is.
if err != nil && isSymlinkWindowsNonAdmin(err) {
mode, _ := f.Mode.ToOSFileMode()
to, err := w.Filesystem.OpenFile(f.Name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, mode.Perm())
if err != nil {
return err
}
defer ioutil.CheckClose(to, &err)
_, err = to.Write(bytes)
return err
}
return
}
func (w *Worktree) addIndexFromTreeEntry(name string, f *object.TreeEntry, idx *indexBuilder) error {
idx.Remove(name)
idx.Add(&index.Entry{
Hash: f.Hash,
Name: name,
Mode: filemode.Submodule,
})
return nil
}
func (w *Worktree) addIndexFromFile(name string, h plumbing.Hash, mode filemode.FileMode, idx *indexBuilder) error {
idx.Remove(name)
fi, err := w.Filesystem.Lstat(name)
if err != nil {
return err
}
e := &index.Entry{
Hash: h,
Name: name,
Mode: mode,
ModifiedAt: fi.ModTime(),
Size: uint32(fi.Size()),
}
// if the FileInfo.Sys() comes from os the ctime, dev, inode, uid and gid
// can be retrieved, otherwise this doesn't apply
if fillSystemInfo != nil {
fillSystemInfo(e, fi.Sys())
}
idx.Add(e)
return nil
}
func (r *Repository) getTreeFromCommitHash(commit plumbing.Hash) (*object.Tree, error) {
c, err := r.CommitObject(commit)
if err != nil {
return nil, err
}
return c.Tree()
}
var fillSystemInfo func(e *index.Entry, sys interface{})
const gitmodulesFile = ".gitmodules"
// Submodule returns the submodule with the given name
func (w *Worktree) Submodule(name string) (*Submodule, error) {
l, err := w.Submodules()
if err != nil {
return nil, err
}
for _, m := range l {
if m.Config().Name == name {
return m, nil
}
}
return nil, ErrSubmoduleNotFound
}
// Submodules returns all the available submodules
func (w *Worktree) Submodules() (Submodules, error) {
l := make(Submodules, 0)
m, err := w.readGitmodulesFile()
if err != nil || m == nil {
return l, err
}
c, err := w.r.Config()
if err != nil {
return nil, err
}
for _, s := range m.Submodules {
l = append(l, w.newSubmodule(s, c.Submodules[s.Name]))
}
return l, nil
}
func (w *Worktree) newSubmodule(fromModules, fromConfig *config.Submodule) *Submodule {
m := &Submodule{w: w}
m.initialized = fromConfig != nil
if !m.initialized {
m.c = fromModules
return m
}
m.c = fromConfig
m.c.Path = fromModules.Path
return m
}
func (w *Worktree) isSymlink(path string) bool {
if s, err := w.Filesystem.Lstat(path); err == nil {
return s.Mode()&os.ModeSymlink != 0
}
return false
}
func (w *Worktree) readGitmodulesFile() (*config.Modules, error) {
if w.isSymlink(gitmodulesFile) {
return nil, ErrGitModulesSymlink
}
f, err := w.Filesystem.Open(gitmodulesFile)
if err != nil {
if os.IsNotExist(err) {
return nil, nil
}
return nil, err
}
defer f.Close()
input, err := io.ReadAll(f)
if err != nil {
return nil, err
}
m := config.NewModules()
if err := m.Unmarshal(input); err != nil {
return m, err
}
return m, nil
}
// Clean the worktree by removing untracked files.
// An empty dir could be removed - this is what `git clean -f -d .` does.
func (w *Worktree) Clean(opts *CleanOptions) error {
s, err := w.Status()
if err != nil {
return err
}
root := ""
files, err := w.Filesystem.ReadDir(root)
if err != nil {
return err
}
return w.doClean(s, opts, root, files)
}
func (w *Worktree) doClean(status Status, opts *CleanOptions, dir string, files []os.FileInfo) error {
for _, fi := range files {
if fi.Name() == GitDirName {
continue
}
// relative path under the root
path := filepath.Join(dir, fi.Name())
if fi.IsDir() {
if !opts.Dir {
continue
}
subfiles, err := w.Filesystem.ReadDir(path)
if err != nil {
return err
}
err = w.doClean(status, opts, path, subfiles)
if err != nil {
return err
}
} else {
if status.IsUntracked(path) {
if err := w.Filesystem.Remove(path); err != nil {
return err
}
}
}
}
if opts.Dir && dir != "" {
_, err := removeDirIfEmpty(w.Filesystem, dir)
return err
}
return nil
}
// GrepResult is structure of a grep result.
type GrepResult struct {
// FileName is the name of file which contains match.
FileName string
// LineNumber is the line number of a file at which a match was found.
LineNumber int
// Content is the content of the file at the matching line.
Content string
// TreeName is the name of the tree (reference name/commit hash) at
// which the match was performed.
TreeName string
}
func (gr GrepResult) String() string {
return fmt.Sprintf("%s:%s:%d:%s", gr.TreeName, gr.FileName, gr.LineNumber, gr.Content)
}
// Grep performs grep on a repository.
func (r *Repository) Grep(opts *GrepOptions) ([]GrepResult, error) {
if err := opts.validate(r); err != nil {
return nil, err
}
// Obtain commit hash from options (CommitHash or ReferenceName).
var commitHash plumbing.Hash
// treeName contains the value of TreeName in GrepResult.
var treeName string
if opts.ReferenceName != "" {
ref, err := r.Reference(opts.ReferenceName, true)
if err != nil {
return nil, err
}
commitHash = ref.Hash()
treeName = opts.ReferenceName.String()
} else if !opts.CommitHash.IsZero() {
commitHash = opts.CommitHash
treeName = opts.CommitHash.String()
}
// Obtain a tree from the commit hash and get a tracked files iterator from
// the tree.
tree, err := r.getTreeFromCommitHash(commitHash)
if err != nil {
return nil, err
}
fileiter := tree.Files()
return findMatchInFiles(fileiter, treeName, opts)
}
// Grep performs grep on a worktree.
func (w *Worktree) Grep(opts *GrepOptions) ([]GrepResult, error) {
return w.r.Grep(opts)
}
// findMatchInFiles takes a FileIter, worktree name and GrepOptions, and
// returns a slice of GrepResult containing the result of regex pattern matching
// in content of all the files.
func findMatchInFiles(fileiter *object.FileIter, treeName string, opts *GrepOptions) ([]GrepResult, error) {
var results []GrepResult
err := fileiter.ForEach(func(file *object.File) error {
var fileInPathSpec bool
// When no pathspecs are provided, search all the files.
if len(opts.PathSpecs) == 0 {
fileInPathSpec = true
}
// Check if the file name matches with the pathspec. Break out of the
// loop once a match is found.
for _, pathSpec := range opts.PathSpecs {
if pathSpec != nil && pathSpec.MatchString(file.Name) {
fileInPathSpec = true
break
}
}
// If the file does not match with any of the pathspec, skip it.
if !fileInPathSpec {
return nil
}
grepResults, err := findMatchInFile(file, treeName, opts)
if err != nil {
return err
}
results = append(results, grepResults...)
return nil
})
return results, err
}
// findMatchInFile takes a single File, worktree name and GrepOptions,
// and returns a slice of GrepResult containing the result of regex pattern
// matching in the given file.
func findMatchInFile(file *object.File, treeName string, opts *GrepOptions) ([]GrepResult, error) {
var grepResults []GrepResult
content, err := file.Contents()
if err != nil {
return grepResults, err
}
// Split the file content and parse line-by-line.
contentByLine := strings.Split(content, "\n")
for lineNum, cnt := range contentByLine {
addToResult := false
// Match the patterns and content. Break out of the loop once a
// match is found.
for _, pattern := range opts.Patterns {
if pattern != nil && pattern.MatchString(cnt) {
// Add to result only if invert match is not enabled.
if !opts.InvertMatch {
addToResult = true
break
}
} else if opts.InvertMatch {
// If matching fails, and invert match is enabled, add to
// results.
addToResult = true
break
}
}
if addToResult {
grepResults = append(grepResults, GrepResult{
FileName: file.Name,
LineNumber: lineNum + 1,
Content: cnt,
TreeName: treeName,
})
}
}
return grepResults, nil
}
// will walk up the directory tree removing all encountered empty
// directories, not just the one containing this file
func rmFileAndDirsIfEmpty(fs billy.Filesystem, name string) error {
if err := util.RemoveAll(fs, name); err != nil {
return err
}
dir := filepath.Dir(name)
for {
removed, err := removeDirIfEmpty(fs, dir)
if err != nil && !os.IsNotExist(err) {
return err
}
if !removed {
// directory was not empty and not removed,
// stop checking parents
break
}
// move to parent directory
dir = filepath.Dir(dir)
}
return nil
}
// removeDirIfEmpty will remove the supplied directory `dir` if
// `dir` is empty
// returns true if the directory was removed
func removeDirIfEmpty(fs billy.Filesystem, dir string) (bool, error) {
files, err := fs.ReadDir(dir)
if err != nil {
return false, err
}
if len(files) > 0 {
return false, nil
}
err = fs.Remove(dir)
if err != nil {
return false, err
}
return true, nil
}
type indexBuilder struct {
entries map[string]*index.Entry
}
func newIndexBuilder(idx *index.Index) *indexBuilder {
entries := make(map[string]*index.Entry, len(idx.Entries))
for _, e := range idx.Entries {
entries[e.Name] = e
}
return &indexBuilder{
entries: entries,
}
}
func (b *indexBuilder) Write(idx *index.Index) {
idx.Entries = idx.Entries[:0]
for _, e := range b.entries {
idx.Entries = append(idx.Entries, e)
}
}
func (b *indexBuilder) Add(e *index.Entry) {
b.entries[e.Name] = e
}
func (b *indexBuilder) Remove(name string) {
delete(b.entries, filepath.ToSlash(name))
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_bsd.go
================================================
// +build darwin freebsd netbsd
package git
import (
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Stat_t); ok {
e.CreatedAt = time.Unix(os.Atimespec.Unix())
e.Dev = uint32(os.Dev)
e.Inode = uint32(os.Ino)
e.GID = os.Gid
e.UID = os.Uid
}
}
}
func isSymlinkWindowsNonAdmin(err error) bool {
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_commit.go
================================================
package git
import (
"bytes"
"errors"
"io"
"path"
"regexp"
"sort"
"strings"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/storage"
"github.com/ProtonMail/go-crypto/openpgp"
"github.com/ProtonMail/go-crypto/openpgp/packet"
"github.com/go-git/go-billy/v5"
)
var (
// ErrEmptyCommit occurs when a commit is attempted using a clean
// working tree, with no changes to be committed.
ErrEmptyCommit = errors.New("cannot create empty commit: clean working tree")
// characters to be removed from user name and/or email before using them to build a commit object
// See https://git-scm.com/docs/git-commit#_commit_information
invalidCharactersRe = regexp.MustCompile(`[<>\n]`)
)
// Commit stores the current contents of the index in a new commit along with
// a log message from the user describing the changes.
func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error) {
if err := opts.Validate(w.r); err != nil {
return plumbing.ZeroHash, err
}
if opts.All {
if err := w.autoAddModifiedAndDeleted(); err != nil {
return plumbing.ZeroHash, err
}
}
if opts.Amend {
head, err := w.r.Head()
if err != nil {
return plumbing.ZeroHash, err
}
headCommit, err := w.r.CommitObject(head.Hash())
if err != nil {
return plumbing.ZeroHash, err
}
opts.Parents = nil
if len(headCommit.ParentHashes) != 0 {
opts.Parents = []plumbing.Hash{headCommit.ParentHashes[0]}
}
}
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
// First handle the case of the first commit in the repository being empty.
if len(opts.Parents) == 0 && len(idx.Entries) == 0 && !opts.AllowEmptyCommits {
return plumbing.ZeroHash, ErrEmptyCommit
}
h := &buildTreeHelper{
fs: w.Filesystem,
s: w.r.Storer,
}
treeHash, err := h.BuildTree(idx, opts)
if err != nil {
return plumbing.ZeroHash, err
}
previousTree := plumbing.ZeroHash
if len(opts.Parents) > 0 {
parentCommit, err := w.r.CommitObject(opts.Parents[0])
if err != nil {
return plumbing.ZeroHash, err
}
previousTree = parentCommit.TreeHash
}
if treeHash == previousTree && !opts.AllowEmptyCommits {
return plumbing.ZeroHash, ErrEmptyCommit
}
commit, err := w.buildCommitObject(msg, opts, treeHash)
if err != nil {
return plumbing.ZeroHash, err
}
return commit, w.updateHEAD(commit)
}
func (w *Worktree) autoAddModifiedAndDeleted() error {
s, err := w.Status()
if err != nil {
return err
}
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
for path, fs := range s {
if fs.Worktree != Modified && fs.Worktree != Deleted {
continue
}
if _, _, err := w.doAddFile(idx, s, path, nil); err != nil {
return err
}
}
return w.r.Storer.SetIndex(idx)
}
func (w *Worktree) updateHEAD(commit plumbing.Hash) error {
head, err := w.r.Storer.Reference(plumbing.HEAD)
if err != nil {
return err
}
name := plumbing.HEAD
if head.Type() != plumbing.HashReference {
name = head.Target()
}
ref := plumbing.NewHashReference(name, commit)
return w.r.Storer.SetReference(ref)
}
func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumbing.Hash) (plumbing.Hash, error) {
commit := &object.Commit{
Author: w.sanitize(*opts.Author),
Committer: w.sanitize(*opts.Committer),
Message: msg,
TreeHash: tree,
ParentHashes: opts.Parents,
}
// Convert SignKey into a Signer if set. Existing Signer should take priority.
signer := opts.Signer
if signer == nil && opts.SignKey != nil {
signer = &gpgSigner{key: opts.SignKey}
}
if signer != nil {
sig, err := signObject(signer, commit)
if err != nil {
return plumbing.ZeroHash, err
}
commit.PGPSignature = string(sig)
}
obj := w.r.Storer.NewEncodedObject()
if err := commit.Encode(obj); err != nil {
return plumbing.ZeroHash, err
}
return w.r.Storer.SetEncodedObject(obj)
}
func (w *Worktree) sanitize(signature object.Signature) object.Signature {
return object.Signature{
Name: invalidCharactersRe.ReplaceAllString(signature.Name, ""),
Email: invalidCharactersRe.ReplaceAllString(signature.Email, ""),
When: signature.When,
}
}
type gpgSigner struct {
key *openpgp.Entity
cfg *packet.Config
}
func (s *gpgSigner) Sign(message io.Reader) ([]byte, error) {
var b bytes.Buffer
if err := openpgp.ArmoredDetachSign(&b, s.key, message, s.cfg); err != nil {
return nil, err
}
return b.Bytes(), nil
}
// buildTreeHelper converts a given index.Index file into multiple git objects
// reading the blobs from the given filesystem and creating the trees from the
// index structure. The created objects are pushed to a given Storer.
type buildTreeHelper struct {
fs billy.Filesystem
s storage.Storer
trees map[string]*object.Tree
entries map[string]*object.TreeEntry
}
// BuildTree builds the tree objects and push its to the storer, the hash
// of the root tree is returned.
func (h *buildTreeHelper) BuildTree(idx *index.Index, opts *CommitOptions) (plumbing.Hash, error) {
const rootNode = ""
h.trees = map[string]*object.Tree{rootNode: {}}
h.entries = map[string]*object.TreeEntry{}
for _, e := range idx.Entries {
if err := h.commitIndexEntry(e); err != nil {
return plumbing.ZeroHash, err
}
}
return h.copyTreeToStorageRecursive(rootNode, h.trees[rootNode])
}
func (h *buildTreeHelper) commitIndexEntry(e *index.Entry) error {
parts := strings.Split(e.Name, "/")
var fullpath string
for _, part := range parts {
parent := fullpath
fullpath = path.Join(fullpath, part)
h.doBuildTree(e, parent, fullpath)
}
return nil
}
func (h *buildTreeHelper) doBuildTree(e *index.Entry, parent, fullpath string) {
if _, ok := h.trees[fullpath]; ok {
return
}
if _, ok := h.entries[fullpath]; ok {
return
}
te := object.TreeEntry{Name: path.Base(fullpath)}
if fullpath == e.Name {
te.Mode = e.Mode
te.Hash = e.Hash
} else {
te.Mode = filemode.Dir
h.trees[fullpath] = &object.Tree{}
}
h.trees[parent].Entries = append(h.trees[parent].Entries, te)
}
type sortableEntries []object.TreeEntry
func (sortableEntries) sortName(te object.TreeEntry) string {
if te.Mode == filemode.Dir {
return te.Name + "/"
}
return te.Name
}
func (se sortableEntries) Len() int { return len(se) }
func (se sortableEntries) Less(i int, j int) bool { return se.sortName(se[i]) < se.sortName(se[j]) }
func (se sortableEntries) Swap(i int, j int) { se[i], se[j] = se[j], se[i] }
func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) {
sort.Sort(sortableEntries(t.Entries))
for i, e := range t.Entries {
if e.Mode != filemode.Dir && !e.Hash.IsZero() {
continue
}
path := path.Join(parent, e.Name)
var err error
e.Hash, err = h.copyTreeToStorageRecursive(path, h.trees[path])
if err != nil {
return plumbing.ZeroHash, err
}
t.Entries[i] = e
}
o := h.s.NewEncodedObject()
if err := t.Encode(o); err != nil {
return plumbing.ZeroHash, err
}
hash := o.Hash()
if h.s.HasEncodedObject(hash) == nil {
return hash, nil
}
return h.s.SetEncodedObject(o)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_js.go
================================================
// +build js
package git
import (
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Stat_t); ok {
e.CreatedAt = time.Unix(int64(os.Ctime), int64(os.CtimeNsec))
e.Dev = uint32(os.Dev)
e.Inode = uint32(os.Ino)
e.GID = os.Gid
e.UID = os.Uid
}
}
}
func isSymlinkWindowsNonAdmin(err error) bool {
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_linux.go
================================================
//go:build linux
// +build linux
package git
import (
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Stat_t); ok {
e.CreatedAt = time.Unix(os.Ctim.Unix())
e.Dev = uint32(os.Dev)
e.Inode = uint32(os.Ino)
e.GID = os.Gid
e.UID = os.Uid
}
}
}
func isSymlinkWindowsNonAdmin(_ error) bool {
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_plan9.go
================================================
package git
import (
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Dir); ok {
// Plan 9 doesn't have a CreatedAt field.
e.CreatedAt = time.Unix(int64(os.Mtime), 0)
e.Dev = uint32(os.Dev)
// Plan 9 has no Inode.
// ext2srv(4) appears to store Inode in Qid.Path.
e.Inode = uint32(os.Qid.Path)
// Plan 9 has string UID/GID
e.GID = 0
e.UID = 0
}
}
}
func isSymlinkWindowsNonAdmin(err error) bool {
return true
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_status.go
================================================
package git
import (
"bytes"
"errors"
"io"
"os"
"path"
"path/filepath"
"strings"
"github.com/go-git/go-billy/v5/util"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/go-git/go-git/v5/plumbing/format/gitignore"
"github.com/go-git/go-git/v5/plumbing/format/index"
"github.com/go-git/go-git/v5/plumbing/object"
"github.com/go-git/go-git/v5/utils/ioutil"
"github.com/go-git/go-git/v5/utils/merkletrie"
"github.com/go-git/go-git/v5/utils/merkletrie/filesystem"
mindex "github.com/go-git/go-git/v5/utils/merkletrie/index"
"github.com/go-git/go-git/v5/utils/merkletrie/noder"
)
var (
// ErrDestinationExists in an Move operation means that the target exists on
// the worktree.
ErrDestinationExists = errors.New("destination exists")
// ErrGlobNoMatches in an AddGlob if the glob pattern does not match any
// files in the worktree.
ErrGlobNoMatches = errors.New("glob pattern did not match any files")
// ErrUnsupportedStatusStrategy occurs when an invalid StatusStrategy is used
// when processing the Worktree status.
ErrUnsupportedStatusStrategy = errors.New("unsupported status strategy")
)
// Status returns the working tree status.
func (w *Worktree) Status() (Status, error) {
return w.StatusWithOptions(StatusOptions{Strategy: defaultStatusStrategy})
}
// StatusOptions defines the options for Worktree.StatusWithOptions().
type StatusOptions struct {
Strategy StatusStrategy
}
// StatusWithOptions returns the working tree status.
func (w *Worktree) StatusWithOptions(o StatusOptions) (Status, error) {
var hash plumbing.Hash
ref, err := w.r.Head()
if err != nil && err != plumbing.ErrReferenceNotFound {
return nil, err
}
if err == nil {
hash = ref.Hash()
}
return w.status(o.Strategy, hash)
}
func (w *Worktree) status(ss StatusStrategy, commit plumbing.Hash) (Status, error) {
s, err := ss.new(w)
if err != nil {
return nil, err
}
left, err := w.diffCommitWithStaging(commit, false)
if err != nil {
return nil, err
}
for _, ch := range left {
a, err := ch.Action()
if err != nil {
return nil, err
}
fs := s.File(nameFromAction(&ch))
fs.Worktree = Unmodified
switch a {
case merkletrie.Delete:
s.File(ch.From.String()).Staging = Deleted
case merkletrie.Insert:
s.File(ch.To.String()).Staging = Added
case merkletrie.Modify:
s.File(ch.To.String()).Staging = Modified
}
}
right, err := w.diffStagingWithWorktree(false, true)
if err != nil {
return nil, err
}
for _, ch := range right {
a, err := ch.Action()
if err != nil {
return nil, err
}
fs := s.File(nameFromAction(&ch))
if fs.Staging == Untracked {
fs.Staging = Unmodified
}
switch a {
case merkletrie.Delete:
fs.Worktree = Deleted
case merkletrie.Insert:
fs.Worktree = Untracked
fs.Staging = Untracked
case merkletrie.Modify:
fs.Worktree = Modified
}
}
return s, nil
}
func nameFromAction(ch *merkletrie.Change) string {
name := ch.To.String()
if name == "" {
return ch.From.String()
}
return name
}
func (w *Worktree) diffStagingWithWorktree(reverse, excludeIgnoredChanges bool) (merkletrie.Changes, error) {
idx, err := w.r.Storer.Index()
if err != nil {
return nil, err
}
from := mindex.NewRootNode(idx)
submodules, err := w.getSubmodulesStatus()
if err != nil {
return nil, err
}
to := filesystem.NewRootNode(w.Filesystem, submodules)
var c merkletrie.Changes
if reverse {
c, err = merkletrie.DiffTree(to, from, diffTreeIsEquals)
} else {
c, err = merkletrie.DiffTree(from, to, diffTreeIsEquals)
}
if err != nil {
return nil, err
}
if excludeIgnoredChanges {
return w.excludeIgnoredChanges(c), nil
}
return c, nil
}
func (w *Worktree) excludeIgnoredChanges(changes merkletrie.Changes) merkletrie.Changes {
patterns, err := gitignore.ReadPatterns(w.Filesystem, nil)
if err != nil {
return changes
}
patterns = append(patterns, w.Excludes...)
if len(patterns) == 0 {
return changes
}
m := gitignore.NewMatcher(patterns)
var res merkletrie.Changes
for _, ch := range changes {
var path []string
for _, n := range ch.To {
path = append(path, n.Name())
}
if len(path) == 0 {
for _, n := range ch.From {
path = append(path, n.Name())
}
}
if len(path) != 0 {
isDir := (len(ch.To) > 0 && ch.To.IsDir()) || (len(ch.From) > 0 && ch.From.IsDir())
if m.Match(path, isDir) {
if len(ch.From) == 0 {
continue
}
}
}
res = append(res, ch)
}
return res
}
func (w *Worktree) getSubmodulesStatus() (map[string]plumbing.Hash, error) {
o := map[string]plumbing.Hash{}
sub, err := w.Submodules()
if err != nil {
return nil, err
}
status, err := sub.Status()
if err != nil {
return nil, err
}
for _, s := range status {
if s.Current.IsZero() {
o[s.Path] = s.Expected
continue
}
o[s.Path] = s.Current
}
return o, nil
}
func (w *Worktree) diffCommitWithStaging(commit plumbing.Hash, reverse bool) (merkletrie.Changes, error) {
var t *object.Tree
if !commit.IsZero() {
c, err := w.r.CommitObject(commit)
if err != nil {
return nil, err
}
t, err = c.Tree()
if err != nil {
return nil, err
}
}
return w.diffTreeWithStaging(t, reverse)
}
func (w *Worktree) diffTreeWithStaging(t *object.Tree, reverse bool) (merkletrie.Changes, error) {
var from noder.Noder
if t != nil {
from = object.NewTreeRootNode(t)
}
idx, err := w.r.Storer.Index()
if err != nil {
return nil, err
}
to := mindex.NewRootNode(idx)
if reverse {
return merkletrie.DiffTree(to, from, diffTreeIsEquals)
}
return merkletrie.DiffTree(from, to, diffTreeIsEquals)
}
var emptyNoderHash = make([]byte, 24)
// diffTreeIsEquals is a implementation of noder.Equals, used to compare
// noder.Noder, it compare the content and the length of the hashes.
//
// Since some of the noder.Noder implementations doesn't compute a hash for
// some directories, if any of the hashes is a 24-byte slice of zero values
// the comparison is not done and the hashes are take as different.
func diffTreeIsEquals(a, b noder.Hasher) bool {
hashA := a.Hash()
hashB := b.Hash()
if bytes.Equal(hashA, emptyNoderHash) || bytes.Equal(hashB, emptyNoderHash) {
return false
}
return bytes.Equal(hashA, hashB)
}
// Add adds the file contents of a file in the worktree to the index. if the
// file is already staged in the index no error is returned. If a file deleted
// from the Workspace is given, the file is removed from the index. If a
// directory given, adds the files and all his sub-directories recursively in
// the worktree to the index. If any of the files is already staged in the index
// no error is returned. When path is a file, the blob.Hash is returned.
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
// TODO(mcuadros): deprecate in favor of AddWithOption in v6.
return w.doAdd(path, make([]gitignore.Pattern, 0), false)
}
func (w *Worktree) doAddDirectory(idx *index.Index, s Status, directory string, ignorePattern []gitignore.Pattern) (added bool, err error) {
if len(ignorePattern) > 0 {
m := gitignore.NewMatcher(ignorePattern)
matchPath := strings.Split(directory, string(os.PathSeparator))
if m.Match(matchPath, true) {
// ignore
return false, nil
}
}
directory = filepath.ToSlash(filepath.Clean(directory))
for name := range s {
if !isPathInDirectory(name, directory) {
continue
}
var a bool
a, _, err = w.doAddFile(idx, s, name, ignorePattern)
if err != nil {
return
}
added = added || a
}
return
}
func isPathInDirectory(path, directory string) bool {
return directory == "." || strings.HasPrefix(path, directory+"/")
}
// AddWithOptions file contents to the index, updates the index using the
// current content found in the working tree, to prepare the content staged for
// the next commit.
//
// It typically adds the current content of existing paths as a whole, but with
// some options it can also be used to add content with only part of the changes
// made to the working tree files applied, or remove paths that do not exist in
// the working tree anymore.
func (w *Worktree) AddWithOptions(opts *AddOptions) error {
if err := opts.Validate(w.r); err != nil {
return err
}
if opts.All {
_, err := w.doAdd(".", w.Excludes, false)
return err
}
if opts.Glob != "" {
return w.AddGlob(opts.Glob)
}
_, err := w.doAdd(opts.Path, make([]gitignore.Pattern, 0), opts.SkipStatus)
return err
}
func (w *Worktree) doAdd(path string, ignorePattern []gitignore.Pattern, skipStatus bool) (plumbing.Hash, error) {
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
var h plumbing.Hash
var added bool
fi, err := w.Filesystem.Lstat(path)
// status is required for doAddDirectory
var s Status
var err2 error
if !skipStatus || fi == nil || fi.IsDir() {
s, err2 = w.Status()
if err2 != nil {
return plumbing.ZeroHash, err2
}
}
path = filepath.Clean(path)
if err != nil || !fi.IsDir() {
added, h, err = w.doAddFile(idx, s, path, ignorePattern)
} else {
added, err = w.doAddDirectory(idx, s, path, ignorePattern)
}
if err != nil {
return h, err
}
if !added {
return h, nil
}
return h, w.r.Storer.SetIndex(idx)
}
// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
// directory path, all directory contents are added to the index recursively. No
// error is returned if all matching paths are already staged in index.
func (w *Worktree) AddGlob(pattern string) error {
// TODO(mcuadros): deprecate in favor of AddWithOption in v6.
files, err := util.Glob(w.Filesystem, pattern)
if err != nil {
return err
}
if len(files) == 0 {
return ErrGlobNoMatches
}
s, err := w.Status()
if err != nil {
return err
}
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
var saveIndex bool
for _, file := range files {
fi, err := w.Filesystem.Lstat(file)
if err != nil {
return err
}
var added bool
if fi.IsDir() {
added, err = w.doAddDirectory(idx, s, file, make([]gitignore.Pattern, 0))
} else {
added, _, err = w.doAddFile(idx, s, file, make([]gitignore.Pattern, 0))
}
if err != nil {
return err
}
if !saveIndex && added {
saveIndex = true
}
}
if saveIndex {
return w.r.Storer.SetIndex(idx)
}
return nil
}
// doAddFile create a new blob from path and update the index, added is true if
// the file added is different from the index.
// if s status is nil will skip the status check and update the index anyway
func (w *Worktree) doAddFile(idx *index.Index, s Status, path string, ignorePattern []gitignore.Pattern) (added bool, h plumbing.Hash, err error) {
if s != nil && s.File(path).Worktree == Unmodified {
return false, h, nil
}
if len(ignorePattern) > 0 {
m := gitignore.NewMatcher(ignorePattern)
matchPath := strings.Split(path, string(os.PathSeparator))
if m.Match(matchPath, true) {
// ignore
return false, h, nil
}
}
h, err = w.copyFileToStorage(path)
if err != nil {
if os.IsNotExist(err) {
added = true
h, err = w.deleteFromIndex(idx, path)
}
return
}
if err := w.addOrUpdateFileToIndex(idx, path, h); err != nil {
return false, h, err
}
return true, h, err
}
func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error) {
fi, err := w.Filesystem.Lstat(path)
if err != nil {
return plumbing.ZeroHash, err
}
obj := w.r.Storer.NewEncodedObject()
obj.SetType(plumbing.BlobObject)
obj.SetSize(fi.Size())
writer, err := obj.Writer()
if err != nil {
return plumbing.ZeroHash, err
}
defer ioutil.CheckClose(writer, &err)
if fi.Mode()&os.ModeSymlink != 0 {
err = w.fillEncodedObjectFromSymlink(writer, path, fi)
} else {
err = w.fillEncodedObjectFromFile(writer, path, fi)
}
if err != nil {
return plumbing.ZeroHash, err
}
return w.r.Storer.SetEncodedObject(obj)
}
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, _ os.FileInfo) (err error) {
src, err := w.Filesystem.Open(path)
if err != nil {
return err
}
defer ioutil.CheckClose(src, &err)
if _, err := io.Copy(dst, src); err != nil {
return err
}
return err
}
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, _ os.FileInfo) error {
target, err := w.Filesystem.Readlink(path)
if err != nil {
return err
}
_, err = dst.Write([]byte(target))
return err
}
func (w *Worktree) addOrUpdateFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error {
e, err := idx.Entry(filename)
if err != nil && err != index.ErrEntryNotFound {
return err
}
if err == index.ErrEntryNotFound {
return w.doAddFileToIndex(idx, filename, h)
}
return w.doUpdateFileToIndex(e, filename, h)
}
func (w *Worktree) doAddFileToIndex(idx *index.Index, filename string, h plumbing.Hash) error {
return w.doUpdateFileToIndex(idx.Add(filename), filename, h)
}
func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbing.Hash) error {
info, err := w.Filesystem.Lstat(filename)
if err != nil {
return err
}
e.Hash = h
e.ModifiedAt = info.ModTime()
e.Mode, err = filemode.NewFromOSFileMode(info.Mode())
if err != nil {
return err
}
// The entry size must always reflect the current state, otherwise
// it will cause go-git's Worktree.Status() to divert from "git status".
// The size of a symlink is the length of the path to the target.
// The size of Regular and Executable files is the size of the files.
e.Size = uint32(info.Size())
fillSystemInfo(e, info.Sys())
return nil
}
// Remove removes files from the working tree and from the index.
func (w *Worktree) Remove(path string) (plumbing.Hash, error) {
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
var h plumbing.Hash
fi, err := w.Filesystem.Lstat(path)
if err != nil || !fi.IsDir() {
h, err = w.doRemoveFile(idx, path)
} else {
_, err = w.doRemoveDirectory(idx, path)
}
if err != nil {
return h, err
}
return h, w.r.Storer.SetIndex(idx)
}
func (w *Worktree) doRemoveDirectory(idx *index.Index, directory string) (removed bool, err error) {
files, err := w.Filesystem.ReadDir(directory)
if err != nil {
return false, err
}
for _, file := range files {
name := path.Join(directory, file.Name())
var r bool
if file.IsDir() {
r, err = w.doRemoveDirectory(idx, name)
} else {
_, err = w.doRemoveFile(idx, name)
if err == index.ErrEntryNotFound {
err = nil
}
}
if err != nil {
return
}
if !removed && r {
removed = true
}
}
err = w.removeEmptyDirectory(directory)
return
}
func (w *Worktree) removeEmptyDirectory(path string) error {
files, err := w.Filesystem.ReadDir(path)
if err != nil {
return err
}
if len(files) != 0 {
return nil
}
return w.Filesystem.Remove(path)
}
func (w *Worktree) doRemoveFile(idx *index.Index, path string) (plumbing.Hash, error) {
hash, err := w.deleteFromIndex(idx, path)
if err != nil {
return plumbing.ZeroHash, err
}
return hash, w.deleteFromFilesystem(path)
}
func (w *Worktree) deleteFromIndex(idx *index.Index, path string) (plumbing.Hash, error) {
e, err := idx.Remove(path)
if err != nil {
return plumbing.ZeroHash, err
}
return e.Hash, nil
}
func (w *Worktree) deleteFromFilesystem(path string) error {
err := w.Filesystem.Remove(path)
if os.IsNotExist(err) {
return nil
}
return err
}
// RemoveGlob removes all paths, matching pattern, from the index. If pattern
// matches a directory path, all directory contents are removed from the index
// recursively.
func (w *Worktree) RemoveGlob(pattern string) error {
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
entries, err := idx.Glob(pattern)
if err != nil {
return err
}
for _, e := range entries {
file := filepath.FromSlash(e.Name)
if _, err := w.Filesystem.Lstat(file); err != nil && !os.IsNotExist(err) {
return err
}
if _, err := w.doRemoveFile(idx, file); err != nil {
return err
}
dir, _ := filepath.Split(file)
if err := w.removeEmptyDirectory(dir); err != nil {
return err
}
}
return w.r.Storer.SetIndex(idx)
}
// Move moves or rename a file in the worktree and the index, directories are
// not supported.
func (w *Worktree) Move(from, to string) (plumbing.Hash, error) {
// TODO(mcuadros): support directories and/or implement support for glob
if _, err := w.Filesystem.Lstat(from); err != nil {
return plumbing.ZeroHash, err
}
if _, err := w.Filesystem.Lstat(to); err == nil {
return plumbing.ZeroHash, ErrDestinationExists
}
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
hash, err := w.deleteFromIndex(idx, from)
if err != nil {
return plumbing.ZeroHash, err
}
if err := w.Filesystem.Rename(from, to); err != nil {
return hash, err
}
if err := w.addOrUpdateFileToIndex(idx, to, hash); err != nil {
return hash, err
}
return hash, w.r.Storer.SetIndex(idx)
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_unix_other.go
================================================
// +build openbsd dragonfly solaris
package git
import (
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Stat_t); ok {
e.CreatedAt = time.Unix(os.Atim.Unix())
e.Dev = uint32(os.Dev)
e.Inode = uint32(os.Ino)
e.GID = os.Gid
e.UID = os.Uid
}
}
}
func isSymlinkWindowsNonAdmin(err error) bool {
return false
}
================================================
FILE: vendor/github.com/go-git/go-git/v5/worktree_windows.go
================================================
// +build windows
package git
import (
"os"
"syscall"
"time"
"github.com/go-git/go-git/v5/plumbing/format/index"
)
func init() {
fillSystemInfo = func(e *index.Entry, sys interface{}) {
if os, ok := sys.(*syscall.Win32FileAttributeData); ok {
seconds := os.CreationTime.Nanoseconds() / 1000000000
nanoseconds := os.CreationTime.Nanoseconds() - seconds*1000000000
e.CreatedAt = time.Unix(seconds, nanoseconds)
}
}
}
func isSymlinkWindowsNonAdmin(err error) bool {
const ERROR_PRIVILEGE_NOT_HELD syscall.Errno = 1314
if err != nil {
if errLink, ok := err.(*os.LinkError); ok {
if errNo, ok := errLink.Err.(syscall.Errno); ok {
return errNo == ERROR_PRIVILEGE_NOT_HELD
}
}
}
return false
}
================================================
FILE: vendor/github.com/goccy/go-json/.codecov.yml
================================================
codecov:
require_ci_to_pass: yes
coverage:
precision: 2
round: down
range: "70...100"
status:
project:
default:
target: 70%
threshold: 2%
patch: off
changes: no
parsers:
gcov:
branch_detection:
conditional: yes
loop: yes
method: no
macro: no
comment:
layout: "header,diff"
behavior: default
require_changes: no
ignore:
- internal/encoder/vm_color
- internal/encoder/vm_color_indent
================================================
FILE: vendor/github.com/goccy/go-json/.gitignore
================================================
cover.html
cover.out
================================================
FILE: vendor/github.com/goccy/go-json/.golangci.yml
================================================
run:
skip-files:
- encode_optype.go
- ".*_test\\.go$"
linters-settings:
govet:
enable-all: true
disable:
- shadow
linters:
enable-all: true
disable:
- dogsled
- dupl
- exhaustive
- exhaustivestruct
- errorlint
- forbidigo
- funlen
- gci
- gochecknoglobals
- gochecknoinits
- gocognit
- gocritic
- gocyclo
- godot
- godox
- goerr113
- gofumpt
- gomnd
- gosec
- ifshort
- lll
- makezero
- nakedret
- nestif
- nlreturn
- paralleltest
- testpackage
- thelper
- wrapcheck
- interfacer
- lll
- nakedret
- nestif
- nlreturn
- testpackage
- wsl
- varnamelen
- nilnil
- ireturn
- govet
- forcetypeassert
- cyclop
- containedctx
- revive
issues:
exclude-rules:
# not needed
- path: /*.go
text: "ST1003: should not use underscores in package names"
linters:
- stylecheck
- path: /*.go
text: "don't use an underscore in package name"
linters:
- golint
- path: rtype.go
linters:
- golint
- stylecheck
- path: error.go
linters:
- staticcheck
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0
================================================
FILE: vendor/github.com/goccy/go-json/CHANGELOG.md
================================================
# v0.9.11 - 2022/08/18
### Fix bugs
* Fix unexpected behavior when buffer ends with backslash ( #383 )
* Fix stream decoding of escaped character ( #387 )
# v0.9.10 - 2022/07/15
### Fix bugs
* Fix boundary exception of type caching ( #382 )
# v0.9.9 - 2022/07/15
### Fix bugs
* Fix encoding of directed interface with typed nil ( #377 )
* Fix embedded primitive type encoding using alias ( #378 )
* Fix slice/array type encoding with types implementing MarshalJSON ( #379 )
* Fix unicode decoding when the expected buffer state is not met after reading ( #380 )
# v0.9.8 - 2022/06/30
### Fix bugs
* Fix decoding of surrogate-pair ( #365 )
* Fix handling of embedded primitive type ( #366 )
* Add validation of escape sequence for decoder ( #367 )
* Fix stream tokenizing respecting UseNumber ( #369 )
* Fix encoding when struct pointer type that implements Marshal JSON is embedded ( #375 )
### Improve performance
* Improve performance of linkRecursiveCode ( #368 )
# v0.9.7 - 2022/04/22
### Fix bugs
#### Encoder
* Add filtering process for encoding on slow path ( #355 )
* Fix encoding of interface{} with pointer type ( #363 )
#### Decoder
* Fix map key decoder that implements UnmarshalJSON ( #353 )
* Fix decoding of []uint8 type ( #361 )
### New features
* Add DebugWith option for encoder ( #356 )
# v0.9.6 - 2022/03/22
### Fix bugs
* Correct the handling of the minimum value of int type for decoder ( #344 )
* Fix bugs of stream decoder's bufferSize ( #349 )
* Add a guard to use typeptr more safely ( #351 )
### Improve decoder performance
* Improve escapeString's performance ( #345 )
### Others
* Update go version for CI ( #347 )
# v0.9.5 - 2022/03/04
### Fix bugs
* Fix panic when decoding time.Time with context ( #328 )
* Fix reading the next character in buffer to nul consideration ( #338 )
* Fix incorrect handling on skipValue ( #341 )
### Improve decoder performance
* Improve performance when a payload contains escape sequence ( #334 )
# v0.9.4 - 2022/01/21
* Fix IsNilForMarshaler for string type with omitempty ( #323 )
* Fix the case where the embedded field is at the end ( #326 )
# v0.9.3 - 2022/01/14
* Fix logic of removing struct field for decoder ( #322 )
# v0.9.2 - 2022/01/14
* Add invalid decoder to delay type error judgment at decode ( #321 )
# v0.9.1 - 2022/01/11
* Fix encoding of MarshalText/MarshalJSON operation with head offset ( #319 )
# v0.9.0 - 2022/01/05
### New feature
* Supports dynamic filtering of struct fields ( #314 )
### Improve encoding performance
* Improve map encoding performance ( #310 )
* Optimize encoding path for escaped string ( #311 )
* Add encoding option for performance ( #312 )
### Fix bugs
* Fix panic at encoding map value on 1.18 ( #310 )
* Fix MarshalIndent for interface type ( #317 )
# v0.8.1 - 2021/12/05
* Fix operation conversion from PtrHead to Head in Recursive type ( #305 )
# v0.8.0 - 2021/12/02
* Fix embedded field conflict behavior ( #300 )
* Refactor compiler for encoder ( #301 #302 )
# v0.7.10 - 2021/10/16
* Fix conversion from pointer to uint64 ( #294 )
# v0.7.9 - 2021/09/28
* Fix encoding of nil value about interface type that has method ( #291 )
# v0.7.8 - 2021/09/01
* Fix mapassign_faststr for indirect struct type ( #283 )
* Fix encoding of not empty interface type ( #284 )
* Fix encoding of empty struct interface type ( #286 )
# v0.7.7 - 2021/08/25
* Fix invalid utf8 on stream decoder ( #279 )
* Fix buffer length bug on string stream decoder ( #280 )
Thank you @orisano !!
# v0.7.6 - 2021/08/13
* Fix nil slice assignment ( #276 )
* Improve error message ( #277 )
# v0.7.5 - 2021/08/12
* Fix encoding of embedded struct with tags ( #265 )
* Fix encoding of embedded struct that isn't first field ( #272 )
* Fix decoding of binary type with escaped char ( #273 )
# v0.7.4 - 2021/07/06
* Fix encoding of indirect layout structure ( #264 )
# v0.7.3 - 2021/06/29
* Fix encoding of pointer type in empty interface ( #262 )
# v0.7.2 - 2021/06/26
### Fix decoder
* Add decoder for func type to fix decoding of nil function value ( #257 )
* Fix stream decoding of []byte type ( #258 )
### Performance
* Improve decoding performance of map[string]interface{} type ( use `mapassign_faststr` ) ( #256 )
* Improve encoding performance of empty interface type ( remove recursive calling of `vm.Run` ) ( #259 )
### Benchmark
* Add bytedance/sonic as benchmark target ( #254 )
# v0.7.1 - 2021/06/18
### Fix decoder
* Fix error when unmarshal empty array ( #253 )
# v0.7.0 - 2021/06/12
### Support context for MarshalJSON and UnmarshalJSON ( #248 )
* json.MarshalContext(context.Context, interface{}, ...json.EncodeOption) ([]byte, error)
* json.NewEncoder(io.Writer).EncodeContext(context.Context, interface{}, ...json.EncodeOption) error
* json.UnmarshalContext(context.Context, []byte, interface{}, ...json.DecodeOption) error
* json.NewDecoder(io.Reader).DecodeContext(context.Context, interface{}) error
```go
type MarshalerContext interface {
MarshalJSON(context.Context) ([]byte, error)
}
type UnmarshalerContext interface {
UnmarshalJSON(context.Context, []byte) error
}
```
### Add DecodeFieldPriorityFirstWin option ( #242 )
In the default behavior, go-json, like encoding/json, will reflect the result of the last evaluation when a field with the same name exists. I've added new options to allow you to change this behavior. `json.DecodeFieldPriorityFirstWin` option reflects the result of the first evaluation if a field with the same name exists. This behavior has a performance advantage as it allows the subsequent strings to be skipped if all fields have been evaluated.
### Fix encoder
* Fix indent number contains recursive type ( #249 )
* Fix encoding of using empty interface as map key ( #244 )
### Fix decoder
* Fix decoding fields containing escaped characters ( #237 )
### Refactor
* Move some tests to subdirectory ( #243 )
* Refactor package layout for decoder ( #238 )
# v0.6.1 - 2021/06/02
### Fix encoder
* Fix value of totalLength for encoding ( #236 )
# v0.6.0 - 2021/06/01
### Support Colorize option for encoding (#233)
```go
b, err := json.MarshalWithOption(v, json.Colorize(json.DefaultColorScheme))
if err != nil {
...
}
fmt.Println(string(b)) // print colored json
```
### Refactor
* Fix opcode layout - Adjust memory layout of the opcode to 128 bytes in a 64-bit environment ( #230 )
* Refactor encode option ( #231 )
* Refactor escape string ( #232 )
# v0.5.1 - 2021/5/20
### Optimization
* Add type addrShift to enable bigger encoder/decoder cache ( #213 )
### Fix decoder
* Keep original reference of slice element ( #229 )
### Refactor
* Refactor Debug mode for encoding ( #226 )
* Generate VM sources for encoding ( #227 )
* Refactor validator for null/true/false for decoding ( #221 )
# v0.5.0 - 2021/5/9
### Supports using omitempty and string tags at the same time ( #216 )
### Fix decoder
* Fix stream decoder for unicode char ( #215 )
* Fix decoding of slice element ( #219 )
* Fix calculating of buffer length for stream decoder ( #220 )
### Refactor
* replace skipWhiteSpace goto by loop ( #212 )
# v0.4.14 - 2021/5/4
### Benchmark
* Add valyala/fastjson to benchmark ( #193 )
* Add benchmark task for CI ( #211 )
### Fix decoder
* Fix decoding of slice with unmarshal json type ( #198 )
* Fix decoding of null value for interface type that does not implement Unmarshaler ( #205 )
* Fix decoding of null value to []byte by json.Unmarshal ( #206 )
* Fix decoding of backslash char at the end of string ( #207 )
* Fix stream decoder for null/true/false value ( #208 )
* Fix stream decoder for slow reader ( #211 )
### Performance
* If cap of slice is enough, reuse slice data for compatibility with encoding/json ( #200 )
# v0.4.13 - 2021/4/20
### Fix json.Compact and json.Indent
* Support validation the input buffer for json.Compact and json.Indent ( #189 )
* Optimize json.Compact and json.Indent ( improve memory footprint ) ( #190 )
# v0.4.12 - 2021/4/15
### Fix encoder
* Fix unnecessary indent for empty slice type ( #181 )
* Fix encoding of omitempty feature for the slice or interface type ( #183 )
* Fix encoding custom types zero values with omitempty when marshaller exists ( #187 )
### Fix decoder
* Fix decoder for invalid top level value ( #184 )
* Fix decoder for invalid number value ( #185 )
# v0.4.11 - 2021/4/3
* Improve decoder performance for interface type
# v0.4.10 - 2021/4/2
### Fix encoder
* Fixed a bug when encoding slice and map containing recursive structures
* Fixed a logic to determine if indirect reference
# v0.4.9 - 2021/3/29
### Add debug mode
If you use `json.MarshalWithOption(v, json.Debug())` and `panic` occurred in `go-json`, produces debug information to console.
### Support a new feature to compatible with encoding/json
- invalid UTF-8 is coerced to valid UTF-8 ( without performance down )
### Fix encoder
- Fixed handling of MarshalJSON of function type
### Fix decoding of slice of pointer type
If there is a pointer value, go-json will use it. (This behavior is necessary to achieve the ability to prioritize pre-filled values). However, since slices are reused internally, there was a bug that referred to the previous pointer value. Therefore, it is not necessary to refer to the pointer value in advance for the slice element, so we explicitly initialize slice element by `nil`.
# v0.4.8 - 2021/3/21
### Reduce memory usage at compile time
* go-json have used about 2GB of memory at compile time, but now it can compile with about less than 550MB.
### Fix any encoder's bug
* Add many test cases for encoder
* Fix composite type ( slice/array/map )
* Fix pointer types
* Fix encoding of MarshalJSON or MarshalText or json.Number type
### Refactor encoder
* Change package layout for reducing memory usage at compile
* Remove anonymous and only operation
* Remove root property from encodeCompileContext and opcode
### Fix CI
* Add Go 1.16
* Remove Go 1.13
* Fix `make cover` task
### Number/Delim/Token/RawMessage use the types defined in encoding/json by type alias
# v0.4.7 - 2021/02/22
### Fix decoder
* Fix decoding of deep recursive structure
* Fix decoding of embedded unexported pointer field
* Fix invalid test case
* Fix decoding of invalid value
* Fix decoding of prefilled value
* Fix not being able to return UnmarshalTypeError when it should be returned
* Fix decoding of null value
* Fix decoding of type of null string
* Use pre allocated pointer if exists it at decoding
### Reduce memory usage at compile
* Integrate int/int8/int16/int32/int64 and uint/uint8/uint16/uint32/uint64 operation to reduce memory usage at compile
### Remove unnecessary optype
================================================
FILE: vendor/github.com/goccy/go-json/LICENSE
================================================
MIT License
Copyright (c) 2020 Masaaki Goshima
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: vendor/github.com/goccy/go-json/Makefile
================================================
PKG := github.com/goccy/go-json
BIN_DIR := $(CURDIR)/bin
PKGS := $(shell go list ./... | grep -v internal/cmd|grep -v test)
COVER_PKGS := $(foreach pkg,$(PKGS),$(subst $(PKG),.,$(pkg)))
COMMA := ,
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
COVERPKG_OPT := $(subst $(SPACE),$(COMMA),$(COVER_PKGS))
$(BIN_DIR):
@mkdir -p $(BIN_DIR)
.PHONY: cover
cover:
go test -coverpkg=$(COVERPKG_OPT) -coverprofile=cover.out ./...
.PHONY: cover-html
cover-html: cover
go tool cover -html=cover.out
.PHONY: lint
lint: golangci-lint
golangci-lint run
golangci-lint: | $(BIN_DIR)
@{ \
set -e; \
GOLANGCI_LINT_TMP_DIR=$$(mktemp -d); \
cd $$GOLANGCI_LINT_TMP_DIR; \
go mod init tmp; \
GOBIN=$(BIN_DIR) go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.36.0; \
rm -rf $$GOLANGCI_LINT_TMP_DIR; \
}
.PHONY: generate
generate:
go generate ./internal/...
================================================
FILE: vendor/github.com/goccy/go-json/README.md
================================================
# go-json

[](https://pkg.go.dev/github.com/goccy/go-json?tab=doc)
[](https://codecov.io/gh/goccy/go-json)
Fast JSON encoder/decoder compatible with encoding/json for Go
# Roadmap
```
* version ( expected release date )
* v0.9.0
|
| while maintaining compatibility with encoding/json, we will add convenient APIs
|
v
* v1.0.0
```
We are accepting requests for features that will be implemented between v0.9.0 and v.1.0.0.
If you have the API you need, please submit your issue [here](https://github.com/goccy/go-json/issues).
# Features
- Drop-in replacement of `encoding/json`
- Fast ( See [Benchmark section](https://github.com/goccy/go-json#benchmarks) )
- Flexible customization with options
- Coloring the encoded string
- Can propagate context.Context to `MarshalJSON` or `UnmarshalJSON`
- Can dynamically filter the fields of the structure type-safely
# Installation
```
go get github.com/goccy/go-json
```
# How to use
Replace import statement from `encoding/json` to `github.com/goccy/go-json`
```
-import "encoding/json"
+import "github.com/goccy/go-json"
```
# JSON library comparison
| name | encoder | decoder | compatible with `encoding/json` |
| :----: | :------: | :-----: | :-----------------------------: |
| encoding/json | yes | yes | N/A |
| [json-iterator/go](https://github.com/json-iterator/go) | yes | yes | partial |
| [easyjson](https://github.com/mailru/easyjson) | yes | yes | no |
| [gojay](https://github.com/francoispqt/gojay) | yes | yes | no |
| [segmentio/encoding/json](https://github.com/segmentio/encoding/tree/master/json) | yes | yes | partial |
| [jettison](https://github.com/wI2L/jettison) | yes | no | no |
| [simdjson-go](https://github.com/minio/simdjson-go) | no | yes | no |
| goccy/go-json | yes | yes | yes |
- `json-iterator/go` isn't compatible with `encoding/json` in many ways (e.g. https://github.com/json-iterator/go/issues/229 ), but it hasn't been supported for a long time.
- `segmentio/encoding/json` is well supported for encoders, but some are not supported for decoder APIs such as `Token` ( streaming decode )
## Other libraries
- [jingo](https://github.com/bet365/jingo)
I tried the benchmark but it didn't work.
Also, it seems to panic when it receives an unexpected value because there is no error handling...
- [ffjson](https://github.com/pquerna/ffjson)
Benchmarking gave very slow results.
It seems that it is assumed that the user will use the buffer pool properly.
Also, development seems to have already stopped
# Benchmarks
```
$ cd benchmarks
$ go test -bench .
```
## Encode
## Decode
# Fuzzing
[go-json-fuzz](https://github.com/goccy/go-json-fuzz) is the repository for fuzzing tests.
If you run the test in this repository and find a bug, please commit to corpus to go-json-fuzz and report the issue to [go-json](https://github.com/goccy/go-json/issues).
# How it works
`go-json` is very fast in both encoding and decoding compared to other libraries.
It's easier to implement by using automatic code generation for performance or by using a dedicated interface, but `go-json` dares to stick to compatibility with `encoding/json` and is the simple interface. Despite this, we are developing with the aim of being the fastest library.
Here, we explain the various speed-up techniques implemented by `go-json`.
## Basic technique
The techniques listed here are the ones used by most of the libraries listed above.
### Buffer reuse
Since the only value required for the result of `json.Marshal(interface{}) ([]byte, error)` is `[]byte`, the only value that must be allocated during encoding is the return value `[]byte` .
Also, as the number of allocations increases, the performance will be affected, so the number of allocations should be kept as low as possible when creating `[]byte`.
Therefore, there is a technique to reduce the number of times a new buffer must be allocated by reusing the buffer used for the previous encoding by using `sync.Pool`.
Finally, you allocate a buffer that is as long as the resulting buffer and copy the contents into it, you only need to allocate the buffer once in theory.
```go
type buffer struct {
data []byte
}
var bufPool = sync.Pool{
New: func() interface{} {
return &buffer{data: make([]byte, 0, 1024)}
},
}
buf := bufPool.Get().(*buffer)
data := encode(buf.data) // reuse buf.data
newBuf := make([]byte, len(data))
copy(newBuf, buf)
buf.data = data
bufPool.Put(buf)
```
### Elimination of reflection
As you know, the reflection operation is very slow.
Therefore, using the fact that the address position where the type information is stored is fixed for each binary ( we call this `typeptr` ),
we can use the address in the type information to call a pre-built optimized process.
For example, you can get the address to the type information from `interface{}` as follows and you can use that information to call a process that does not have reflection.
To process without reflection, pass a pointer (`unsafe.Pointer`) to the value is stored.
```go
type emptyInterface struct {
typ unsafe.Pointer
ptr unsafe.Pointer
}
var typeToEncoder = map[uintptr]func(unsafe.Pointer)([]byte, error){}
func Marshal(v interface{}) ([]byte, error) {
iface := (*emptyInterface)(unsafe.Pointer(&v)
typeptr := uintptr(iface.typ)
if enc, exists := typeToEncoder[typeptr]; exists {
return enc(iface.ptr)
}
...
}
```
※ In reality, `typeToEncoder` can be referenced by multiple goroutines, so exclusive control is required.
## Unique speed-up technique
## Encoder
### Do not escape arguments of `Marshal`
`json.Marshal` and `json.Unmarshal` receive `interface{}` value and they perform type determination dynamically to process.
In normal case, you need to use the `reflect` library to determine the type dynamically, but since `reflect.Type` is defined as `interface`, when you call the method of `reflect.Type`, The reflect's argument is escaped.
Therefore, the arguments for `Marshal` and `Unmarshal` are always escape to the heap.
However, `go-json` can use the feature of `reflect.Type` while avoiding escaping.
`reflect.Type` is defined as `interface`, but in reality `reflect.Type` is implemented only by the structure `rtype` defined in the `reflect` package.
For this reason, to date `reflect.Type` is the same as `*reflect.rtype`.
Therefore, by directly handling `*reflect.rtype`, which is an implementation of `reflect.Type`, it is possible to avoid escaping because it changes from `interface` to using `struct`.
The technique for working with `*reflect.rtype` directly from `go-json` is implemented at [rtype.go](https://github.com/goccy/go-json/blob/master/internal/runtime/rtype.go)
Also, the same technique is cut out as a library ( https://github.com/goccy/go-reflect )
Initially this feature was the default behavior of `go-json`.
But after careful testing, I found that I passed a large value to `json.Marshal()` and if the argument could not be assigned to the stack, it could not be properly escaped to the heap (a bug in the Go compiler).
Therefore, this feature will be provided as an **optional** until this issue is resolved.
To use it, add `NoEscape` like `MarshalNoEscape()`
### Encoding using opcode sequence
I explained that you can use `typeptr` to call a pre-built process from type information.
In other libraries, this dedicated process is processed by making it an function calling like anonymous function, but function calls are inherently slow processes and should be avoided as much as possible.
Therefore, `go-json` adopted the Instruction-based execution processing system, which is also used to implement virtual machines for programming language.
If it is the first type to encode, create the opcode ( instruction ) sequence required for encoding.
From the second time onward, use `typeptr` to get the cached pre-built opcode sequence and encode it based on it. An example of the opcode sequence is shown below.
```go
json.Marshal(struct{
X int `json:"x"`
Y string `json:"y"`
}{X: 1, Y: "hello"})
```
When encoding a structure like the one above, create a sequence of opcodes like this:
```
- opStructFieldHead ( `{` )
- opStructFieldInt ( `"x": 1,` )
- opStructFieldString ( `"y": "hello"` )
- opStructEnd ( `}` )
- opEnd
```
※ When processing each operation, write the letters on the right.
In addition, each opcode is managed by the following structure (
Pseudo code ).
```go
type opType int
const (
opStructFieldHead opType = iota
opStructFieldInt
opStructFieldStirng
opStructEnd
opEnd
)
type opcode struct {
op opType
key []byte
next *opcode
}
```
The process of encoding using the opcode sequence is roughly implemented as follows.
```go
func encode(code *opcode, b []byte, p unsafe.Pointer) ([]byte, error) {
for {
switch code.op {
case opStructFieldHead:
b = append(b, '{')
code = code.next
case opStructFieldInt:
b = append(b, code.key...)
b = appendInt((*int)(unsafe.Pointer(uintptr(p)+code.offset)))
code = code.next
case opStructFieldString:
b = append(b, code.key...)
b = appendString((*string)(unsafe.Pointer(uintptr(p)+code.offset)))
code = code.next
case opStructEnd:
b = append(b, '}')
code = code.next
case opEnd:
goto END
}
}
END:
return b, nil
}
```
In this way, the huge `switch-case` is used to encode by manipulating the linked list opcodes to avoid unnecessary function calls.
### Opcode sequence optimization
One of the advantages of encoding using the opcode sequence is the ease of optimization.
The opcode sequence mentioned above is actually converted into the following optimized operations and used.
```
- opStructFieldHeadInt ( `{"x": 1,` )
- opStructEndString ( `"y": "hello"}` )
- opEnd
```
It has been reduced from 5 opcodes to 3 opcodes !
Reducing the number of opcodees means reducing the number of branches with `switch-case`.
In other words, the closer the number of operations is to 1, the faster the processing can be performed.
In `go-json`, optimization to reduce the number of opcodes itself like the above and it speeds up by preparing opcodes with optimized paths.
### Change recursive call from CALL to JMP
Recursive processing is required during encoding if the type is defined recursively as follows:
```go
type T struct {
X int
U *U
}
type U struct {
T *T
}
b, err := json.Marshal(&T{
X: 1,
U: &U{
T: &T{
X: 2,
},
},
})
fmt.Println(string(b)) // {"X":1,"U":{"T":{"X":2,"U":null}}}
```
In `go-json`, recursive processing is processed by the operation type of ` opStructFieldRecursive`.
In this operation, after acquiring the opcode sequence used for recursive processing, the function is **not** called recursively as it is, but the necessary values are saved by itself and implemented by moving to the next operation.
The technique of implementing recursive processing with the `JMP` operation while avoiding the `CALL` operation is a famous technique for implementing a high-speed virtual machine.
For more details, please refer to [the article](https://engineering.mercari.com/blog/entry/1599563768-081104c850) ( but Japanese only ).
### Dispatch by typeptr from map to slice
When retrieving the data cached from the type information by `typeptr`, we usually use map.
Map requires exclusive control, so use `sync.Map` for a naive implementation.
However, this is slow, so it's a good idea to use the `atomic` package for exclusive control as implemented by `segmentio/encoding/json` ( https://github.com/segmentio/encoding/blob/master/json/codec.go#L41-L55 ).
This implementation slows down the set instead of speeding up the get, but it works well because of the nature of the library, it encodes much more for the same type.
However, as a result of profiling, I noticed that `runtime.mapaccess2` accounts for a significant percentage of the execution time. So I thought if I could change the lookup from map to slice.
There is an API named `typelinks` defined in the `runtime` package that the `reflect` package uses internally.
This allows you to get all the type information defined in the binary at runtime.
The fact that all type information can be acquired means that by constructing slices in advance with the acquired total number of type information, it is possible to look up with the value of `typeptr` without worrying about out-of-range access.
However, if there is too much type information, it will use a lot of memory, so by default we will only use this optimization if the slice size fits within **2Mib** .
If this approach is not available, it will fall back to the `atomic` based process described above.
If you want to know more, please refer to the implementation [here](https://github.com/goccy/go-json/blob/master/internal/runtime/type.go#L36-L100)
## Decoder
### Dispatch by typeptr from map to slice
Like the encoder, the decoder also uses typeptr to call the dedicated process.
### Faster termination character inspection using NUL character
In order to decode, you have to traverse the input buffer character by position.
At that time, if you check whether the buffer has reached the end, it will be very slow.
`buf` : `[]byte` type variable. holds the string passed to the decoder
`cursor` : `int64` type variable. holds the current read position
```go
buflen := len(buf)
for ; cursor < buflen; cursor++ { // compare cursor and buflen at all times, it is so slow.
switch buf[cursor] {
case ' ', '\n', '\r', '\t':
}
}
```
Therefore, by adding the `NUL` (`\000`) character to the end of the read buffer as shown below, it is possible to check the termination character at the same time as other characters.
```go
for {
switch buf[cursor] {
case ' ', '\n', '\r', '\t':
case '\000':
return nil
}
cursor++
}
```
### Use Boundary Check Elimination
Due to the `NUL` character optimization, the Go compiler does a boundary check every time, even though `buf[cursor]` does not cause out-of-range access.
Therefore, `go-json` eliminates boundary check by fetching characters for hotspot by pointer operation. For example, the following code.
```go
func char(ptr unsafe.Pointer, offset int64) byte {
return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
}
p := (*sliceHeader)(&unsafe.Pointer(buf)).data
for {
switch char(p, cursor) {
case ' ', '\n', '\r', '\t':
case '\000':
return nil
}
cursor++
}
```
### Checking the existence of fields of struct using Bitmaps
I found by the profiling result, in the struct decode, lookup process for field was taking a long time.
For example, consider decoding a string like `{"a":1,"b":2,"c":3}` into the following structure:
```go
type T struct {
A int `json:"a"`
B int `json:"b"`
C int `json:"c"`
}
```
At this time, it was found that it takes a lot of time to acquire the decoding process corresponding to the field from the field name as shown below during the decoding process.
```go
fieldName := decodeKey(buf, cursor) // "a" or "b" or "c"
decoder, exists := fieldToDecoderMap[fieldName] // so slow
if exists {
decoder(buf, cursor)
} else {
skipValue(buf, cursor)
}
```
To improve this process, `json-iterator/go` is optimized so that it can be branched by switch-case when the number of fields in the structure is 10 or less (switch-case is faster than map). However, there is a risk of hash collision because the value hashed by the FNV algorithm is used for conditional branching. Also, `gojay` processes this part at high speed by letting the library user yourself write `switch-case`.
`go-json` considers and implements a new approach that is different from these. I call this **bitmap field optimization**.
The range of values per character can be represented by `[256]byte`. Also, if the number of fields in the structure is 8 or less, `int8` type can represent the state of each field.
In other words, it has the following structure.
- Base ( 8bit ): `00000000`
- Key "a": `00000001` ( assign key "a" to the first bit )
- Key "b": `00000010` ( assign key "b" to the second bit )
- Key "c": `00000100` ( assign key "c" to the third bit )
Bitmap structure is the following
```
| key index(0) |
------------------------
0 | 00000000 |
1 | 00000000 |
~~ | |
97 (a) | 00000001 |
98 (b) | 00000010 |
99 (c) | 00000100 |
~~ | |
255 | 00000000 |
```
You can think of this as a Bitmap with a height of `256` and a width of the maximum string length in the field name.
In other words, it can be represented by the following type .
```go
[maxFieldKeyLength][256]int8
```
When decoding a field character, check whether the corresponding character exists by referring to the pre-built bitmap like the following.
```go
var curBit int8 = math.MaxInt8 // 11111111
c := char(buf, cursor)
bit := bitmap[keyIdx][c]
curBit &= bit
if curBit == 0 {
// not found field
}
```
If `curBit` is not `0` until the end of the field string, then the string is
You may have hit one of the fields.
But the possibility is that if the decoded string is shorter than the field string, you will get a false hit.
- input: `{"a":1}`
```go
type T struct {
X int `json:"abc"`
}
```
※ Since `a` is shorter than `abc`, it can decode to the end of the field character without `curBit` being 0.
Rest assured. In this case, it doesn't matter because you can tell if you hit by comparing the string length of `a` with the string length of `abc`.
Finally, calculate the position of the bit where `1` is set and get the corresponding value, and you're done.
Using this technique, field lookups are possible with only bitwise operations and access to slices.
`go-json` uses a similar technique for fields with 9 or more and 16 or less fields. At this time, Bitmap is constructed as `[maxKeyLen][256]int16` type.
Currently, this optimization is not performed when the maximum length of the field name is long (specifically, 64 bytes or more) in addition to the limitation of the number of fields from the viewpoint of saving memory usage.
### Others
I have done a lot of other optimizations. I will find time to write about them. If you have any questions about what's written here or other optimizations, please visit the `#go-json` channel on `gophers.slack.com` .
## Reference
Regarding the story of go-json, there are the following articles in Japanese only.
- https://speakerdeck.com/goccy/zui-su-falsejsonraiburariwoqiu-mete
- https://engineering.mercari.com/blog/entry/1599563768-081104c850/
# Looking for Sponsors
I'm looking for sponsors this library. This library is being developed as a personal project in my spare time. If you want a quick response or problem resolution when using this library in your project, please register as a [sponsor](https://github.com/sponsors/goccy). I will cooperate as much as possible. Of course, this library is developed as an MIT license, so you can use it freely for free.
# License
MIT
================================================
FILE: vendor/github.com/goccy/go-json/color.go
================================================
package json
import (
"fmt"
"github.com/goccy/go-json/internal/encoder"
)
type (
ColorFormat = encoder.ColorFormat
ColorScheme = encoder.ColorScheme
)
const escape = "\x1b"
type colorAttr int
//nolint:deadcode,varcheck
const (
fgBlackColor colorAttr = iota + 30
fgRedColor
fgGreenColor
fgYellowColor
fgBlueColor
fgMagentaColor
fgCyanColor
fgWhiteColor
)
//nolint:deadcode,varcheck
const (
fgHiBlackColor colorAttr = iota + 90
fgHiRedColor
fgHiGreenColor
fgHiYellowColor
fgHiBlueColor
fgHiMagentaColor
fgHiCyanColor
fgHiWhiteColor
)
func createColorFormat(attr colorAttr) ColorFormat {
return ColorFormat{
Header: wrapColor(attr),
Footer: resetColor(),
}
}
func wrapColor(attr colorAttr) string {
return fmt.Sprintf("%s[%dm", escape, attr)
}
func resetColor() string {
return wrapColor(colorAttr(0))
}
var (
DefaultColorScheme = &ColorScheme{
Int: createColorFormat(fgHiMagentaColor),
Uint: createColorFormat(fgHiMagentaColor),
Float: createColorFormat(fgHiMagentaColor),
Bool: createColorFormat(fgHiYellowColor),
String: createColorFormat(fgHiGreenColor),
Binary: createColorFormat(fgHiRedColor),
ObjectKey: createColorFormat(fgHiCyanColor),
Null: createColorFormat(fgBlueColor),
}
)
================================================
FILE: vendor/github.com/goccy/go-json/decode.go
================================================
package json
import (
"context"
"fmt"
"io"
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/decoder"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type Decoder struct {
s *decoder.Stream
}
const (
nul = '\000'
)
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
func unmarshal(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
src := make([]byte, len(data)+1) // append nul byte to the end
copy(src, data)
header := (*emptyInterface)(unsafe.Pointer(&v))
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err
}
dec, err := decoder.CompileToGetDecoder(header.typ)
if err != nil {
return err
}
ctx := decoder.TakeRuntimeContext()
ctx.Buf = src
ctx.Option.Flags = 0
for _, optFunc := range optFuncs {
optFunc(ctx.Option)
}
cursor, err := dec.Decode(ctx, 0, 0, header.ptr)
if err != nil {
decoder.ReleaseRuntimeContext(ctx)
return err
}
decoder.ReleaseRuntimeContext(ctx)
return validateEndBuf(src, cursor)
}
func unmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
src := make([]byte, len(data)+1) // append nul byte to the end
copy(src, data)
header := (*emptyInterface)(unsafe.Pointer(&v))
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err
}
dec, err := decoder.CompileToGetDecoder(header.typ)
if err != nil {
return err
}
rctx := decoder.TakeRuntimeContext()
rctx.Buf = src
rctx.Option.Flags = 0
rctx.Option.Flags |= decoder.ContextOption
rctx.Option.Context = ctx
for _, optFunc := range optFuncs {
optFunc(rctx.Option)
}
cursor, err := dec.Decode(rctx, 0, 0, header.ptr)
if err != nil {
decoder.ReleaseRuntimeContext(rctx)
return err
}
decoder.ReleaseRuntimeContext(rctx)
return validateEndBuf(src, cursor)
}
func unmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
src := make([]byte, len(data)+1) // append nul byte to the end
copy(src, data)
header := (*emptyInterface)(unsafe.Pointer(&v))
if err := validateType(header.typ, uintptr(header.ptr)); err != nil {
return err
}
dec, err := decoder.CompileToGetDecoder(header.typ)
if err != nil {
return err
}
ctx := decoder.TakeRuntimeContext()
ctx.Buf = src
ctx.Option.Flags = 0
for _, optFunc := range optFuncs {
optFunc(ctx.Option)
}
cursor, err := dec.Decode(ctx, 0, 0, noescape(header.ptr))
if err != nil {
decoder.ReleaseRuntimeContext(ctx)
return err
}
decoder.ReleaseRuntimeContext(ctx)
return validateEndBuf(src, cursor)
}
func validateEndBuf(src []byte, cursor int64) error {
for {
switch src[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case nul:
return nil
}
return errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
cursor+1,
)
}
}
//nolint:staticcheck
//go:nosplit
func noescape(p unsafe.Pointer) unsafe.Pointer {
x := uintptr(p)
return unsafe.Pointer(x ^ 0)
}
func validateType(typ *runtime.Type, p uintptr) error {
if typ == nil || typ.Kind() != reflect.Ptr || p == 0 {
return &InvalidUnmarshalError{Type: runtime.RType2Type(typ)}
}
return nil
}
// NewDecoder returns a new decoder that reads from r.
//
// The decoder introduces its own buffering and may
// read data from r beyond the JSON values requested.
func NewDecoder(r io.Reader) *Decoder {
s := decoder.NewStream(r)
return &Decoder{
s: s,
}
}
// Buffered returns a reader of the data remaining in the Decoder's
// buffer. The reader is valid until the next call to Decode.
func (d *Decoder) Buffered() io.Reader {
return d.s.Buffered()
}
// Decode reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v.
//
// See the documentation for Unmarshal for details about
// the conversion of JSON into a Go value.
func (d *Decoder) Decode(v interface{}) error {
return d.DecodeWithOption(v)
}
// DecodeContext reads the next JSON-encoded value from its
// input and stores it in the value pointed to by v with context.Context.
func (d *Decoder) DecodeContext(ctx context.Context, v interface{}) error {
d.s.Option.Flags |= decoder.ContextOption
d.s.Option.Context = ctx
return d.DecodeWithOption(v)
}
func (d *Decoder) DecodeWithOption(v interface{}, optFuncs ...DecodeOptionFunc) error {
header := (*emptyInterface)(unsafe.Pointer(&v))
typ := header.typ
ptr := uintptr(header.ptr)
typeptr := uintptr(unsafe.Pointer(typ))
// noescape trick for header.typ ( reflect.*rtype )
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
if err := validateType(copiedType, ptr); err != nil {
return err
}
dec, err := decoder.CompileToGetDecoder(typ)
if err != nil {
return err
}
if err := d.s.PrepareForDecode(); err != nil {
return err
}
s := d.s
for _, optFunc := range optFuncs {
optFunc(s.Option)
}
if err := dec.DecodeStream(s, 0, header.ptr); err != nil {
return err
}
s.Reset()
return nil
}
func (d *Decoder) More() bool {
return d.s.More()
}
func (d *Decoder) Token() (Token, error) {
return d.s.Token()
}
// DisallowUnknownFields causes the Decoder to return an error when the destination
// is a struct and the input contains object keys which do not match any
// non-ignored, exported fields in the destination.
func (d *Decoder) DisallowUnknownFields() {
d.s.DisallowUnknownFields = true
}
func (d *Decoder) InputOffset() int64 {
return d.s.TotalOffset()
}
// UseNumber causes the Decoder to unmarshal a number into an interface{} as a
// Number instead of as a float64.
func (d *Decoder) UseNumber() {
d.s.UseNumber = true
}
================================================
FILE: vendor/github.com/goccy/go-json/docker-compose.yml
================================================
version: '2'
services:
go-json:
image: golang:1.18
volumes:
- '.:/go/src/go-json'
deploy:
resources:
limits:
memory: 620M
working_dir: /go/src/go-json
command: |
sh -c "go test -c . && ls go-json.test"
================================================
FILE: vendor/github.com/goccy/go-json/encode.go
================================================
package json
import (
"context"
"io"
"os"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/encoder/vm"
"github.com/goccy/go-json/internal/encoder/vm_color"
"github.com/goccy/go-json/internal/encoder/vm_color_indent"
"github.com/goccy/go-json/internal/encoder/vm_indent"
)
// An Encoder writes JSON values to an output stream.
type Encoder struct {
w io.Writer
enabledIndent bool
enabledHTMLEscape bool
prefix string
indentStr string
}
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w: w, enabledHTMLEscape: true}
}
// Encode writes the JSON encoding of v to the stream, followed by a newline character.
//
// See the documentation for Marshal for details about the conversion of Go values to JSON.
func (e *Encoder) Encode(v interface{}) error {
return e.EncodeWithOption(v)
}
// EncodeWithOption call Encode with EncodeOption.
func (e *Encoder) EncodeWithOption(v interface{}, optFuncs ...EncodeOptionFunc) error {
ctx := encoder.TakeRuntimeContext()
ctx.Option.Flag = 0
err := e.encodeWithOption(ctx, v, optFuncs...)
encoder.ReleaseRuntimeContext(ctx)
return err
}
// EncodeContext call Encode with context.Context and EncodeOption.
func (e *Encoder) EncodeContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) error {
rctx := encoder.TakeRuntimeContext()
rctx.Option.Flag = 0
rctx.Option.Flag |= encoder.ContextOption
rctx.Option.Context = ctx
err := e.encodeWithOption(rctx, v, optFuncs...)
encoder.ReleaseRuntimeContext(rctx)
return err
}
func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, optFuncs ...EncodeOptionFunc) error {
if e.enabledHTMLEscape {
ctx.Option.Flag |= encoder.HTMLEscapeOption
}
ctx.Option.Flag |= encoder.NormalizeUTF8Option
ctx.Option.DebugOut = os.Stdout
for _, optFunc := range optFuncs {
optFunc(ctx.Option)
}
var (
buf []byte
err error
)
if e.enabledIndent {
buf, err = encodeIndent(ctx, v, e.prefix, e.indentStr)
} else {
buf, err = encode(ctx, v)
}
if err != nil {
return err
}
if e.enabledIndent {
buf = buf[:len(buf)-2]
} else {
buf = buf[:len(buf)-1]
}
buf = append(buf, '\n')
if _, err := e.w.Write(buf); err != nil {
return err
}
return nil
}
// SetEscapeHTML specifies whether problematic HTML characters should be escaped inside JSON quoted strings.
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e to avoid certain safety problems that can arise when embedding JSON in HTML.
//
// In non-HTML settings where the escaping interferes with the readability of the output, SetEscapeHTML(false) disables this behavior.
func (e *Encoder) SetEscapeHTML(on bool) {
e.enabledHTMLEscape = on
}
// SetIndent instructs the encoder to format each subsequent encoded value as if indented by the package-level function Indent(dst, src, prefix, indent).
// Calling SetIndent("", "") disables indentation.
func (e *Encoder) SetIndent(prefix, indent string) {
if prefix == "" && indent == "" {
e.enabledIndent = false
return
}
e.prefix = prefix
e.indentStr = indent
e.enabledIndent = true
}
func marshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
rctx := encoder.TakeRuntimeContext()
rctx.Option.Flag = 0
rctx.Option.Flag = encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.ContextOption
rctx.Option.Context = ctx
for _, optFunc := range optFuncs {
optFunc(rctx.Option)
}
buf, err := encode(rctx, v)
if err != nil {
encoder.ReleaseRuntimeContext(rctx)
return nil, err
}
// this line exists to escape call of `runtime.makeslicecopy` .
// if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`,
// dst buffer size and src buffer size are differrent.
// in this case, compiler uses `runtime.makeslicecopy`, but it is slow.
buf = buf[:len(buf)-1]
copied := make([]byte, len(buf))
copy(copied, buf)
encoder.ReleaseRuntimeContext(rctx)
return copied, nil
}
func marshal(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
ctx := encoder.TakeRuntimeContext()
ctx.Option.Flag = 0
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option)
for _, optFunc := range optFuncs {
optFunc(ctx.Option)
}
buf, err := encode(ctx, v)
if err != nil {
encoder.ReleaseRuntimeContext(ctx)
return nil, err
}
// this line exists to escape call of `runtime.makeslicecopy` .
// if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`,
// dst buffer size and src buffer size are differrent.
// in this case, compiler uses `runtime.makeslicecopy`, but it is slow.
buf = buf[:len(buf)-1]
copied := make([]byte, len(buf))
copy(copied, buf)
encoder.ReleaseRuntimeContext(ctx)
return copied, nil
}
func marshalNoEscape(v interface{}) ([]byte, error) {
ctx := encoder.TakeRuntimeContext()
ctx.Option.Flag = 0
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option)
buf, err := encodeNoEscape(ctx, v)
if err != nil {
encoder.ReleaseRuntimeContext(ctx)
return nil, err
}
// this line exists to escape call of `runtime.makeslicecopy` .
// if use `make([]byte, len(buf)-1)` and `copy(copied, buf)`,
// dst buffer size and src buffer size are differrent.
// in this case, compiler uses `runtime.makeslicecopy`, but it is slow.
buf = buf[:len(buf)-1]
copied := make([]byte, len(buf))
copy(copied, buf)
encoder.ReleaseRuntimeContext(ctx)
return copied, nil
}
func marshalIndent(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
ctx := encoder.TakeRuntimeContext()
ctx.Option.Flag = 0
ctx.Option.Flag |= (encoder.HTMLEscapeOption | encoder.NormalizeUTF8Option | encoder.IndentOption)
for _, optFunc := range optFuncs {
optFunc(ctx.Option)
}
buf, err := encodeIndent(ctx, v, prefix, indent)
if err != nil {
encoder.ReleaseRuntimeContext(ctx)
return nil, err
}
buf = buf[:len(buf)-2]
copied := make([]byte, len(buf))
copy(copied, buf)
encoder.ReleaseRuntimeContext(ctx)
return copied, nil
}
func encode(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
b := ctx.Buf[:0]
if v == nil {
b = encoder.AppendNull(ctx, b)
b = encoder.AppendComma(ctx, b)
return b, nil
}
header := (*emptyInterface)(unsafe.Pointer(&v))
typ := header.typ
typeptr := uintptr(unsafe.Pointer(typ))
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
if err != nil {
return nil, err
}
p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength)
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
buf, err := encodeRunCode(ctx, b, codeSet)
if err != nil {
return nil, err
}
ctx.Buf = buf
return buf, nil
}
func encodeNoEscape(ctx *encoder.RuntimeContext, v interface{}) ([]byte, error) {
b := ctx.Buf[:0]
if v == nil {
b = encoder.AppendNull(ctx, b)
b = encoder.AppendComma(ctx, b)
return b, nil
}
header := (*emptyInterface)(unsafe.Pointer(&v))
typ := header.typ
typeptr := uintptr(unsafe.Pointer(typ))
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
if err != nil {
return nil, err
}
p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength)
buf, err := encodeRunCode(ctx, b, codeSet)
if err != nil {
return nil, err
}
ctx.Buf = buf
return buf, nil
}
func encodeIndent(ctx *encoder.RuntimeContext, v interface{}, prefix, indent string) ([]byte, error) {
b := ctx.Buf[:0]
if v == nil {
b = encoder.AppendNull(ctx, b)
b = encoder.AppendCommaIndent(ctx, b)
return b, nil
}
header := (*emptyInterface)(unsafe.Pointer(&v))
typ := header.typ
typeptr := uintptr(unsafe.Pointer(typ))
codeSet, err := encoder.CompileToGetCodeSet(ctx, typeptr)
if err != nil {
return nil, err
}
p := uintptr(header.ptr)
ctx.Init(p, codeSet.CodeLength)
buf, err := encodeRunIndentCode(ctx, b, codeSet, prefix, indent)
ctx.KeepRefs = append(ctx.KeepRefs, header.ptr)
if err != nil {
return nil, err
}
ctx.Buf = buf
return buf, nil
}
func encodeRunCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
if (ctx.Option.Flag & encoder.DebugOption) != 0 {
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
return vm_color.DebugRun(ctx, b, codeSet)
}
return vm.DebugRun(ctx, b, codeSet)
}
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
return vm_color.Run(ctx, b, codeSet)
}
return vm.Run(ctx, b, codeSet)
}
func encodeRunIndentCode(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, prefix, indent string) ([]byte, error) {
ctx.Prefix = []byte(prefix)
ctx.IndentStr = []byte(indent)
if (ctx.Option.Flag & encoder.DebugOption) != 0 {
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
return vm_color_indent.DebugRun(ctx, b, codeSet)
}
return vm_indent.DebugRun(ctx, b, codeSet)
}
if (ctx.Option.Flag & encoder.ColorizeOption) != 0 {
return vm_color_indent.Run(ctx, b, codeSet)
}
return vm_indent.Run(ctx, b, codeSet)
}
================================================
FILE: vendor/github.com/goccy/go-json/error.go
================================================
package json
import (
"github.com/goccy/go-json/internal/errors"
)
// Before Go 1.2, an InvalidUTF8Error was returned by Marshal when
// attempting to encode a string value with invalid UTF-8 sequences.
// As of Go 1.2, Marshal instead coerces the string to valid UTF-8 by
// replacing invalid bytes with the Unicode replacement rune U+FFFD.
//
// Deprecated: No longer used; kept for compatibility.
type InvalidUTF8Error = errors.InvalidUTF8Error
// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal.
// (The argument to Unmarshal must be a non-nil pointer.)
type InvalidUnmarshalError = errors.InvalidUnmarshalError
// A MarshalerError represents an error from calling a MarshalJSON or MarshalText method.
type MarshalerError = errors.MarshalerError
// A SyntaxError is a description of a JSON syntax error.
type SyntaxError = errors.SyntaxError
// An UnmarshalFieldError describes a JSON object key that
// led to an unexported (and therefore unwritable) struct field.
//
// Deprecated: No longer used; kept for compatibility.
type UnmarshalFieldError = errors.UnmarshalFieldError
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError = errors.UnmarshalTypeError
// An UnsupportedTypeError is returned by Marshal when attempting
// to encode an unsupported value type.
type UnsupportedTypeError = errors.UnsupportedTypeError
type UnsupportedValueError = errors.UnsupportedValueError
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/anonymous_field.go
================================================
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type anonymousFieldDecoder struct {
structType *runtime.Type
offset uintptr
dec Decoder
}
func newAnonymousFieldDecoder(structType *runtime.Type, offset uintptr, dec Decoder) *anonymousFieldDecoder {
return &anonymousFieldDecoder{
structType: structType,
offset: offset,
dec: dec,
}
}
func (d *anonymousFieldDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
}
p = *(*unsafe.Pointer)(p)
return d.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+d.offset))
}
func (d *anonymousFieldDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
if *(*unsafe.Pointer)(p) == nil {
*(*unsafe.Pointer)(p) = unsafe_New(d.structType)
}
p = *(*unsafe.Pointer)(p)
return d.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+d.offset))
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/array.go
================================================
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type arrayDecoder struct {
elemType *runtime.Type
size uintptr
valueDecoder Decoder
alen int
structName string
fieldName string
zeroValue unsafe.Pointer
}
func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
return &arrayDecoder{
valueDecoder: dec,
elemType: elemType,
size: elemType.Size(),
alen: alen,
structName: structName,
fieldName: fieldName,
zeroValue: zeroValue,
}
}
func (d *arrayDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
case 'n':
if err := nullBytes(s); err != nil {
return err
}
return nil
case '[':
idx := 0
s.cursor++
if s.skipWhiteSpace() == ']' {
for idx < d.alen {
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
idx++
}
s.cursor++
return nil
}
for {
if idx < d.alen {
if err := d.valueDecoder.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size)); err != nil {
return err
}
} else {
if err := s.skipValue(depth); err != nil {
return err
}
}
idx++
switch s.skipWhiteSpace() {
case ']':
for idx < d.alen {
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
idx++
}
s.cursor++
return nil
case ',':
s.cursor++
continue
case nul:
if s.read() {
s.cursor++
continue
}
goto ERROR
default:
goto ERROR
}
}
case nul:
if s.read() {
continue
}
goto ERROR
default:
goto ERROR
}
s.cursor++
}
ERROR:
return errors.ErrUnexpectedEndOfJSON("array", s.totalOffset())
}
func (d *arrayDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
continue
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
return cursor, nil
case '[':
idx := 0
cursor++
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == ']' {
for idx < d.alen {
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
idx++
}
cursor++
return cursor, nil
}
for {
if idx < d.alen {
c, err := d.valueDecoder.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+uintptr(idx)*d.size))
if err != nil {
return 0, err
}
cursor = c
} else {
c, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
cursor = c
}
idx++
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case ']':
for idx < d.alen {
*(*unsafe.Pointer)(unsafe.Pointer(uintptr(p) + uintptr(idx)*d.size)) = d.zeroValue
idx++
}
cursor++
return cursor, nil
case ',':
cursor++
continue
default:
return 0, errors.ErrInvalidCharacter(buf[cursor], "array", cursor)
}
}
default:
return 0, errors.ErrUnexpectedEndOfJSON("array", cursor)
}
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/bool.go
================================================
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type boolDecoder struct {
structName string
fieldName string
}
func newBoolDecoder(structName, fieldName string) *boolDecoder {
return &boolDecoder{structName: structName, fieldName: fieldName}
}
func (d *boolDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
c := s.skipWhiteSpace()
for {
switch c {
case 't':
if err := trueBytes(s); err != nil {
return err
}
**(**bool)(unsafe.Pointer(&p)) = true
return nil
case 'f':
if err := falseBytes(s); err != nil {
return err
}
**(**bool)(unsafe.Pointer(&p)) = false
return nil
case 'n':
if err := nullBytes(s); err != nil {
return err
}
return nil
case nul:
if s.read() {
c = s.char()
continue
}
goto ERROR
}
break
}
ERROR:
return errors.ErrUnexpectedEndOfJSON("bool", s.totalOffset())
}
func (d *boolDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case 't':
if err := validateTrue(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**bool)(unsafe.Pointer(&p)) = true
return cursor, nil
case 'f':
if err := validateFalse(buf, cursor); err != nil {
return 0, err
}
cursor += 5
**(**bool)(unsafe.Pointer(&p)) = false
return cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
return cursor, nil
}
return 0, errors.ErrUnexpectedEndOfJSON("bool", cursor)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/bytes.go
================================================
package decoder
import (
"encoding/base64"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type bytesDecoder struct {
typ *runtime.Type
sliceDecoder Decoder
stringDecoder *stringDecoder
structName string
fieldName string
}
func byteUnmarshalerSliceDecoder(typ *runtime.Type, structName string, fieldName string) Decoder {
var unmarshalDecoder Decoder
switch {
case runtime.PtrTo(typ).Implements(unmarshalJSONType):
unmarshalDecoder = newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName)
case runtime.PtrTo(typ).Implements(unmarshalTextType):
unmarshalDecoder = newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName)
default:
unmarshalDecoder, _ = compileUint8(typ, structName, fieldName)
}
return newSliceDecoder(unmarshalDecoder, typ, 1, structName, fieldName)
}
func newBytesDecoder(typ *runtime.Type, structName string, fieldName string) *bytesDecoder {
return &bytesDecoder{
typ: typ,
sliceDecoder: byteUnmarshalerSliceDecoder(typ, structName, fieldName),
stringDecoder: newStringDecoder(structName, fieldName),
structName: structName,
fieldName: fieldName,
}
}
func (d *bytesDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamBinary(s, depth, p)
if err != nil {
return err
}
if bytes == nil {
s.reset()
return nil
}
decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
buf := make([]byte, decodedLen)
n, err := base64.StdEncoding.Decode(buf, bytes)
if err != nil {
return err
}
*(*[]byte)(p) = buf[:n]
s.reset()
return nil
}
func (d *bytesDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeBinary(ctx, cursor, depth, p)
if err != nil {
return 0, err
}
if bytes == nil {
return c, nil
}
cursor = c
decodedLen := base64.StdEncoding.DecodedLen(len(bytes))
b := make([]byte, decodedLen)
n, err := base64.StdEncoding.Decode(b, bytes)
if err != nil {
return 0, err
}
*(*[]byte)(p) = b[:n]
return cursor, nil
}
func (d *bytesDecoder) decodeStreamBinary(s *Stream, depth int64, p unsafe.Pointer) ([]byte, error) {
c := s.skipWhiteSpace()
if c == '[' {
if d.sliceDecoder == nil {
return nil, &errors.UnmarshalTypeError{
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
}
err := d.sliceDecoder.DecodeStream(s, depth, p)
return nil, err
}
return d.stringDecoder.decodeStreamByte(s)
}
func (d *bytesDecoder) decodeBinary(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) ([]byte, int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == '[' {
if d.sliceDecoder == nil {
return nil, 0, &errors.UnmarshalTypeError{
Type: runtime.RType2Type(d.typ),
Offset: cursor,
}
}
c, err := d.sliceDecoder.Decode(ctx, cursor, depth, p)
if err != nil {
return nil, 0, err
}
return nil, c, nil
}
return d.stringDecoder.decodeByte(buf, cursor)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/compile.go
================================================
package decoder
import (
"encoding/json"
"fmt"
"reflect"
"strings"
"sync/atomic"
"unicode"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
var (
jsonNumberType = reflect.TypeOf(json.Number(""))
typeAddr *runtime.TypeAddr
cachedDecoderMap unsafe.Pointer // map[uintptr]decoder
cachedDecoder []Decoder
)
func init() {
typeAddr = runtime.AnalyzeTypeAddr()
if typeAddr == nil {
typeAddr = &runtime.TypeAddr{}
}
cachedDecoder = make([]Decoder, typeAddr.AddrRange>>typeAddr.AddrShift+1)
}
func loadDecoderMap() map[uintptr]Decoder {
p := atomic.LoadPointer(&cachedDecoderMap)
return *(*map[uintptr]Decoder)(unsafe.Pointer(&p))
}
func storeDecoder(typ uintptr, dec Decoder, m map[uintptr]Decoder) {
newDecoderMap := make(map[uintptr]Decoder, len(m)+1)
newDecoderMap[typ] = dec
for k, v := range m {
newDecoderMap[k] = v
}
atomic.StorePointer(&cachedDecoderMap, *(*unsafe.Pointer)(unsafe.Pointer(&newDecoderMap)))
}
func compileToGetDecoderSlowPath(typeptr uintptr, typ *runtime.Type) (Decoder, error) {
decoderMap := loadDecoderMap()
if dec, exists := decoderMap[typeptr]; exists {
return dec, nil
}
dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil {
return nil, err
}
storeDecoder(typeptr, dec, decoderMap)
return dec, nil
}
func compileHead(typ *runtime.Type, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
switch {
case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), "", ""), nil
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(runtime.PtrTo(typ), "", ""), nil
}
return compile(typ.Elem(), "", "", structTypeToDecoder)
}
func compile(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
switch {
case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
return newUnmarshalJSONDecoder(runtime.PtrTo(typ), structName, fieldName), nil
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
}
switch typ.Kind() {
case reflect.Ptr:
return compilePtr(typ, structName, fieldName, structTypeToDecoder)
case reflect.Struct:
return compileStruct(typ, structName, fieldName, structTypeToDecoder)
case reflect.Slice:
elem := typ.Elem()
if elem.Kind() == reflect.Uint8 {
return compileBytes(elem, structName, fieldName)
}
return compileSlice(typ, structName, fieldName, structTypeToDecoder)
case reflect.Array:
return compileArray(typ, structName, fieldName, structTypeToDecoder)
case reflect.Map:
return compileMap(typ, structName, fieldName, structTypeToDecoder)
case reflect.Interface:
return compileInterface(typ, structName, fieldName)
case reflect.Uintptr:
return compileUint(typ, structName, fieldName)
case reflect.Int:
return compileInt(typ, structName, fieldName)
case reflect.Int8:
return compileInt8(typ, structName, fieldName)
case reflect.Int16:
return compileInt16(typ, structName, fieldName)
case reflect.Int32:
return compileInt32(typ, structName, fieldName)
case reflect.Int64:
return compileInt64(typ, structName, fieldName)
case reflect.Uint:
return compileUint(typ, structName, fieldName)
case reflect.Uint8:
return compileUint8(typ, structName, fieldName)
case reflect.Uint16:
return compileUint16(typ, structName, fieldName)
case reflect.Uint32:
return compileUint32(typ, structName, fieldName)
case reflect.Uint64:
return compileUint64(typ, structName, fieldName)
case reflect.String:
return compileString(typ, structName, fieldName)
case reflect.Bool:
return compileBool(structName, fieldName)
case reflect.Float32:
return compileFloat32(structName, fieldName)
case reflect.Float64:
return compileFloat64(structName, fieldName)
case reflect.Func:
return compileFunc(typ, structName, fieldName)
}
return newInvalidDecoder(typ, structName, fieldName), nil
}
func isStringTagSupportedType(typ *runtime.Type) bool {
switch {
case implementsUnmarshalJSONType(runtime.PtrTo(typ)):
return false
case runtime.PtrTo(typ).Implements(unmarshalTextType):
return false
}
switch typ.Kind() {
case reflect.Map:
return false
case reflect.Slice:
return false
case reflect.Array:
return false
case reflect.Struct:
return false
case reflect.Interface:
return false
}
return true
}
func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
if runtime.PtrTo(typ).Implements(unmarshalTextType) {
return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
}
if typ.Kind() == reflect.String {
return newStringDecoder(structName, fieldName), nil
}
dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
for {
switch t := dec.(type) {
case *stringDecoder, *interfaceDecoder:
return dec, nil
case *boolDecoder, *intDecoder, *uintDecoder, *numberDecoder:
return newWrappedStringDecoder(typ, dec, structName, fieldName), nil
case *ptrDecoder:
dec = t.dec
default:
return newInvalidDecoder(typ, structName, fieldName), nil
}
}
}
func compilePtr(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
dec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil
}
func compileInt(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int)(p) = int(v)
}), nil
}
func compileInt8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int8)(p) = int8(v)
}), nil
}
func compileInt16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int16)(p) = int16(v)
}), nil
}
func compileInt32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int32)(p) = int32(v)
}), nil
}
func compileInt64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newIntDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v int64) {
*(*int64)(p) = v
}), nil
}
func compileUint(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint)(p) = uint(v)
}), nil
}
func compileUint8(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint8)(p) = uint8(v)
}), nil
}
func compileUint16(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint16)(p) = uint16(v)
}), nil
}
func compileUint32(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint32)(p) = uint32(v)
}), nil
}
func compileUint64(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newUintDecoder(typ, structName, fieldName, func(p unsafe.Pointer, v uint64) {
*(*uint64)(p) = v
}), nil
}
func compileFloat32(structName, fieldName string) (Decoder, error) {
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*float32)(p) = float32(v)
}), nil
}
func compileFloat64(structName, fieldName string) (Decoder, error) {
return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*float64)(p) = v
}), nil
}
func compileString(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
if typ == runtime.Type2RType(jsonNumberType) {
return newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*json.Number)(p) = v
}), nil
}
return newStringDecoder(structName, fieldName), nil
}
func compileBool(structName, fieldName string) (Decoder, error) {
return newBoolDecoder(structName, fieldName), nil
}
func compileBytes(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newBytesDecoder(typ, structName, fieldName), nil
}
func compileSlice(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
elem := typ.Elem()
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil
}
func compileArray(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
elem := typ.Elem()
decoder, err := compile(elem, structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil
}
func compileMap(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
keyDec, err := compileMapKey(typ.Key(), structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
valueDec, err := compile(typ.Elem(), structName, fieldName, structTypeToDecoder)
if err != nil {
return nil, err
}
return newMapDecoder(typ, typ.Key(), keyDec, typ.Elem(), valueDec, structName, fieldName), nil
}
func compileInterface(typ *runtime.Type, structName, fieldName string) (Decoder, error) {
return newInterfaceDecoder(typ, structName, fieldName), nil
}
func compileFunc(typ *runtime.Type, strutName, fieldName string) (Decoder, error) {
return newFuncDecoder(typ, strutName, fieldName), nil
}
func typeToStructTags(typ *runtime.Type) runtime.StructTags {
tags := runtime.StructTags{}
fieldNum := typ.NumField()
for i := 0; i < fieldNum; i++ {
field := typ.Field(i)
if runtime.IsIgnoredStructField(field) {
continue
}
tags = append(tags, runtime.StructTagFromField(field))
}
return tags
}
func compileStruct(typ *runtime.Type, structName, fieldName string, structTypeToDecoder map[uintptr]Decoder) (Decoder, error) {
fieldNum := typ.NumField()
fieldMap := map[string]*structFieldSet{}
typeptr := uintptr(unsafe.Pointer(typ))
if dec, exists := structTypeToDecoder[typeptr]; exists {
return dec, nil
}
structDec := newStructDecoder(structName, fieldName, fieldMap)
structTypeToDecoder[typeptr] = structDec
structName = typ.Name()
tags := typeToStructTags(typ)
allFields := []*structFieldSet{}
for i := 0; i < fieldNum; i++ {
field := typ.Field(i)
if runtime.IsIgnoredStructField(field) {
continue
}
isUnexportedField := unicode.IsLower([]rune(field.Name)[0])
tag := runtime.StructTagFromField(field)
dec, err := compile(runtime.Type2RType(field.Type), structName, field.Name, structTypeToDecoder)
if err != nil {
return nil, err
}
if field.Anonymous && !tag.IsTaggedKey {
if stDec, ok := dec.(*structDecoder); ok {
if runtime.Type2RType(field.Type) == typ {
// recursive definition
continue
}
for k, v := range stDec.fieldMap {
if tags.ExistsKey(k) {
continue
}
fieldSet := &structFieldSet{
dec: v.dec,
offset: field.Offset + v.offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
}
allFields = append(allFields, fieldSet)
}
} else if pdec, ok := dec.(*ptrDecoder); ok {
contentDec := pdec.contentDecoder()
if pdec.typ == typ {
// recursive definition
continue
}
var fieldSetErr error
if isUnexportedField {
fieldSetErr = fmt.Errorf(
"json: cannot set embedded pointer to unexported struct: %v",
field.Type.Elem(),
)
}
if dec, ok := contentDec.(*structDecoder); ok {
for k, v := range dec.fieldMap {
if tags.ExistsKey(k) {
continue
}
fieldSet := &structFieldSet{
dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec),
offset: field.Offset,
isTaggedKey: v.isTaggedKey,
key: k,
keyLen: int64(len(k)),
err: fieldSetErr,
}
allFields = append(allFields, fieldSet)
}
} else {
fieldSet := &structFieldSet{
dec: pdec,
offset: field.Offset,
isTaggedKey: tag.IsTaggedKey,
key: field.Name,
keyLen: int64(len(field.Name)),
}
allFields = append(allFields, fieldSet)
}
} else {
fieldSet := &structFieldSet{
dec: dec,
offset: field.Offset,
isTaggedKey: tag.IsTaggedKey,
key: field.Name,
keyLen: int64(len(field.Name)),
}
allFields = append(allFields, fieldSet)
}
} else {
if tag.IsString && isStringTagSupportedType(runtime.Type2RType(field.Type)) {
dec = newWrappedStringDecoder(runtime.Type2RType(field.Type), dec, structName, field.Name)
}
var key string
if tag.Key != "" {
key = tag.Key
} else {
key = field.Name
}
fieldSet := &structFieldSet{
dec: dec,
offset: field.Offset,
isTaggedKey: tag.IsTaggedKey,
key: key,
keyLen: int64(len(key)),
}
allFields = append(allFields, fieldSet)
}
}
for _, set := range filterDuplicatedFields(allFields) {
fieldMap[set.key] = set
lower := strings.ToLower(set.key)
if _, exists := fieldMap[lower]; !exists {
// first win
fieldMap[lower] = set
}
}
delete(structTypeToDecoder, typeptr)
structDec.tryOptimize()
return structDec, nil
}
func filterDuplicatedFields(allFields []*structFieldSet) []*structFieldSet {
fieldMap := map[string][]*structFieldSet{}
for _, field := range allFields {
fieldMap[field.key] = append(fieldMap[field.key], field)
}
duplicatedFieldMap := map[string]struct{}{}
for k, sets := range fieldMap {
sets = filterFieldSets(sets)
if len(sets) != 1 {
duplicatedFieldMap[k] = struct{}{}
}
}
filtered := make([]*structFieldSet, 0, len(allFields))
for _, field := range allFields {
if _, exists := duplicatedFieldMap[field.key]; exists {
continue
}
filtered = append(filtered, field)
}
return filtered
}
func filterFieldSets(sets []*structFieldSet) []*structFieldSet {
if len(sets) == 1 {
return sets
}
filtered := make([]*structFieldSet, 0, len(sets))
for _, set := range sets {
if set.isTaggedKey {
filtered = append(filtered, set)
}
}
return filtered
}
func implementsUnmarshalJSONType(typ *runtime.Type) bool {
return typ.Implements(unmarshalJSONType) || typ.Implements(unmarshalJSONContextType)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/compile_norace.go
================================================
//go:build !race
// +build !race
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > typeAddr.MaxTypeAddr {
return compileToGetDecoderSlowPath(typeptr, typ)
}
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
if dec := cachedDecoder[index]; dec != nil {
return dec, nil
}
dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil {
return nil, err
}
cachedDecoder[index] = dec
return dec, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/compile_race.go
================================================
//go:build race
// +build race
package decoder
import (
"sync"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
var decMu sync.RWMutex
func CompileToGetDecoder(typ *runtime.Type) (Decoder, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if typeptr > typeAddr.MaxTypeAddr {
return compileToGetDecoderSlowPath(typeptr, typ)
}
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
decMu.RLock()
if dec := cachedDecoder[index]; dec != nil {
decMu.RUnlock()
return dec, nil
}
decMu.RUnlock()
dec, err := compileHead(typ, map[uintptr]Decoder{})
if err != nil {
return nil, err
}
decMu.Lock()
cachedDecoder[index] = dec
decMu.Unlock()
return dec, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/context.go
================================================
package decoder
import (
"sync"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type RuntimeContext struct {
Buf []byte
Option *Option
}
var (
runtimeContextPool = sync.Pool{
New: func() interface{} {
return &RuntimeContext{
Option: &Option{},
}
},
}
)
func TakeRuntimeContext() *RuntimeContext {
return runtimeContextPool.Get().(*RuntimeContext)
}
func ReleaseRuntimeContext(ctx *RuntimeContext) {
runtimeContextPool.Put(ctx)
}
var (
isWhiteSpace = [256]bool{}
)
func init() {
isWhiteSpace[' '] = true
isWhiteSpace['\n'] = true
isWhiteSpace['\t'] = true
isWhiteSpace['\r'] = true
}
func char(ptr unsafe.Pointer, offset int64) byte {
return *(*byte)(unsafe.Pointer(uintptr(ptr) + uintptr(offset)))
}
func skipWhiteSpace(buf []byte, cursor int64) int64 {
for isWhiteSpace[buf[cursor]] {
cursor++
}
return cursor
}
func skipObject(buf []byte, cursor, depth int64) (int64, error) {
braceCount := 1
for {
switch buf[cursor] {
case '{':
braceCount++
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
case '}':
depth--
braceCount--
if braceCount == 0 {
return cursor + 1, nil
}
case '[':
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
case ']':
depth--
case '"':
for {
cursor++
switch buf[cursor] {
case '\\':
cursor++
if buf[cursor] == nul {
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
case '"':
goto SWITCH_OUT
case nul:
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
}
case nul:
return 0, errors.ErrUnexpectedEndOfJSON("object of object", cursor)
}
SWITCH_OUT:
cursor++
}
}
func skipArray(buf []byte, cursor, depth int64) (int64, error) {
bracketCount := 1
for {
switch buf[cursor] {
case '[':
bracketCount++
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
case ']':
bracketCount--
depth--
if bracketCount == 0 {
return cursor + 1, nil
}
case '{':
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
case '}':
depth--
case '"':
for {
cursor++
switch buf[cursor] {
case '\\':
cursor++
if buf[cursor] == nul {
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
case '"':
goto SWITCH_OUT
case nul:
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
}
case nul:
return 0, errors.ErrUnexpectedEndOfJSON("array of object", cursor)
}
SWITCH_OUT:
cursor++
}
}
func skipValue(buf []byte, cursor, depth int64) (int64, error) {
for {
switch buf[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case '{':
return skipObject(buf, cursor+1, depth+1)
case '[':
return skipArray(buf, cursor+1, depth+1)
case '"':
for {
cursor++
switch buf[cursor] {
case '\\':
cursor++
if buf[cursor] == nul {
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
case '"':
return cursor + 1, nil
case nul:
return 0, errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
for {
cursor++
if floatTable[buf[cursor]] {
continue
}
break
}
return cursor, nil
case 't':
if err := validateTrue(buf, cursor); err != nil {
return 0, err
}
cursor += 4
return cursor, nil
case 'f':
if err := validateFalse(buf, cursor); err != nil {
return 0, err
}
cursor += 5
return cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
return cursor, nil
default:
return cursor, errors.ErrUnexpectedEndOfJSON("null", cursor)
}
}
}
func validateTrue(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) {
return errors.ErrUnexpectedEndOfJSON("true", cursor)
}
if buf[cursor+1] != 'r' {
return errors.ErrInvalidCharacter(buf[cursor+1], "true", cursor)
}
if buf[cursor+2] != 'u' {
return errors.ErrInvalidCharacter(buf[cursor+2], "true", cursor)
}
if buf[cursor+3] != 'e' {
return errors.ErrInvalidCharacter(buf[cursor+3], "true", cursor)
}
return nil
}
func validateFalse(buf []byte, cursor int64) error {
if cursor+4 >= int64(len(buf)) {
return errors.ErrUnexpectedEndOfJSON("false", cursor)
}
if buf[cursor+1] != 'a' {
return errors.ErrInvalidCharacter(buf[cursor+1], "false", cursor)
}
if buf[cursor+2] != 'l' {
return errors.ErrInvalidCharacter(buf[cursor+2], "false", cursor)
}
if buf[cursor+3] != 's' {
return errors.ErrInvalidCharacter(buf[cursor+3], "false", cursor)
}
if buf[cursor+4] != 'e' {
return errors.ErrInvalidCharacter(buf[cursor+4], "false", cursor)
}
return nil
}
func validateNull(buf []byte, cursor int64) error {
if cursor+3 >= int64(len(buf)) {
return errors.ErrUnexpectedEndOfJSON("null", cursor)
}
if buf[cursor+1] != 'u' {
return errors.ErrInvalidCharacter(buf[cursor+1], "null", cursor)
}
if buf[cursor+2] != 'l' {
return errors.ErrInvalidCharacter(buf[cursor+2], "null", cursor)
}
if buf[cursor+3] != 'l' {
return errors.ErrInvalidCharacter(buf[cursor+3], "null", cursor)
}
return nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/float.go
================================================
package decoder
import (
"strconv"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type floatDecoder struct {
op func(unsafe.Pointer, float64)
structName string
fieldName string
}
func newFloatDecoder(structName, fieldName string, op func(unsafe.Pointer, float64)) *floatDecoder {
return &floatDecoder{op: op, structName: structName, fieldName: fieldName}
}
var (
floatTable = [256]bool{
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
'.': true,
'e': true,
'E': true,
'+': true,
'-': true,
}
validEndNumberChar = [256]bool{
nul: true,
' ': true,
'\t': true,
'\r': true,
'\n': true,
',': true,
':': true,
'}': true,
']': true,
}
)
func floatBytes(s *Stream) []byte {
start := s.cursor
for {
s.cursor++
if floatTable[s.char()] {
continue
} else if s.char() == nul {
if s.read() {
s.cursor-- // for retry current character
continue
}
}
break
}
return s.buf[start:s.cursor]
}
func (d *floatDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return floatBytes(s), nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
goto ERROR
default:
goto ERROR
}
}
ERROR:
return nil, errors.ErrUnexpectedEndOfJSON("float", s.totalOffset())
}
func (d *floatDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor
cursor++
for floatTable[buf[cursor]] {
cursor++
}
num := buf[start:cursor]
return num, cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
}
cursor += 4
return nil, cursor, nil
default:
return nil, 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
}
}
}
func (d *floatDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {
return err
}
if bytes == nil {
return nil
}
str := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(str, 64)
if err != nil {
return errors.ErrSyntax(err.Error(), s.totalOffset())
}
d.op(p, f64)
return nil
}
func (d *floatDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
bytes, c, err := d.decodeByte(buf, cursor)
if err != nil {
return 0, err
}
if bytes == nil {
return c, nil
}
cursor = c
if !validEndNumberChar[buf[cursor]] {
return 0, errors.ErrUnexpectedEndOfJSON("float", cursor)
}
s := *(*string)(unsafe.Pointer(&bytes))
f64, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0, errors.ErrSyntax(err.Error(), cursor)
}
d.op(p, f64)
return cursor, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/func.go
================================================
package decoder
import (
"bytes"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type funcDecoder struct {
typ *runtime.Type
structName string
fieldName string
}
func newFuncDecoder(typ *runtime.Type, structName, fieldName string) *funcDecoder {
fnDecoder := &funcDecoder{typ, structName, fieldName}
return fnDecoder
}
func (d *funcDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace()
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
if len(src) > 0 {
switch src[0] {
case '"':
return &errors.UnmarshalTypeError{
Value: "string",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case '[':
return &errors.UnmarshalTypeError{
Value: "array",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case '{':
return &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return &errors.UnmarshalTypeError{
Value: "number",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case 'n':
if err := nullBytes(s); err != nil {
return err
}
*(*unsafe.Pointer)(p) = nil
return nil
case 't':
if err := trueBytes(s); err == nil {
return &errors.UnmarshalTypeError{
Value: "boolean",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
}
case 'f':
if err := falseBytes(s); err == nil {
return &errors.UnmarshalTypeError{
Value: "boolean",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
}
}
}
return errors.ErrInvalidBeginningOfValue(s.buf[s.cursor], s.totalOffset())
}
func (d *funcDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
if len(src) > 0 {
switch src[0] {
case '"':
return 0, &errors.UnmarshalTypeError{
Value: "string",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case '[':
return 0, &errors.UnmarshalTypeError{
Value: "array",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case '{':
return 0, &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, &errors.UnmarshalTypeError{
Value: "number",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case 'n':
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return end, nil
}
case 't':
if err := validateTrue(buf, start); err == nil {
return 0, &errors.UnmarshalTypeError{
Value: "boolean",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
}
case 'f':
if err := validateFalse(buf, start); err == nil {
return 0, &errors.UnmarshalTypeError{
Value: "boolean",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
}
}
}
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/int.go
================================================
package decoder
import (
"fmt"
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type intDecoder struct {
typ *runtime.Type
kind reflect.Kind
op func(unsafe.Pointer, int64)
structName string
fieldName string
}
func newIntDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder {
return &intDecoder{
typ: typ,
kind: typ.Kind(),
op: op,
structName: structName,
fieldName: fieldName,
}
}
func (d *intDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: fmt.Sprintf("number %s", string(buf)),
Type: runtime.RType2Type(d.typ),
Struct: d.structName,
Field: d.fieldName,
Offset: offset,
}
}
var (
pow10i64 = [...]int64{
1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18,
}
pow10i64Len = len(pow10i64)
)
func (d *intDecoder) parseInt(b []byte) (int64, error) {
isNegative := false
if b[0] == '-' {
b = b[1:]
isNegative = true
}
maxDigit := len(b)
if maxDigit > pow10i64Len {
return 0, fmt.Errorf("invalid length of number")
}
sum := int64(0)
for i := 0; i < maxDigit; i++ {
c := int64(b[i]) - 48
digitValue := pow10i64[maxDigit-i-1]
sum += c * digitValue
}
if isNegative {
return -1 * sum, nil
}
return sum, nil
}
var (
numTable = [256]bool{
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
}
)
var (
numZeroBuf = []byte{'0'}
)
func (d *intDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '-':
start := s.cursor
for {
s.cursor++
if numTable[s.char()] {
continue
} else if s.char() == nul {
if s.read() {
s.cursor-- // for retry current character
continue
}
}
break
}
num := s.buf[start:s.cursor]
if len(num) < 2 {
goto ERROR
}
return num, nil
case '0':
s.cursor++
return numZeroBuf, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := s.cursor
for {
s.cursor++
if numTable[s.char()] {
continue
} else if s.char() == nul {
if s.read() {
s.cursor-- // for retry current character
continue
}
}
break
}
num := s.buf[start:s.cursor]
return num, nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
goto ERROR
default:
return nil, d.typeError([]byte{s.char()}, s.totalOffset())
}
}
ERROR:
return nil, errors.ErrUnexpectedEndOfJSON("number(integer)", s.totalOffset())
}
func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
continue
case '0':
cursor++
return numZeroBuf, cursor, nil
case '-', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor
cursor++
for numTable[char(b, cursor)] {
cursor++
}
num := buf[start:cursor]
return num, cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
}
cursor += 4
return nil, cursor, nil
default:
return nil, 0, d.typeError([]byte{char(b, cursor)}, cursor)
}
}
}
func (d *intDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {
return err
}
if bytes == nil {
return nil
}
i64, err := d.parseInt(bytes)
if err != nil {
return d.typeError(bytes, s.totalOffset())
}
switch d.kind {
case reflect.Int8:
if i64 < -1*(1<<7) || (1<<7) <= i64 {
return d.typeError(bytes, s.totalOffset())
}
case reflect.Int16:
if i64 < -1*(1<<15) || (1<<15) <= i64 {
return d.typeError(bytes, s.totalOffset())
}
case reflect.Int32:
if i64 < -1*(1<<31) || (1<<31) <= i64 {
return d.typeError(bytes, s.totalOffset())
}
}
d.op(p, i64)
s.reset()
return nil
}
func (d *intDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
if err != nil {
return 0, err
}
if bytes == nil {
return c, nil
}
cursor = c
i64, err := d.parseInt(bytes)
if err != nil {
return 0, d.typeError(bytes, cursor)
}
switch d.kind {
case reflect.Int8:
if i64 < -1*(1<<7) || (1<<7) <= i64 {
return 0, d.typeError(bytes, cursor)
}
case reflect.Int16:
if i64 < -1*(1<<15) || (1<<15) <= i64 {
return 0, d.typeError(bytes, cursor)
}
case reflect.Int32:
if i64 < -1*(1<<31) || (1<<31) <= i64 {
return 0, d.typeError(bytes, cursor)
}
}
d.op(p, i64)
return cursor, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/interface.go
================================================
package decoder
import (
"bytes"
"encoding"
"encoding/json"
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type interfaceDecoder struct {
typ *runtime.Type
structName string
fieldName string
sliceDecoder *sliceDecoder
mapDecoder *mapDecoder
floatDecoder *floatDecoder
numberDecoder *numberDecoder
stringDecoder *stringDecoder
}
func newEmptyInterfaceDecoder(structName, fieldName string) *interfaceDecoder {
ifaceDecoder := &interfaceDecoder{
typ: emptyInterfaceType,
structName: structName,
fieldName: fieldName,
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v
}),
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v
}),
stringDecoder: newStringDecoder(structName, fieldName),
}
ifaceDecoder.sliceDecoder = newSliceDecoder(
ifaceDecoder,
emptyInterfaceType,
emptyInterfaceType.Size(),
structName, fieldName,
)
ifaceDecoder.mapDecoder = newMapDecoder(
interfaceMapType,
stringType,
ifaceDecoder.stringDecoder,
interfaceMapType.Elem(),
ifaceDecoder,
structName,
fieldName,
)
return ifaceDecoder
}
func newInterfaceDecoder(typ *runtime.Type, structName, fieldName string) *interfaceDecoder {
emptyIfaceDecoder := newEmptyInterfaceDecoder(structName, fieldName)
stringDecoder := newStringDecoder(structName, fieldName)
return &interfaceDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
sliceDecoder: newSliceDecoder(
emptyIfaceDecoder,
emptyInterfaceType,
emptyInterfaceType.Size(),
structName, fieldName,
),
mapDecoder: newMapDecoder(
interfaceMapType,
stringType,
stringDecoder,
interfaceMapType.Elem(),
emptyIfaceDecoder,
structName,
fieldName,
),
floatDecoder: newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) {
*(*interface{})(p) = v
}),
numberDecoder: newNumberDecoder(structName, fieldName, func(p unsafe.Pointer, v json.Number) {
*(*interface{})(p) = v
}),
stringDecoder: stringDecoder,
}
}
func (d *interfaceDecoder) numDecoder(s *Stream) Decoder {
if s.UseNumber {
return d.numberDecoder
}
return d.floatDecoder
}
var (
emptyInterfaceType = runtime.Type2RType(reflect.TypeOf((*interface{})(nil)).Elem())
interfaceMapType = runtime.Type2RType(
reflect.TypeOf((*map[string]interface{})(nil)).Elem(),
)
stringType = runtime.Type2RType(
reflect.TypeOf(""),
)
)
func decodeStreamUnmarshaler(s *Stream, depth int64, unmarshaler json.Unmarshaler) error {
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(dst); err != nil {
return err
}
return nil
}
func decodeStreamUnmarshalerContext(s *Stream, depth int64, unmarshaler unmarshalerContext) error {
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(s.Option.Context, dst); err != nil {
return err
}
return nil
}
func decodeUnmarshaler(buf []byte, cursor, depth int64, unmarshaler json.Unmarshaler) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(dst); err != nil {
return 0, err
}
return end, nil
}
func decodeUnmarshalerContext(ctx *RuntimeContext, buf []byte, cursor, depth int64, unmarshaler unmarshalerContext) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalJSON(ctx.Option.Context, dst); err != nil {
return 0, err
}
return end, nil
}
func decodeStreamTextUnmarshaler(s *Stream, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) error {
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return nil
}
dst := make([]byte, len(src))
copy(dst, src)
if err := unmarshaler.UnmarshalText(dst); err != nil {
return err
}
return nil
}
func decodeTextUnmarshaler(buf []byte, cursor, depth int64, unmarshaler encoding.TextUnmarshaler, p unsafe.Pointer) (int64, error) {
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return end, nil
}
if s, ok := unquoteBytes(src); ok {
src = s
}
if err := unmarshaler.UnmarshalText(src); err != nil {
return 0, err
}
return end, nil
}
func (d *interfaceDecoder) decodeStreamEmptyInterface(s *Stream, depth int64, p unsafe.Pointer) error {
c := s.skipWhiteSpace()
for {
switch c {
case '{':
var v map[string]interface{}
ptr := unsafe.Pointer(&v)
if err := d.mapDecoder.DecodeStream(s, depth, ptr); err != nil {
return err
}
*(*interface{})(p) = v
return nil
case '[':
var v []interface{}
ptr := unsafe.Pointer(&v)
if err := d.sliceDecoder.DecodeStream(s, depth, ptr); err != nil {
return err
}
*(*interface{})(p) = v
return nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return d.numDecoder(s).DecodeStream(s, depth, p)
case '"':
s.cursor++
start := s.cursor
for {
switch s.char() {
case '\\':
if _, err := decodeEscapeString(s, nil); err != nil {
return err
}
case '"':
literal := s.buf[start:s.cursor]
s.cursor++
*(*interface{})(p) = string(literal)
return nil
case nul:
if s.read() {
continue
}
return errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
s.cursor++
}
case 't':
if err := trueBytes(s); err != nil {
return err
}
**(**interface{})(unsafe.Pointer(&p)) = true
return nil
case 'f':
if err := falseBytes(s); err != nil {
return err
}
**(**interface{})(unsafe.Pointer(&p)) = false
return nil
case 'n':
if err := nullBytes(s); err != nil {
return err
}
*(*interface{})(p) = nil
return nil
case nul:
if s.read() {
c = s.char()
continue
}
}
break
}
return errors.ErrInvalidBeginningOfValue(c, s.totalOffset())
}
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
func (d *interfaceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: p,
}))
rv := reflect.ValueOf(runtimeInterfaceValue)
if rv.NumMethod() > 0 && rv.CanInterface() {
if u, ok := rv.Interface().(unmarshalerContext); ok {
return decodeStreamUnmarshalerContext(s, depth, u)
}
if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeStreamUnmarshaler(s, depth, u)
}
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
return decodeStreamTextUnmarshaler(s, depth, u, p)
}
if s.skipWhiteSpace() == 'n' {
if err := nullBytes(s); err != nil {
return err
}
*(*interface{})(p) = nil
return nil
}
return d.errUnmarshalType(rv.Type(), s.totalOffset())
}
iface := rv.Interface()
ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
typ := ifaceHeader.typ
if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
// concrete type is empty interface
return d.decodeStreamEmptyInterface(s, depth, p)
}
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
return d.decodeStreamEmptyInterface(s, depth, p)
}
if s.skipWhiteSpace() == 'n' {
if err := nullBytes(s); err != nil {
return err
}
*(*interface{})(p) = nil
return nil
}
decoder, err := CompileToGetDecoder(typ)
if err != nil {
return err
}
return decoder.DecodeStream(s, depth, ifaceHeader.ptr)
}
func (d *interfaceDecoder) errUnmarshalType(typ reflect.Type, offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: typ.String(),
Type: typ,
Offset: offset,
Struct: d.structName,
Field: d.fieldName,
}
}
func (d *interfaceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
runtimeInterfaceValue := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: p,
}))
rv := reflect.ValueOf(runtimeInterfaceValue)
if rv.NumMethod() > 0 && rv.CanInterface() {
if u, ok := rv.Interface().(unmarshalerContext); ok {
return decodeUnmarshalerContext(ctx, buf, cursor, depth, u)
}
if u, ok := rv.Interface().(json.Unmarshaler); ok {
return decodeUnmarshaler(buf, cursor, depth, u)
}
if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
return decodeTextUnmarshaler(buf, cursor, depth, u, p)
}
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil
}
return 0, d.errUnmarshalType(rv.Type(), cursor)
}
iface := rv.Interface()
ifaceHeader := (*emptyInterface)(unsafe.Pointer(&iface))
typ := ifaceHeader.typ
if ifaceHeader.ptr == nil || d.typ == typ || typ == nil {
// concrete type is empty interface
return d.decodeEmptyInterface(ctx, cursor, depth, p)
}
if typ.Kind() == reflect.Ptr && typ.Elem() == d.typ || typ.Kind() != reflect.Ptr {
return d.decodeEmptyInterface(ctx, cursor, depth, p)
}
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil
}
decoder, err := CompileToGetDecoder(typ)
if err != nil {
return 0, err
}
return decoder.Decode(ctx, cursor, depth, ifaceHeader.ptr)
}
func (d *interfaceDecoder) decodeEmptyInterface(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case '{':
var v map[string]interface{}
ptr := unsafe.Pointer(&v)
cursor, err := d.mapDecoder.Decode(ctx, cursor, depth, ptr)
if err != nil {
return 0, err
}
**(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil
case '[':
var v []interface{}
ptr := unsafe.Pointer(&v)
cursor, err := d.sliceDecoder.Decode(ctx, cursor, depth, ptr)
if err != nil {
return 0, err
}
**(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return d.floatDecoder.Decode(ctx, cursor, depth, p)
case '"':
var v string
ptr := unsafe.Pointer(&v)
cursor, err := d.stringDecoder.Decode(ctx, cursor, depth, ptr)
if err != nil {
return 0, err
}
**(**interface{})(unsafe.Pointer(&p)) = v
return cursor, nil
case 't':
if err := validateTrue(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = true
return cursor, nil
case 'f':
if err := validateFalse(buf, cursor); err != nil {
return 0, err
}
cursor += 5
**(**interface{})(unsafe.Pointer(&p)) = false
return cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**interface{})(unsafe.Pointer(&p)) = nil
return cursor, nil
}
return cursor, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/invalid.go
================================================
package decoder
import (
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type invalidDecoder struct {
typ *runtime.Type
kind reflect.Kind
structName string
fieldName string
}
func newInvalidDecoder(typ *runtime.Type, structName, fieldName string) *invalidDecoder {
return &invalidDecoder{
typ: typ,
kind: typ.Kind(),
structName: structName,
fieldName: fieldName,
}
}
func (d *invalidDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
return &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
Struct: d.structName,
Field: d.fieldName,
}
}
func (d *invalidDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
return 0, &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: cursor,
Struct: d.structName,
Field: d.fieldName,
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/map.go
================================================
package decoder
import (
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type mapDecoder struct {
mapType *runtime.Type
keyType *runtime.Type
valueType *runtime.Type
canUseAssignFaststrType bool
keyDecoder Decoder
valueDecoder Decoder
structName string
fieldName string
}
func newMapDecoder(mapType *runtime.Type, keyType *runtime.Type, keyDec Decoder, valueType *runtime.Type, valueDec Decoder, structName, fieldName string) *mapDecoder {
return &mapDecoder{
mapType: mapType,
keyDecoder: keyDec,
keyType: keyType,
canUseAssignFaststrType: canUseAssignFaststrType(keyType, valueType),
valueType: valueType,
valueDecoder: valueDec,
structName: structName,
fieldName: fieldName,
}
}
const (
mapMaxElemSize = 128
)
// See detail: https://github.com/goccy/go-json/pull/283
func canUseAssignFaststrType(key *runtime.Type, value *runtime.Type) bool {
indirectElem := value.Size() > mapMaxElemSize
if indirectElem {
return false
}
return key.Kind() == reflect.String
}
//go:linkname makemap reflect.makemap
func makemap(*runtime.Type, int) unsafe.Pointer
//nolint:golint
//go:linkname mapassign_faststr runtime.mapassign_faststr
//go:noescape
func mapassign_faststr(t *runtime.Type, m unsafe.Pointer, s string) unsafe.Pointer
//go:linkname mapassign reflect.mapassign
//go:noescape
func mapassign(t *runtime.Type, m unsafe.Pointer, k, v unsafe.Pointer)
func (d *mapDecoder) mapassign(t *runtime.Type, m, k, v unsafe.Pointer) {
if d.canUseAssignFaststrType {
mapV := mapassign_faststr(t, m, *(*string)(k))
typedmemmove(d.valueType, mapV, v)
} else {
mapassign(t, m, k, v)
}
}
func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
switch s.skipWhiteSpace() {
case 'n':
if err := nullBytes(s); err != nil {
return err
}
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
return nil
case '{':
default:
return errors.ErrExpected("{ character for map value", s.totalOffset())
}
mapValue := *(*unsafe.Pointer)(p)
if mapValue == nil {
mapValue = makemap(d.mapType, 0)
}
s.cursor++
if s.equalChar('}') {
*(*unsafe.Pointer)(p) = mapValue
s.cursor++
return nil
}
for {
k := unsafe_New(d.keyType)
if err := d.keyDecoder.DecodeStream(s, depth, k); err != nil {
return err
}
s.skipWhiteSpace()
if !s.equalChar(':') {
return errors.ErrExpected("colon after object key", s.totalOffset())
}
s.cursor++
v := unsafe_New(d.valueType)
if err := d.valueDecoder.DecodeStream(s, depth, v); err != nil {
return err
}
d.mapassign(d.mapType, mapValue, k, v)
s.skipWhiteSpace()
if s.equalChar('}') {
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
s.cursor++
return nil
}
if !s.equalChar(',') {
return errors.ErrExpected("comma after object value", s.totalOffset())
}
s.cursor++
}
}
func (d *mapDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
cursor = skipWhiteSpace(buf, cursor)
buflen := int64(len(buf))
if buflen < 2 {
return 0, errors.ErrExpected("{} for map", cursor)
}
switch buf[cursor] {
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = nil
return cursor, nil
case '{':
default:
return 0, errors.ErrExpected("{ character for map value", cursor)
}
cursor++
cursor = skipWhiteSpace(buf, cursor)
mapValue := *(*unsafe.Pointer)(p)
if mapValue == nil {
mapValue = makemap(d.mapType, 0)
}
if buf[cursor] == '}' {
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
cursor++
return cursor, nil
}
for {
k := unsafe_New(d.keyType)
keyCursor, err := d.keyDecoder.Decode(ctx, cursor, depth, k)
if err != nil {
return 0, err
}
cursor = skipWhiteSpace(buf, keyCursor)
if buf[cursor] != ':' {
return 0, errors.ErrExpected("colon after object key", cursor)
}
cursor++
v := unsafe_New(d.valueType)
valueCursor, err := d.valueDecoder.Decode(ctx, cursor, depth, v)
if err != nil {
return 0, err
}
d.mapassign(d.mapType, mapValue, k, v)
cursor = skipWhiteSpace(buf, valueCursor)
if buf[cursor] == '}' {
**(**unsafe.Pointer)(unsafe.Pointer(&p)) = mapValue
cursor++
return cursor, nil
}
if buf[cursor] != ',' {
return 0, errors.ErrExpected("comma after object value", cursor)
}
cursor++
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/number.go
================================================
package decoder
import (
"encoding/json"
"strconv"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type numberDecoder struct {
stringDecoder *stringDecoder
op func(unsafe.Pointer, json.Number)
structName string
fieldName string
}
func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, json.Number)) *numberDecoder {
return &numberDecoder{
stringDecoder: newStringDecoder(structName, fieldName),
op: op,
structName: structName,
fieldName: fieldName,
}
}
func (d *numberDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {
return err
}
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
return errors.ErrSyntax(err.Error(), s.totalOffset())
}
d.op(p, json.Number(string(bytes)))
s.reset()
return nil
}
func (d *numberDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
if err != nil {
return 0, err
}
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&bytes)), 64); err != nil {
return 0, errors.ErrSyntax(err.Error(), c)
}
cursor = c
s := *(*string)(unsafe.Pointer(&bytes))
d.op(p, json.Number(s))
return cursor, nil
}
func (d *numberDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
start := s.cursor
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return floatBytes(s), nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case '"':
return d.stringDecoder.decodeStreamByte(s)
case nul:
if s.read() {
continue
}
goto ERROR
default:
goto ERROR
}
}
ERROR:
if s.cursor == start {
return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
}
return nil, errors.ErrUnexpectedEndOfJSON("json.Number", s.totalOffset())
}
func (d *numberDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
continue
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor
cursor++
for floatTable[buf[cursor]] {
cursor++
}
num := buf[start:cursor]
return num, cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
}
cursor += 4
return nil, cursor, nil
case '"':
return d.stringDecoder.decodeByte(buf, cursor)
default:
return nil, 0, errors.ErrUnexpectedEndOfJSON("json.Number", cursor)
}
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/option.go
================================================
package decoder
import "context"
type OptionFlags uint8
const (
FirstWinOption OptionFlags = 1 << iota
ContextOption
)
type Option struct {
Flags OptionFlags
Context context.Context
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/ptr.go
================================================
package decoder
import (
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type ptrDecoder struct {
dec Decoder
typ *runtime.Type
structName string
fieldName string
}
func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder {
return &ptrDecoder{
dec: dec,
typ: typ,
structName: structName,
fieldName: fieldName,
}
}
func (d *ptrDecoder) contentDecoder() Decoder {
dec, ok := d.dec.(*ptrDecoder)
if !ok {
return d.dec
}
return dec.contentDecoder()
}
//nolint:golint
//go:linkname unsafe_New reflect.unsafe_New
func unsafe_New(*runtime.Type) unsafe.Pointer
func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
if s.skipWhiteSpace() == nul {
s.read()
}
if s.char() == 'n' {
if err := nullBytes(s); err != nil {
return err
}
*(*unsafe.Pointer)(p) = nil
return nil
}
var newptr unsafe.Pointer
if *(*unsafe.Pointer)(p) == nil {
newptr = unsafe_New(d.typ)
*(*unsafe.Pointer)(p) = newptr
} else {
newptr = *(*unsafe.Pointer)(p)
}
if err := d.dec.DecodeStream(s, depth, newptr); err != nil {
return err
}
return nil
}
func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == 'n' {
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
if p != nil {
*(*unsafe.Pointer)(p) = nil
}
cursor += 4
return cursor, nil
}
var newptr unsafe.Pointer
if *(*unsafe.Pointer)(p) == nil {
newptr = unsafe_New(d.typ)
*(*unsafe.Pointer)(p) = newptr
} else {
newptr = *(*unsafe.Pointer)(p)
}
c, err := d.dec.Decode(ctx, cursor, depth, newptr)
if err != nil {
return 0, err
}
cursor = c
return cursor, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/slice.go
================================================
package decoder
import (
"reflect"
"sync"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
var (
sliceType = runtime.Type2RType(
reflect.TypeOf((*sliceHeader)(nil)).Elem(),
)
nilSlice = unsafe.Pointer(&sliceHeader{})
)
type sliceDecoder struct {
elemType *runtime.Type
isElemPointerType bool
valueDecoder Decoder
size uintptr
arrayPool sync.Pool
structName string
fieldName string
}
// If use reflect.SliceHeader, data type is uintptr.
// In this case, Go compiler cannot trace reference created by newArray().
// So, define using unsafe.Pointer as data type
type sliceHeader struct {
data unsafe.Pointer
len int
cap int
}
const (
defaultSliceCapacity = 2
)
func newSliceDecoder(dec Decoder, elemType *runtime.Type, size uintptr, structName, fieldName string) *sliceDecoder {
return &sliceDecoder{
valueDecoder: dec,
elemType: elemType,
isElemPointerType: elemType.Kind() == reflect.Ptr || elemType.Kind() == reflect.Map,
size: size,
arrayPool: sync.Pool{
New: func() interface{} {
return &sliceHeader{
data: newArray(elemType, defaultSliceCapacity),
len: 0,
cap: defaultSliceCapacity,
}
},
},
structName: structName,
fieldName: fieldName,
}
}
func (d *sliceDecoder) newSlice(src *sliceHeader) *sliceHeader {
slice := d.arrayPool.Get().(*sliceHeader)
if src.len > 0 {
// copy original elem
if slice.cap < src.cap {
data := newArray(d.elemType, src.cap)
slice = &sliceHeader{data: data, len: src.len, cap: src.cap}
} else {
slice.len = src.len
}
copySlice(d.elemType, *slice, *src)
} else {
slice.len = 0
}
return slice
}
func (d *sliceDecoder) releaseSlice(p *sliceHeader) {
d.arrayPool.Put(p)
}
//go:linkname copySlice reflect.typedslicecopy
func copySlice(elemType *runtime.Type, dst, src sliceHeader) int
//go:linkname newArray reflect.unsafe_NewArray
func newArray(*runtime.Type, int) unsafe.Pointer
//go:linkname typedmemmove reflect.typedmemmove
func typedmemmove(t *runtime.Type, dst, src unsafe.Pointer)
func (d *sliceDecoder) errNumber(offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: "number",
Type: reflect.SliceOf(runtime.RType2Type(d.elemType)),
Struct: d.structName,
Field: d.fieldName,
Offset: offset,
}
}
func (d *sliceDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case 'n':
if err := nullBytes(s); err != nil {
return err
}
typedmemmove(sliceType, p, nilSlice)
return nil
case '[':
s.cursor++
if s.skipWhiteSpace() == ']' {
dst := (*sliceHeader)(p)
if dst.data == nil {
dst.data = newArray(d.elemType, 0)
} else {
dst.len = 0
}
s.cursor++
return nil
}
idx := 0
slice := d.newSlice((*sliceHeader)(p))
srcLen := slice.len
capacity := slice.cap
data := slice.data
for {
if capacity <= idx {
src := sliceHeader{data: data, len: idx, cap: capacity}
capacity *= 2
data = newArray(d.elemType, capacity)
dst := sliceHeader{data: data, len: idx, cap: capacity}
copySlice(d.elemType, dst, src)
}
ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
// if srcLen is greater than idx, keep the original reference
if srcLen <= idx {
if d.isElemPointerType {
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
} else {
// assign new element to the slice
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
}
}
if err := d.valueDecoder.DecodeStream(s, depth, ep); err != nil {
return err
}
s.skipWhiteSpace()
RETRY:
switch s.char() {
case ']':
slice.cap = capacity
slice.len = idx + 1
slice.data = data
dst := (*sliceHeader)(p)
dst.len = idx + 1
if dst.len > dst.cap {
dst.data = newArray(d.elemType, dst.len)
dst.cap = dst.len
}
copySlice(d.elemType, *dst, *slice)
d.releaseSlice(slice)
s.cursor++
return nil
case ',':
idx++
case nul:
if s.read() {
goto RETRY
}
slice.cap = capacity
slice.data = data
d.releaseSlice(slice)
goto ERROR
default:
slice.cap = capacity
slice.data = data
d.releaseSlice(slice)
goto ERROR
}
s.cursor++
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return d.errNumber(s.totalOffset())
case nul:
if s.read() {
continue
}
goto ERROR
default:
goto ERROR
}
}
ERROR:
return errors.ErrUnexpectedEndOfJSON("slice", s.totalOffset())
}
func (d *sliceDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
continue
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
typedmemmove(sliceType, p, nilSlice)
return cursor, nil
case '[':
cursor++
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == ']' {
dst := (*sliceHeader)(p)
if dst.data == nil {
dst.data = newArray(d.elemType, 0)
} else {
dst.len = 0
}
cursor++
return cursor, nil
}
idx := 0
slice := d.newSlice((*sliceHeader)(p))
srcLen := slice.len
capacity := slice.cap
data := slice.data
for {
if capacity <= idx {
src := sliceHeader{data: data, len: idx, cap: capacity}
capacity *= 2
data = newArray(d.elemType, capacity)
dst := sliceHeader{data: data, len: idx, cap: capacity}
copySlice(d.elemType, dst, src)
}
ep := unsafe.Pointer(uintptr(data) + uintptr(idx)*d.size)
// if srcLen is greater than idx, keep the original reference
if srcLen <= idx {
if d.isElemPointerType {
**(**unsafe.Pointer)(unsafe.Pointer(&ep)) = nil // initialize elem pointer
} else {
// assign new element to the slice
typedmemmove(d.elemType, ep, unsafe_New(d.elemType))
}
}
c, err := d.valueDecoder.Decode(ctx, cursor, depth, ep)
if err != nil {
return 0, err
}
cursor = c
cursor = skipWhiteSpace(buf, cursor)
switch buf[cursor] {
case ']':
slice.cap = capacity
slice.len = idx + 1
slice.data = data
dst := (*sliceHeader)(p)
dst.len = idx + 1
if dst.len > dst.cap {
dst.data = newArray(d.elemType, dst.len)
dst.cap = dst.len
}
copySlice(d.elemType, *dst, *slice)
d.releaseSlice(slice)
cursor++
return cursor, nil
case ',':
idx++
default:
slice.cap = capacity
slice.data = data
d.releaseSlice(slice)
return 0, errors.ErrInvalidCharacter(buf[cursor], "slice", cursor)
}
cursor++
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, d.errNumber(cursor)
default:
return 0, errors.ErrUnexpectedEndOfJSON("slice", cursor)
}
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/stream.go
================================================
package decoder
import (
"bytes"
"encoding/json"
"io"
"strconv"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
const (
initBufSize = 512
)
type Stream struct {
buf []byte
bufSize int64
length int64
r io.Reader
offset int64
cursor int64
filledBuffer bool
allRead bool
UseNumber bool
DisallowUnknownFields bool
Option *Option
}
func NewStream(r io.Reader) *Stream {
return &Stream{
r: r,
bufSize: initBufSize,
buf: make([]byte, initBufSize),
Option: &Option{},
}
}
func (s *Stream) TotalOffset() int64 {
return s.totalOffset()
}
func (s *Stream) Buffered() io.Reader {
buflen := int64(len(s.buf))
for i := s.cursor; i < buflen; i++ {
if s.buf[i] == nul {
return bytes.NewReader(s.buf[s.cursor:i])
}
}
return bytes.NewReader(s.buf[s.cursor:])
}
func (s *Stream) PrepareForDecode() error {
for {
switch s.char() {
case ' ', '\t', '\r', '\n':
s.cursor++
continue
case ',', ':':
s.cursor++
return nil
case nul:
if s.read() {
continue
}
return io.EOF
}
break
}
return nil
}
func (s *Stream) totalOffset() int64 {
return s.offset + s.cursor
}
func (s *Stream) char() byte {
return s.buf[s.cursor]
}
func (s *Stream) equalChar(c byte) bool {
cur := s.buf[s.cursor]
if cur == nul {
s.read()
cur = s.buf[s.cursor]
}
return cur == c
}
func (s *Stream) stat() ([]byte, int64, unsafe.Pointer) {
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
}
func (s *Stream) bufptr() unsafe.Pointer {
return (*sliceHeader)(unsafe.Pointer(&s.buf)).data
}
func (s *Stream) statForRetry() ([]byte, int64, unsafe.Pointer) {
s.cursor-- // for retry ( because caller progress cursor position in each loop )
return s.buf, s.cursor, (*sliceHeader)(unsafe.Pointer(&s.buf)).data
}
func (s *Stream) Reset() {
s.reset()
s.bufSize = int64(len(s.buf))
}
func (s *Stream) More() bool {
for {
switch s.char() {
case ' ', '\n', '\r', '\t':
s.cursor++
continue
case '}', ']':
return false
case nul:
if s.read() {
continue
}
return false
}
break
}
return true
}
func (s *Stream) Token() (interface{}, error) {
for {
c := s.char()
switch c {
case ' ', '\n', '\r', '\t':
s.cursor++
case '{', '[', ']', '}':
s.cursor++
return json.Delim(c), nil
case ',', ':':
s.cursor++
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
bytes := floatBytes(s)
str := *(*string)(unsafe.Pointer(&bytes))
if s.UseNumber {
return json.Number(str), nil
}
f64, err := strconv.ParseFloat(str, 64)
if err != nil {
return nil, err
}
return f64, nil
case '"':
bytes, err := stringBytes(s)
if err != nil {
return nil, err
}
return string(bytes), nil
case 't':
if err := trueBytes(s); err != nil {
return nil, err
}
return true, nil
case 'f':
if err := falseBytes(s); err != nil {
return nil, err
}
return false, nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
goto END
default:
return nil, errors.ErrInvalidCharacter(s.char(), "token", s.totalOffset())
}
}
END:
return nil, io.EOF
}
func (s *Stream) reset() {
s.offset += s.cursor
s.buf = s.buf[s.cursor:]
s.length -= s.cursor
s.cursor = 0
}
func (s *Stream) readBuf() []byte {
if s.filledBuffer {
s.bufSize *= 2
remainBuf := s.buf
s.buf = make([]byte, s.bufSize)
copy(s.buf, remainBuf)
}
remainLen := s.length - s.cursor
remainNotNulCharNum := int64(0)
for i := int64(0); i < remainLen; i++ {
if s.buf[s.cursor+i] == nul {
break
}
remainNotNulCharNum++
}
s.length = s.cursor + remainNotNulCharNum
return s.buf[s.cursor+remainNotNulCharNum:]
}
func (s *Stream) read() bool {
if s.allRead {
return false
}
buf := s.readBuf()
last := len(buf) - 1
buf[last] = nul
n, err := s.r.Read(buf[:last])
s.length += int64(n)
if n == last {
s.filledBuffer = true
} else {
s.filledBuffer = false
}
if err == io.EOF {
s.allRead = true
} else if err != nil {
return false
}
return true
}
func (s *Stream) skipWhiteSpace() byte {
p := s.bufptr()
LOOP:
c := char(p, s.cursor)
switch c {
case ' ', '\n', '\t', '\r':
s.cursor++
goto LOOP
case nul:
if s.read() {
p = s.bufptr()
goto LOOP
}
}
return c
}
func (s *Stream) skipObject(depth int64) error {
braceCount := 1
_, cursor, p := s.stat()
for {
switch char(p, cursor) {
case '{':
braceCount++
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
case '}':
braceCount--
depth--
if braceCount == 0 {
s.cursor = cursor + 1
return nil
}
case '[':
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
case ']':
depth--
case '"':
for {
cursor++
switch char(p, cursor) {
case '\\':
cursor++
if char(p, cursor) == nul {
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
case '"':
goto SWITCH_OUT
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.statForRetry()
continue
}
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
}
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("object of object", cursor)
}
SWITCH_OUT:
cursor++
}
}
func (s *Stream) skipArray(depth int64) error {
bracketCount := 1
_, cursor, p := s.stat()
for {
switch char(p, cursor) {
case '[':
bracketCount++
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
case ']':
bracketCount--
depth--
if bracketCount == 0 {
s.cursor = cursor + 1
return nil
}
case '{':
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
case '}':
depth--
case '"':
for {
cursor++
switch char(p, cursor) {
case '\\':
cursor++
if char(p, cursor) == nul {
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
case '"':
goto SWITCH_OUT
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.statForRetry()
continue
}
return errors.ErrUnexpectedEndOfJSON("string of object", cursor)
}
}
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("array of object", cursor)
}
SWITCH_OUT:
cursor++
}
}
func (s *Stream) skipValue(depth int64) error {
_, cursor, p := s.stat()
for {
switch char(p, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
continue
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("value of object", s.totalOffset())
case '{':
s.cursor = cursor + 1
return s.skipObject(depth + 1)
case '[':
s.cursor = cursor + 1
return s.skipArray(depth + 1)
case '"':
for {
cursor++
switch char(p, cursor) {
case '\\':
cursor++
if char(p, cursor) == nul {
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
}
case '"':
s.cursor = cursor + 1
return nil
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.statForRetry()
continue
}
return errors.ErrUnexpectedEndOfJSON("value of string", s.totalOffset())
}
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
for {
cursor++
c := char(p, cursor)
if floatTable[c] {
continue
} else if c == nul {
if s.read() {
_, cursor, p = s.stat()
continue
}
}
s.cursor = cursor
return nil
}
case 't':
s.cursor = cursor
if err := trueBytes(s); err != nil {
return err
}
return nil
case 'f':
s.cursor = cursor
if err := falseBytes(s); err != nil {
return err
}
return nil
case 'n':
s.cursor = cursor
if err := nullBytes(s); err != nil {
return err
}
return nil
}
cursor++
}
}
func nullBytes(s *Stream) error {
// current cursor's character is 'n'
s.cursor++
if s.char() != 'u' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadNull(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadNull(s *Stream) error {
if s.char() == nul && s.read() {
return nil
}
return errors.ErrInvalidCharacter(s.char(), "null", s.totalOffset())
}
func trueBytes(s *Stream) error {
// current cursor's character is 't'
s.cursor++
if s.char() != 'r' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'u' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'e' {
if err := retryReadTrue(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadTrue(s *Stream) error {
if s.char() == nul && s.read() {
return nil
}
return errors.ErrInvalidCharacter(s.char(), "bool(true)", s.totalOffset())
}
func falseBytes(s *Stream) error {
// current cursor's character is 'f'
s.cursor++
if s.char() != 'a' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'l' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 's' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
if s.char() != 'e' {
if err := retryReadFalse(s); err != nil {
return err
}
}
s.cursor++
return nil
}
func retryReadFalse(s *Stream) error {
if s.char() == nul && s.read() {
return nil
}
return errors.ErrInvalidCharacter(s.char(), "bool(false)", s.totalOffset())
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/string.go
================================================
package decoder
import (
"bytes"
"fmt"
"reflect"
"unicode"
"unicode/utf16"
"unicode/utf8"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type stringDecoder struct {
structName string
fieldName string
}
func newStringDecoder(structName, fieldName string) *stringDecoder {
return &stringDecoder{
structName: structName,
fieldName: fieldName,
}
}
func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: typeName,
Type: reflect.TypeOf(""),
Offset: offset,
Struct: d.structName,
Field: d.fieldName,
}
}
func (d *stringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {
return err
}
if bytes == nil {
return nil
}
**(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes))
s.reset()
return nil
}
func (d *stringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
if err != nil {
return 0, err
}
if bytes == nil {
return c, nil
}
cursor = c
**(**string)(unsafe.Pointer(&p)) = *(*string)(unsafe.Pointer(&bytes))
return cursor, nil
}
var (
hexToInt = [256]int{
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5,
'6': 6,
'7': 7,
'8': 8,
'9': 9,
'A': 10,
'B': 11,
'C': 12,
'D': 13,
'E': 14,
'F': 15,
'a': 10,
'b': 11,
'c': 12,
'd': 13,
'e': 14,
'f': 15,
}
)
func unicodeToRune(code []byte) rune {
var r rune
for i := 0; i < len(code); i++ {
r = r*16 + rune(hexToInt[code[i]])
}
return r
}
func readAtLeast(s *Stream, n int64, p *unsafe.Pointer) bool {
for s.cursor+n >= s.length {
if !s.read() {
return false
}
*p = s.bufptr()
}
return true
}
func decodeUnicodeRune(s *Stream, p unsafe.Pointer) (rune, int64, unsafe.Pointer, error) {
const defaultOffset = 5
const surrogateOffset = 11
if !readAtLeast(s, defaultOffset, &p) {
return rune(0), 0, nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
}
r := unicodeToRune(s.buf[s.cursor+1 : s.cursor+defaultOffset])
if utf16.IsSurrogate(r) {
if !readAtLeast(s, surrogateOffset, &p) {
return unicode.ReplacementChar, defaultOffset, p, nil
}
if s.buf[s.cursor+defaultOffset] != '\\' || s.buf[s.cursor+defaultOffset+1] != 'u' {
return unicode.ReplacementChar, defaultOffset, p, nil
}
r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
return r, surrogateOffset, p, nil
}
}
return r, defaultOffset, p, nil
}
func decodeUnicode(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
const backSlashAndULen = 2 // length of \u
r, offset, pp, err := decodeUnicodeRune(s, p)
if err != nil {
return nil, err
}
unicode := []byte(string(r))
unicodeLen := int64(len(unicode))
s.buf = append(append(s.buf[:s.cursor-1], unicode...), s.buf[s.cursor+offset:]...)
unicodeOrgLen := offset - 1
s.length = s.length - (backSlashAndULen + (unicodeOrgLen - unicodeLen))
s.cursor = s.cursor - backSlashAndULen + unicodeLen
return pp, nil
}
func decodeEscapeString(s *Stream, p unsafe.Pointer) (unsafe.Pointer, error) {
s.cursor++
RETRY:
switch s.buf[s.cursor] {
case '"':
s.buf[s.cursor] = '"'
case '\\':
s.buf[s.cursor] = '\\'
case '/':
s.buf[s.cursor] = '/'
case 'b':
s.buf[s.cursor] = '\b'
case 'f':
s.buf[s.cursor] = '\f'
case 'n':
s.buf[s.cursor] = '\n'
case 'r':
s.buf[s.cursor] = '\r'
case 't':
s.buf[s.cursor] = '\t'
case 'u':
return decodeUnicode(s, p)
case nul:
if !s.read() {
return nil, errors.ErrInvalidCharacter(s.char(), "escaped string", s.totalOffset())
}
p = s.bufptr()
goto RETRY
default:
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
s.buf = append(s.buf[:s.cursor-1], s.buf[s.cursor:]...)
s.length--
s.cursor--
p = s.bufptr()
return p, nil
}
var (
runeErrBytes = []byte(string(utf8.RuneError))
runeErrBytesLen = int64(len(runeErrBytes))
)
func stringBytes(s *Stream) ([]byte, error) {
_, cursor, p := s.stat()
cursor++ // skip double quote char
start := cursor
for {
switch char(p, cursor) {
case '\\':
s.cursor = cursor
pp, err := decodeEscapeString(s, p)
if err != nil {
return nil, err
}
p = pp
cursor = s.cursor
case '"':
literal := s.buf[start:cursor]
cursor++
s.cursor = cursor
return literal, nil
case
// 0x00 is nul, 0x5c is '\\', 0x22 is '"' .
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 0x00-0x0F
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, // 0x10-0x1F
0x20, 0x21 /*0x22,*/, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, // 0x20-0x2F
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, // 0x30-0x3F
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, // 0x40-0x4F
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B /*0x5C,*/, 0x5D, 0x5E, 0x5F, // 0x50-0x5F
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, // 0x60-0x6F
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F: // 0x70-0x7F
// character is ASCII. skip to next char
case
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, // 0x80-0x8F
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, // 0x90-0x9F
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, // 0xA0-0xAF
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF, // 0xB0-0xBF
0xC0, 0xC1, // 0xC0-0xC1
0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF: // 0xF5-0xFE
// character is invalid
s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...)
_, _, p = s.stat()
cursor += runeErrBytesLen
s.length += runeErrBytesLen
continue
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
goto ERROR
case 0xEF:
// RuneError is {0xEF, 0xBF, 0xBD}
if s.buf[cursor+1] == 0xBF && s.buf[cursor+2] == 0xBD {
// found RuneError: skip
cursor += 2
break
}
fallthrough
default:
// multi bytes character
if !utf8.FullRune(s.buf[cursor : len(s.buf)-1]) {
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
goto ERROR
}
r, size := utf8.DecodeRune(s.buf[cursor:])
if r == utf8.RuneError {
s.buf = append(append(append([]byte{}, s.buf[:cursor]...), runeErrBytes...), s.buf[cursor+1:]...)
cursor += runeErrBytesLen
s.length += runeErrBytesLen
_, _, p = s.stat()
} else {
cursor += int64(size)
}
continue
}
cursor++
}
ERROR:
return nil, errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
func (d *stringDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '[':
return nil, d.errUnmarshalType("array", s.totalOffset())
case '{':
return nil, d.errUnmarshalType("object", s.totalOffset())
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return nil, d.errUnmarshalType("number", s.totalOffset())
case '"':
return stringBytes(s)
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
}
break
}
return nil, errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
}
func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
case '[':
return nil, 0, d.errUnmarshalType("array", cursor)
case '{':
return nil, 0, d.errUnmarshalType("object", cursor)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return nil, 0, d.errUnmarshalType("number", cursor)
case '"':
cursor++
start := cursor
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
escaped := 0
for {
switch char(b, cursor) {
case '\\':
escaped++
cursor++
switch char(b, cursor) {
case '"', '\\', '/', 'b', 'f', 'n', 'r', 't':
cursor++
case 'u':
buflen := int64(len(buf))
if cursor+5 >= buflen {
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
}
for i := int64(1); i <= 4; i++ {
c := char(b, cursor+i)
if !(('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')) {
return nil, 0, errors.ErrSyntax(fmt.Sprintf("json: invalid character %c in \\u hexadecimal character escape", c), cursor+i)
}
}
cursor += 5
default:
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
}
continue
case '"':
literal := buf[start:cursor]
if escaped > 0 {
literal = literal[:unescapeString(literal)]
}
cursor++
return literal, cursor, nil
case nul:
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
cursor++
}
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
}
cursor += 4
return nil, cursor, nil
default:
return nil, 0, errors.ErrInvalidBeginningOfValue(buf[cursor], cursor)
}
}
}
var unescapeMap = [256]byte{
'"': '"',
'\\': '\\',
'/': '/',
'b': '\b',
'f': '\f',
'n': '\n',
'r': '\r',
't': '\t',
}
func unsafeAdd(ptr unsafe.Pointer, offset int) unsafe.Pointer {
return unsafe.Pointer(uintptr(ptr) + uintptr(offset))
}
func unescapeString(buf []byte) int {
p := (*sliceHeader)(unsafe.Pointer(&buf)).data
end := unsafeAdd(p, len(buf))
src := unsafeAdd(p, bytes.IndexByte(buf, '\\'))
dst := src
for src != end {
c := char(src, 0)
if c == '\\' {
escapeChar := char(src, 1)
if escapeChar != 'u' {
*(*byte)(dst) = unescapeMap[escapeChar]
src = unsafeAdd(src, 2)
dst = unsafeAdd(dst, 1)
} else {
v1 := hexToInt[char(src, 2)]
v2 := hexToInt[char(src, 3)]
v3 := hexToInt[char(src, 4)]
v4 := hexToInt[char(src, 5)]
code := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4)
if code >= 0xd800 && code < 0xdc00 && uintptr(unsafeAdd(src, 11)) < uintptr(end) {
if char(src, 6) == '\\' && char(src, 7) == 'u' {
v1 := hexToInt[char(src, 8)]
v2 := hexToInt[char(src, 9)]
v3 := hexToInt[char(src, 10)]
v4 := hexToInt[char(src, 11)]
lo := rune((v1 << 12) | (v2 << 8) | (v3 << 4) | v4)
if lo >= 0xdc00 && lo < 0xe000 {
code = (code-0xd800)<<10 | (lo - 0xdc00) + 0x10000
src = unsafeAdd(src, 6)
}
}
}
var b [utf8.UTFMax]byte
n := utf8.EncodeRune(b[:], code)
switch n {
case 4:
*(*byte)(unsafeAdd(dst, 3)) = b[3]
fallthrough
case 3:
*(*byte)(unsafeAdd(dst, 2)) = b[2]
fallthrough
case 2:
*(*byte)(unsafeAdd(dst, 1)) = b[1]
fallthrough
case 1:
*(*byte)(unsafeAdd(dst, 0)) = b[0]
}
src = unsafeAdd(src, 6)
dst = unsafeAdd(dst, n)
}
} else {
*(*byte)(dst) = c
src = unsafeAdd(src, 1)
dst = unsafeAdd(dst, 1)
}
}
return int(uintptr(dst) - uintptr(p))
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/struct.go
================================================
package decoder
import (
"fmt"
"math"
"math/bits"
"sort"
"strings"
"unicode"
"unicode/utf16"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
type structFieldSet struct {
dec Decoder
offset uintptr
isTaggedKey bool
fieldIdx int
key string
keyLen int64
err error
}
type structDecoder struct {
fieldMap map[string]*structFieldSet
fieldUniqueNameNum int
stringDecoder *stringDecoder
structName string
fieldName string
isTriedOptimize bool
keyBitmapUint8 [][256]uint8
keyBitmapUint16 [][256]uint16
sortedFieldSets []*structFieldSet
keyDecoder func(*structDecoder, []byte, int64) (int64, *structFieldSet, error)
keyStreamDecoder func(*structDecoder, *Stream) (*structFieldSet, string, error)
}
var (
largeToSmallTable [256]byte
)
func init() {
for i := 0; i < 256; i++ {
c := i
if 'A' <= c && c <= 'Z' {
c += 'a' - 'A'
}
largeToSmallTable[i] = byte(c)
}
}
func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder {
return &structDecoder{
fieldMap: fieldMap,
stringDecoder: newStringDecoder(structName, fieldName),
structName: structName,
fieldName: fieldName,
keyDecoder: decodeKey,
keyStreamDecoder: decodeKeyStream,
}
}
const (
allowOptimizeMaxKeyLen = 64
allowOptimizeMaxFieldLen = 16
)
func (d *structDecoder) tryOptimize() {
fieldUniqueNameMap := map[string]int{}
fieldIdx := -1
for k, v := range d.fieldMap {
lower := strings.ToLower(k)
idx, exists := fieldUniqueNameMap[lower]
if exists {
v.fieldIdx = idx
} else {
fieldIdx++
v.fieldIdx = fieldIdx
}
fieldUniqueNameMap[lower] = fieldIdx
}
d.fieldUniqueNameNum = len(fieldUniqueNameMap)
if d.isTriedOptimize {
return
}
fieldMap := map[string]*structFieldSet{}
conflicted := map[string]struct{}{}
for k, v := range d.fieldMap {
key := strings.ToLower(k)
if key != k {
// already exists same key (e.g. Hello and HELLO has same lower case key
if _, exists := conflicted[key]; exists {
d.isTriedOptimize = true
return
}
conflicted[key] = struct{}{}
}
if field, exists := fieldMap[key]; exists {
if field != v {
d.isTriedOptimize = true
return
}
}
fieldMap[key] = v
}
if len(fieldMap) > allowOptimizeMaxFieldLen {
d.isTriedOptimize = true
return
}
var maxKeyLen int
sortedKeys := []string{}
for key := range fieldMap {
keyLen := len(key)
if keyLen > allowOptimizeMaxKeyLen {
d.isTriedOptimize = true
return
}
if maxKeyLen < keyLen {
maxKeyLen = keyLen
}
sortedKeys = append(sortedKeys, key)
}
sort.Strings(sortedKeys)
// By allocating one extra capacity than `maxKeyLen`,
// it is possible to avoid the process of comparing the index of the key with the length of the bitmap each time.
bitmapLen := maxKeyLen + 1
if len(sortedKeys) <= 8 {
keyBitmap := make([][256]uint8, bitmapLen)
for i, key := range sortedKeys {
for j := 0; j < len(key); j++ {
c := key[j]
keyBitmap[j][c] |= (1 << uint(i))
}
d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
}
d.keyBitmapUint8 = keyBitmap
d.keyDecoder = decodeKeyByBitmapUint8
d.keyStreamDecoder = decodeKeyByBitmapUint8Stream
} else {
keyBitmap := make([][256]uint16, bitmapLen)
for i, key := range sortedKeys {
for j := 0; j < len(key); j++ {
c := key[j]
keyBitmap[j][c] |= (1 << uint(i))
}
d.sortedFieldSets = append(d.sortedFieldSets, fieldMap[key])
}
d.keyBitmapUint16 = keyBitmap
d.keyDecoder = decodeKeyByBitmapUint16
d.keyStreamDecoder = decodeKeyByBitmapUint16Stream
}
}
// decode from '\uXXXX'
func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64) {
const defaultOffset = 4
const surrogateOffset = 6
r := unicodeToRune(buf[cursor : cursor+defaultOffset])
if utf16.IsSurrogate(r) {
cursor += defaultOffset
if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' {
return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1
}
cursor += 2
r2 := unicodeToRune(buf[cursor : cursor+defaultOffset])
if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
return []byte(string(r)), cursor + defaultOffset - 1
}
}
return []byte(string(r)), cursor + defaultOffset - 1
}
func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64) {
c := buf[cursor]
cursor++
switch c {
case '"':
return []byte{'"'}, cursor
case '\\':
return []byte{'\\'}, cursor
case '/':
return []byte{'/'}, cursor
case 'b':
return []byte{'\b'}, cursor
case 'f':
return []byte{'\f'}, cursor
case 'n':
return []byte{'\n'}, cursor
case 'r':
return []byte{'\r'}, cursor
case 't':
return []byte{'\t'}, cursor
case 'u':
return decodeKeyCharByUnicodeRune(buf, cursor)
}
return nil, cursor
}
func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
var (
curBit uint8 = math.MaxUint8
)
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case '"':
cursor++
c := char(b, cursor)
switch c {
case '"':
cursor++
return cursor, nil, nil
case nul:
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
keyIdx := 0
bitmap := d.keyBitmapUint8
start := cursor
for {
c := char(b, cursor)
switch c {
case '"':
fieldSetIndex := bits.TrailingZeros8(curBit)
field := d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
if keyLen < field.keyLen {
// early match
return cursor, nil, nil
}
return cursor, field, nil
case nul:
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\':
cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
return decodeKeyNotFound(b, cursor)
}
keyIdx++
}
cursor = nextCursor
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
return decodeKeyNotFound(b, cursor)
}
keyIdx++
}
cursor++
}
default:
return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
}
}
}
func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
var (
curBit uint16 = math.MaxUint16
)
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
for {
switch char(b, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case '"':
cursor++
c := char(b, cursor)
switch c {
case '"':
cursor++
return cursor, nil, nil
case nul:
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
keyIdx := 0
bitmap := d.keyBitmapUint16
start := cursor
for {
c := char(b, cursor)
switch c {
case '"':
fieldSetIndex := bits.TrailingZeros16(curBit)
field := d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
if keyLen < field.keyLen {
// early match
return cursor, nil, nil
}
return cursor, field, nil
case nul:
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\':
cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
return decodeKeyNotFound(b, cursor)
}
keyIdx++
}
cursor = nextCursor
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
return decodeKeyNotFound(b, cursor)
}
keyIdx++
}
cursor++
}
default:
return cursor, nil, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
}
}
}
func decodeKeyNotFound(b unsafe.Pointer, cursor int64) (int64, *structFieldSet, error) {
for {
cursor++
switch char(b, cursor) {
case '"':
cursor++
return cursor, nil, nil
case '\\':
cursor++
if char(b, cursor) == nul {
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
case nul:
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
}
}
}
func decodeKey(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
key, c, err := d.stringDecoder.decodeByte(buf, cursor)
if err != nil {
return 0, nil, err
}
cursor = c
k := *(*string)(unsafe.Pointer(&key))
field, exists := d.fieldMap[k]
if !exists {
return cursor, nil, nil
}
return cursor, field, nil
}
func decodeKeyByBitmapUint8Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var (
curBit uint8 = math.MaxUint8
)
_, cursor, p := s.stat()
for {
switch char(p, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
case '"':
cursor++
FIRST_CHAR:
start := cursor
switch char(p, cursor) {
case '"':
cursor++
s.cursor = cursor
return nil, "", nil
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
goto FIRST_CHAR
}
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
keyIdx := 0
bitmap := d.keyBitmapUint8
for {
c := char(p, cursor)
switch c {
case '"':
fieldSetIndex := bits.TrailingZeros8(curBit)
field := d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
s.cursor = cursor
if keyLen < field.keyLen {
// early match
return nil, field.key, nil
}
return field, field.key, nil
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
case '\\':
s.cursor = cursor + 1 // skip '\' char
chars, err := decodeKeyCharByEscapeCharStream(s)
if err != nil {
return nil, "", err
}
cursor = s.cursor
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
s.cursor = cursor
return decodeKeyNotFoundStream(s, start)
}
keyIdx++
}
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
s.cursor = cursor
return decodeKeyNotFoundStream(s, start)
}
keyIdx++
}
cursor++
}
default:
return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
}
}
}
func decodeKeyByBitmapUint16Stream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
var (
curBit uint16 = math.MaxUint16
)
_, cursor, p := s.stat()
for {
switch char(p, cursor) {
case ' ', '\n', '\t', '\r':
cursor++
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
case '"':
cursor++
FIRST_CHAR:
start := cursor
switch char(p, cursor) {
case '"':
cursor++
s.cursor = cursor
return nil, "", nil
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
goto FIRST_CHAR
}
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
keyIdx := 0
bitmap := d.keyBitmapUint16
for {
c := char(p, cursor)
switch c {
case '"':
fieldSetIndex := bits.TrailingZeros16(curBit)
field := d.sortedFieldSets[fieldSetIndex]
keyLen := cursor - start
cursor++
s.cursor = cursor
if keyLen < field.keyLen {
// early match
return nil, field.key, nil
}
return field, field.key, nil
case nul:
s.cursor = cursor
if s.read() {
_, cursor, p = s.stat()
continue
}
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
case '\\':
s.cursor = cursor + 1 // skip '\' char
chars, err := decodeKeyCharByEscapeCharStream(s)
if err != nil {
return nil, "", err
}
cursor = s.cursor
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
s.cursor = cursor
return decodeKeyNotFoundStream(s, start)
}
keyIdx++
}
default:
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
s.cursor = cursor
return decodeKeyNotFoundStream(s, start)
}
keyIdx++
}
cursor++
}
default:
return nil, "", errors.ErrInvalidBeginningOfValue(char(p, cursor), s.totalOffset())
}
}
}
// decode from '\uXXXX'
func decodeKeyCharByUnicodeRuneStream(s *Stream) ([]byte, error) {
const defaultOffset = 4
const surrogateOffset = 6
if s.cursor+defaultOffset >= s.length {
if !s.read() {
return nil, errors.ErrInvalidCharacter(s.char(), "escaped unicode char", s.totalOffset())
}
}
r := unicodeToRune(s.buf[s.cursor : s.cursor+defaultOffset])
if utf16.IsSurrogate(r) {
s.cursor += defaultOffset
if s.cursor+surrogateOffset >= s.length {
s.read()
}
if s.cursor+surrogateOffset >= s.length || s.buf[s.cursor] != '\\' || s.buf[s.cursor+1] != 'u' {
s.cursor += defaultOffset - 1
return []byte(string(unicode.ReplacementChar)), nil
}
r2 := unicodeToRune(s.buf[s.cursor+defaultOffset+2 : s.cursor+surrogateOffset])
if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
s.cursor += defaultOffset - 1
return []byte(string(r)), nil
}
}
s.cursor += defaultOffset - 1
return []byte(string(r)), nil
}
func decodeKeyCharByEscapeCharStream(s *Stream) ([]byte, error) {
c := s.buf[s.cursor]
s.cursor++
RETRY:
switch c {
case '"':
return []byte{'"'}, nil
case '\\':
return []byte{'\\'}, nil
case '/':
return []byte{'/'}, nil
case 'b':
return []byte{'\b'}, nil
case 'f':
return []byte{'\f'}, nil
case 'n':
return []byte{'\n'}, nil
case 'r':
return []byte{'\r'}, nil
case 't':
return []byte{'\t'}, nil
case 'u':
return decodeKeyCharByUnicodeRuneStream(s)
case nul:
if !s.read() {
return nil, errors.ErrInvalidCharacter(s.char(), "escaped char", s.totalOffset())
}
goto RETRY
default:
return nil, errors.ErrUnexpectedEndOfJSON("struct field", s.totalOffset())
}
}
func decodeKeyNotFoundStream(s *Stream, start int64) (*structFieldSet, string, error) {
buf, cursor, p := s.stat()
for {
cursor++
switch char(p, cursor) {
case '"':
b := buf[start:cursor]
key := *(*string)(unsafe.Pointer(&b))
cursor++
s.cursor = cursor
return nil, key, nil
case '\\':
cursor++
if char(p, cursor) == nul {
s.cursor = cursor
if !s.read() {
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
case nul:
s.cursor = cursor
if !s.read() {
return nil, "", errors.ErrUnexpectedEndOfJSON("string", s.totalOffset())
}
buf, cursor, p = s.statForRetry()
}
}
}
func decodeKeyStream(d *structDecoder, s *Stream) (*structFieldSet, string, error) {
key, err := d.stringDecoder.decodeStreamByte(s)
if err != nil {
return nil, "", err
}
k := *(*string)(unsafe.Pointer(&key))
return d.fieldMap[k], k, nil
}
func (d *structDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
depth++
if depth > maxDecodeNestingDepth {
return errors.ErrExceededMaxDepth(s.char(), s.cursor)
}
c := s.skipWhiteSpace()
switch c {
case 'n':
if err := nullBytes(s); err != nil {
return err
}
return nil
default:
if s.char() != '{' {
return errors.ErrInvalidBeginningOfValue(s.char(), s.totalOffset())
}
}
s.cursor++
if s.skipWhiteSpace() == '}' {
s.cursor++
return nil
}
var (
seenFields map[int]struct{}
seenFieldNum int
)
firstWin := (s.Option.Flags & FirstWinOption) != 0
if firstWin {
seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
}
for {
s.reset()
field, key, err := d.keyStreamDecoder(d, s)
if err != nil {
return err
}
if s.skipWhiteSpace() != ':' {
return errors.ErrExpected("colon after object key", s.totalOffset())
}
s.cursor++
if field != nil {
if field.err != nil {
return field.err
}
if firstWin {
if _, exists := seenFields[field.fieldIdx]; exists {
if err := s.skipValue(depth); err != nil {
return err
}
} else {
if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
return err
}
seenFieldNum++
if d.fieldUniqueNameNum <= seenFieldNum {
return s.skipObject(depth)
}
seenFields[field.fieldIdx] = struct{}{}
}
} else {
if err := field.dec.DecodeStream(s, depth, unsafe.Pointer(uintptr(p)+field.offset)); err != nil {
return err
}
}
} else if s.DisallowUnknownFields {
return fmt.Errorf("json: unknown field %q", key)
} else {
if err := s.skipValue(depth); err != nil {
return err
}
}
c := s.skipWhiteSpace()
if c == '}' {
s.cursor++
return nil
}
if c != ',' {
return errors.ErrExpected("comma after object element", s.totalOffset())
}
s.cursor++
}
}
func (d *structDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
depth++
if depth > maxDecodeNestingDepth {
return 0, errors.ErrExceededMaxDepth(buf[cursor], cursor)
}
buflen := int64(len(buf))
cursor = skipWhiteSpace(buf, cursor)
b := (*sliceHeader)(unsafe.Pointer(&buf)).data
switch char(b, cursor) {
case 'n':
if err := validateNull(buf, cursor); err != nil {
return 0, err
}
cursor += 4
return cursor, nil
case '{':
default:
return 0, errors.ErrInvalidBeginningOfValue(char(b, cursor), cursor)
}
cursor++
cursor = skipWhiteSpace(buf, cursor)
if buf[cursor] == '}' {
cursor++
return cursor, nil
}
var (
seenFields map[int]struct{}
seenFieldNum int
)
firstWin := (ctx.Option.Flags & FirstWinOption) != 0
if firstWin {
seenFields = make(map[int]struct{}, d.fieldUniqueNameNum)
}
for {
c, field, err := d.keyDecoder(d, buf, cursor)
if err != nil {
return 0, err
}
cursor = skipWhiteSpace(buf, c)
if char(b, cursor) != ':' {
return 0, errors.ErrExpected("colon after object key", cursor)
}
cursor++
if cursor >= buflen {
return 0, errors.ErrExpected("object value after colon", cursor)
}
if field != nil {
if field.err != nil {
return 0, field.err
}
if firstWin {
if _, exists := seenFields[field.fieldIdx]; exists {
c, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
cursor = c
} else {
c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
if err != nil {
return 0, err
}
cursor = c
seenFieldNum++
if d.fieldUniqueNameNum <= seenFieldNum {
return skipObject(buf, cursor, depth)
}
seenFields[field.fieldIdx] = struct{}{}
}
} else {
c, err := field.dec.Decode(ctx, cursor, depth, unsafe.Pointer(uintptr(p)+field.offset))
if err != nil {
return 0, err
}
cursor = c
}
} else {
c, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
cursor = c
}
cursor = skipWhiteSpace(buf, cursor)
if char(b, cursor) == '}' {
cursor++
return cursor, nil
}
if char(b, cursor) != ',' {
return 0, errors.ErrExpected("comma after object element", cursor)
}
cursor++
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/type.go
================================================
package decoder
import (
"context"
"encoding"
"encoding/json"
"reflect"
"unsafe"
)
type Decoder interface {
Decode(*RuntimeContext, int64, int64, unsafe.Pointer) (int64, error)
DecodeStream(*Stream, int64, unsafe.Pointer) error
}
const (
nul = '\000'
maxDecodeNestingDepth = 10000
)
type unmarshalerContext interface {
UnmarshalJSON(context.Context, []byte) error
}
var (
unmarshalJSONType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
unmarshalJSONContextType = reflect.TypeOf((*unmarshalerContext)(nil)).Elem()
unmarshalTextType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
)
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/uint.go
================================================
package decoder
import (
"fmt"
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type uintDecoder struct {
typ *runtime.Type
kind reflect.Kind
op func(unsafe.Pointer, uint64)
structName string
fieldName string
}
func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder {
return &uintDecoder{
typ: typ,
kind: typ.Kind(),
op: op,
structName: structName,
fieldName: fieldName,
}
}
func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError {
return &errors.UnmarshalTypeError{
Value: fmt.Sprintf("number %s", string(buf)),
Type: runtime.RType2Type(d.typ),
Offset: offset,
}
}
var (
pow10u64 = [...]uint64{
1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09,
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
}
pow10u64Len = len(pow10u64)
)
func (d *uintDecoder) parseUint(b []byte) (uint64, error) {
maxDigit := len(b)
if maxDigit > pow10u64Len {
return 0, fmt.Errorf("invalid length of number")
}
sum := uint64(0)
for i := 0; i < maxDigit; i++ {
c := uint64(b[i]) - 48
digitValue := pow10u64[maxDigit-i-1]
sum += c * digitValue
}
return sum, nil
}
func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) {
for {
switch s.char() {
case ' ', '\n', '\t', '\r':
s.cursor++
continue
case '0':
s.cursor++
return numZeroBuf, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := s.cursor
for {
s.cursor++
if numTable[s.char()] {
continue
} else if s.char() == nul {
if s.read() {
s.cursor-- // for retry current character
continue
}
}
break
}
num := s.buf[start:s.cursor]
return num, nil
case 'n':
if err := nullBytes(s); err != nil {
return nil, err
}
return nil, nil
case nul:
if s.read() {
continue
}
default:
return nil, d.typeError([]byte{s.char()}, s.totalOffset())
}
break
}
return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset())
}
func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) {
for {
switch buf[cursor] {
case ' ', '\n', '\t', '\r':
cursor++
continue
case '0':
cursor++
return numZeroBuf, cursor, nil
case '1', '2', '3', '4', '5', '6', '7', '8', '9':
start := cursor
cursor++
for numTable[buf[cursor]] {
cursor++
}
num := buf[start:cursor]
return num, cursor, nil
case 'n':
if err := validateNull(buf, cursor); err != nil {
return nil, 0, err
}
cursor += 4
return nil, cursor, nil
default:
return nil, 0, d.typeError([]byte{buf[cursor]}, cursor)
}
}
}
func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.decodeStreamByte(s)
if err != nil {
return err
}
if bytes == nil {
return nil
}
u64, err := d.parseUint(bytes)
if err != nil {
return d.typeError(bytes, s.totalOffset())
}
switch d.kind {
case reflect.Uint8:
if (1 << 8) <= u64 {
return d.typeError(bytes, s.totalOffset())
}
case reflect.Uint16:
if (1 << 16) <= u64 {
return d.typeError(bytes, s.totalOffset())
}
case reflect.Uint32:
if (1 << 32) <= u64 {
return d.typeError(bytes, s.totalOffset())
}
}
d.op(p, u64)
return nil
}
func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.decodeByte(ctx.Buf, cursor)
if err != nil {
return 0, err
}
if bytes == nil {
return c, nil
}
cursor = c
u64, err := d.parseUint(bytes)
if err != nil {
return 0, d.typeError(bytes, cursor)
}
switch d.kind {
case reflect.Uint8:
if (1 << 8) <= u64 {
return 0, d.typeError(bytes, cursor)
}
case reflect.Uint16:
if (1 << 16) <= u64 {
return 0, d.typeError(bytes, cursor)
}
case reflect.Uint32:
if (1 << 32) <= u64 {
return 0, d.typeError(bytes, cursor)
}
}
d.op(p, u64)
return cursor, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/unmarshal_json.go
================================================
package decoder
import (
"context"
"encoding/json"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type unmarshalJSONDecoder struct {
typ *runtime.Type
structName string
fieldName string
}
func newUnmarshalJSONDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
}
}
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) {
case *errors.UnmarshalTypeError:
e.Struct = d.structName
e.Field = d.fieldName
case *errors.SyntaxError:
e.Offset = cursor
}
}
func (d *unmarshalJSONDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace()
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
dst := make([]byte, len(src))
copy(dst, src)
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: p,
}))
switch v := v.(type) {
case unmarshalerContext:
var ctx context.Context
if (s.Option.Flags & ContextOption) != 0 {
ctx = s.Option.Context
} else {
ctx = context.Background()
}
if err := v.UnmarshalJSON(ctx, dst); err != nil {
d.annotateError(s.cursor, err)
return err
}
case json.Unmarshaler:
if err := v.UnmarshalJSON(dst); err != nil {
d.annotateError(s.cursor, err)
return err
}
}
return nil
}
func (d *unmarshalJSONDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
dst := make([]byte, len(src))
copy(dst, src)
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: p,
}))
if (ctx.Option.Flags & ContextOption) != 0 {
if err := v.(unmarshalerContext).UnmarshalJSON(ctx.Option.Context, dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
} else {
if err := v.(json.Unmarshaler).UnmarshalJSON(dst); err != nil {
d.annotateError(cursor, err)
return 0, err
}
}
return end, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/unmarshal_text.go
================================================
package decoder
import (
"bytes"
"encoding"
"unicode"
"unicode/utf16"
"unicode/utf8"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type unmarshalTextDecoder struct {
typ *runtime.Type
structName string
fieldName string
}
func newUnmarshalTextDecoder(typ *runtime.Type, structName, fieldName string) *unmarshalTextDecoder {
return &unmarshalTextDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
}
}
func (d *unmarshalTextDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) {
case *errors.UnmarshalTypeError:
e.Struct = d.structName
e.Field = d.fieldName
case *errors.SyntaxError:
e.Offset = cursor
}
}
var (
nullbytes = []byte(`null`)
)
func (d *unmarshalTextDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
s.skipWhiteSpace()
start := s.cursor
if err := s.skipValue(depth); err != nil {
return err
}
src := s.buf[start:s.cursor]
if len(src) > 0 {
switch src[0] {
case '[':
return &errors.UnmarshalTypeError{
Value: "array",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case '{':
return &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return &errors.UnmarshalTypeError{
Value: "number",
Type: runtime.RType2Type(d.typ),
Offset: s.totalOffset(),
}
case 'n':
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return nil
}
}
}
dst := make([]byte, len(src))
copy(dst, src)
if b, ok := unquoteBytes(dst); ok {
dst = b
}
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: p,
}))
if err := v.(encoding.TextUnmarshaler).UnmarshalText(dst); err != nil {
d.annotateError(s.cursor, err)
return err
}
return nil
}
func (d *unmarshalTextDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
buf := ctx.Buf
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor, depth)
if err != nil {
return 0, err
}
src := buf[start:end]
if len(src) > 0 {
switch src[0] {
case '[':
return 0, &errors.UnmarshalTypeError{
Value: "array",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case '{':
return 0, &errors.UnmarshalTypeError{
Value: "object",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return 0, &errors.UnmarshalTypeError{
Value: "number",
Type: runtime.RType2Type(d.typ),
Offset: start,
}
case 'n':
if bytes.Equal(src, nullbytes) {
*(*unsafe.Pointer)(p) = nil
return end, nil
}
}
}
if s, ok := unquoteBytes(src); ok {
src = s
}
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: d.typ,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
if err := v.(encoding.TextUnmarshaler).UnmarshalText(src); err != nil {
d.annotateError(cursor, err)
return 0, err
}
return end, nil
}
func unquoteBytes(s []byte) (t []byte, ok bool) {
length := len(s)
if length < 2 || s[0] != '"' || s[length-1] != '"' {
return
}
s = s[1 : length-1]
length -= 2
// Check for unusual characters. If there are none,
// then no unquoting is needed, so return a slice of the
// original bytes.
r := 0
for r < length {
c := s[r]
if c == '\\' || c == '"' || c < ' ' {
break
}
if c < utf8.RuneSelf {
r++
continue
}
rr, size := utf8.DecodeRune(s[r:])
if rr == utf8.RuneError && size == 1 {
break
}
r += size
}
if r == length {
return s, true
}
b := make([]byte, length+2*utf8.UTFMax)
w := copy(b, s[0:r])
for r < length {
// Out of room? Can only happen if s is full of
// malformed UTF-8 and we're replacing each
// byte with RuneError.
if w >= len(b)-2*utf8.UTFMax {
nb := make([]byte, (len(b)+utf8.UTFMax)*2)
copy(nb, b[0:w])
b = nb
}
switch c := s[r]; {
case c == '\\':
r++
if r >= length {
return
}
switch s[r] {
default:
return
case '"', '\\', '/', '\'':
b[w] = s[r]
r++
w++
case 'b':
b[w] = '\b'
r++
w++
case 'f':
b[w] = '\f'
r++
w++
case 'n':
b[w] = '\n'
r++
w++
case 'r':
b[w] = '\r'
r++
w++
case 't':
b[w] = '\t'
r++
w++
case 'u':
r--
rr := getu4(s[r:])
if rr < 0 {
return
}
r += 6
if utf16.IsSurrogate(rr) {
rr1 := getu4(s[r:])
if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
// A valid pair; consume.
r += 6
w += utf8.EncodeRune(b[w:], dec)
break
}
// Invalid surrogate; fall back to replacement rune.
rr = unicode.ReplacementChar
}
w += utf8.EncodeRune(b[w:], rr)
}
// Quote, control characters are invalid.
case c == '"', c < ' ':
return
// ASCII
case c < utf8.RuneSelf:
b[w] = c
r++
w++
// Coerce to well-formed UTF-8.
default:
rr, size := utf8.DecodeRune(s[r:])
r += size
w += utf8.EncodeRune(b[w:], rr)
}
}
return b[0:w], true
}
func getu4(s []byte) rune {
if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
return -1
}
var r rune
for _, c := range s[2:6] {
switch {
case '0' <= c && c <= '9':
c = c - '0'
case 'a' <= c && c <= 'f':
c = c - 'a' + 10
case 'A' <= c && c <= 'F':
c = c - 'A' + 10
default:
return -1
}
r = r*16 + rune(c)
}
return r
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/decoder/wrapped_string.go
================================================
package decoder
import (
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type wrappedStringDecoder struct {
typ *runtime.Type
dec Decoder
stringDecoder *stringDecoder
structName string
fieldName string
isPtrType bool
}
func newWrappedStringDecoder(typ *runtime.Type, dec Decoder, structName, fieldName string) *wrappedStringDecoder {
return &wrappedStringDecoder{
typ: typ,
dec: dec,
stringDecoder: newStringDecoder(structName, fieldName),
structName: structName,
fieldName: fieldName,
isPtrType: typ.Kind() == reflect.Ptr,
}
}
func (d *wrappedStringDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error {
bytes, err := d.stringDecoder.decodeStreamByte(s)
if err != nil {
return err
}
if bytes == nil {
if d.isPtrType {
*(*unsafe.Pointer)(p) = nil
}
return nil
}
b := make([]byte, len(bytes)+1)
copy(b, bytes)
if _, err := d.dec.Decode(&RuntimeContext{Buf: b}, 0, depth, p); err != nil {
return err
}
return nil
}
func (d *wrappedStringDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) {
bytes, c, err := d.stringDecoder.decodeByte(ctx.Buf, cursor)
if err != nil {
return 0, err
}
if bytes == nil {
if d.isPtrType {
*(*unsafe.Pointer)(p) = nil
}
return c, nil
}
bytes = append(bytes, nul)
oldBuf := ctx.Buf
ctx.Buf = bytes
if _, err := d.dec.Decode(ctx, 0, depth, p); err != nil {
return 0, err
}
ctx.Buf = oldBuf
return c, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/code.go
================================================
package encoder
import (
"fmt"
"reflect"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type Code interface {
Kind() CodeKind
ToOpcode(*compileContext) Opcodes
Filter(*FieldQuery) Code
}
type AnonymousCode interface {
ToAnonymousOpcode(*compileContext) Opcodes
}
type Opcodes []*Opcode
func (o Opcodes) First() *Opcode {
if len(o) == 0 {
return nil
}
return o[0]
}
func (o Opcodes) Last() *Opcode {
if len(o) == 0 {
return nil
}
return o[len(o)-1]
}
func (o Opcodes) Add(codes ...*Opcode) Opcodes {
return append(o, codes...)
}
type CodeKind int
const (
CodeKindInterface CodeKind = iota
CodeKindPtr
CodeKindInt
CodeKindUint
CodeKindFloat
CodeKindString
CodeKindBool
CodeKindStruct
CodeKindMap
CodeKindSlice
CodeKindArray
CodeKindBytes
CodeKindMarshalJSON
CodeKindMarshalText
CodeKindRecursive
)
type IntCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *IntCode) Kind() CodeKind {
return CodeKindInt
}
func (c *IntCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpIntPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpIntString)
default:
code = newOpCode(ctx, c.typ, OpInt)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
func (c *IntCode) Filter(_ *FieldQuery) Code {
return c
}
type UintCode struct {
typ *runtime.Type
bitSize uint8
isString bool
isPtr bool
}
func (c *UintCode) Kind() CodeKind {
return CodeKindUint
}
func (c *UintCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpUintPtr)
case c.isString:
code = newOpCode(ctx, c.typ, OpUintString)
default:
code = newOpCode(ctx, c.typ, OpUint)
}
code.NumBitSize = c.bitSize
ctx.incIndex()
return Opcodes{code}
}
func (c *UintCode) Filter(_ *FieldQuery) Code {
return c
}
type FloatCode struct {
typ *runtime.Type
bitSize uint8
isPtr bool
}
func (c *FloatCode) Kind() CodeKind {
return CodeKindFloat
}
func (c *FloatCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32Ptr)
default:
code = newOpCode(ctx, c.typ, OpFloat64Ptr)
}
default:
switch c.bitSize {
case 32:
code = newOpCode(ctx, c.typ, OpFloat32)
default:
code = newOpCode(ctx, c.typ, OpFloat64)
}
}
ctx.incIndex()
return Opcodes{code}
}
func (c *FloatCode) Filter(_ *FieldQuery) Code {
return c
}
type StringCode struct {
typ *runtime.Type
isPtr bool
}
func (c *StringCode) Kind() CodeKind {
return CodeKindString
}
func (c *StringCode) ToOpcode(ctx *compileContext) Opcodes {
isJSONNumberType := c.typ == runtime.Type2RType(jsonNumberType)
var code *Opcode
if c.isPtr {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumberPtr)
} else {
code = newOpCode(ctx, c.typ, OpStringPtr)
}
} else {
if isJSONNumberType {
code = newOpCode(ctx, c.typ, OpNumber)
} else {
code = newOpCode(ctx, c.typ, OpString)
}
}
ctx.incIndex()
return Opcodes{code}
}
func (c *StringCode) Filter(_ *FieldQuery) Code {
return c
}
type BoolCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BoolCode) Kind() CodeKind {
return CodeKindBool
}
func (c *BoolCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBoolPtr)
default:
code = newOpCode(ctx, c.typ, OpBool)
}
ctx.incIndex()
return Opcodes{code}
}
func (c *BoolCode) Filter(_ *FieldQuery) Code {
return c
}
type BytesCode struct {
typ *runtime.Type
isPtr bool
}
func (c *BytesCode) Kind() CodeKind {
return CodeKindBytes
}
func (c *BytesCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpBytesPtr)
default:
code = newOpCode(ctx, c.typ, OpBytes)
}
ctx.incIndex()
return Opcodes{code}
}
func (c *BytesCode) Filter(_ *FieldQuery) Code {
return c
}
type SliceCode struct {
typ *runtime.Type
value Code
}
func (c *SliceCode) Kind() CodeKind {
return CodeKindSlice
}
func (c *SliceCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
size := c.typ.Elem().Size()
header := newSliceHeaderCode(ctx, c.typ)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newSliceElemCode(ctx, c.typ.Elem(), header, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpSliceEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
func (c *SliceCode) Filter(_ *FieldQuery) Code {
return c
}
type ArrayCode struct {
typ *runtime.Type
value Code
}
func (c *ArrayCode) Kind() CodeKind {
return CodeKindArray
}
func (c *ArrayCode) ToOpcode(ctx *compileContext) Opcodes {
// header => opcode => elem => end
// ^ |
// |________|
elem := c.typ.Elem()
alen := c.typ.Len()
size := elem.Size()
header := newArrayHeaderCode(ctx, c.typ, alen)
ctx.incIndex()
ctx.incIndent()
codes := c.value.ToOpcode(ctx)
ctx.decIndent()
codes.First().Flags |= IndirectFlags
elemCode := newArrayElemCode(ctx, elem, header, alen, size)
ctx.incIndex()
end := newOpCode(ctx, c.typ, OpArrayEnd)
ctx.incIndex()
header.End = end
header.Next = codes.First()
codes.Last().Next = elemCode
elemCode.Next = codes.First()
elemCode.End = end
return Opcodes{header}.Add(codes...).Add(elemCode).Add(end)
}
func (c *ArrayCode) Filter(_ *FieldQuery) Code {
return c
}
type MapCode struct {
typ *runtime.Type
key Code
value Code
}
func (c *MapCode) Kind() CodeKind {
return CodeKindMap
}
func (c *MapCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => value => code => key => code => value => code => end
// ^ |
// |_______________________|
header := newMapHeaderCode(ctx, c.typ)
ctx.incIndex()
keyCodes := c.key.ToOpcode(ctx)
value := newMapValueCode(ctx, c.typ.Elem(), header)
ctx.incIndex()
ctx.incIndent()
valueCodes := c.value.ToOpcode(ctx)
ctx.decIndent()
valueCodes.First().Flags |= IndirectFlags
key := newMapKeyCode(ctx, c.typ.Key(), header)
ctx.incIndex()
end := newMapEndCode(ctx, c.typ, header)
ctx.incIndex()
header.Next = keyCodes.First()
keyCodes.Last().Next = value
value.Next = valueCodes.First()
valueCodes.Last().Next = key
key.Next = keyCodes.First()
header.End = end
key.End = end
value.End = end
return Opcodes{header}.Add(keyCodes...).Add(value).Add(valueCodes...).Add(key).Add(end)
}
func (c *MapCode) Filter(_ *FieldQuery) Code {
return c
}
type StructCode struct {
typ *runtime.Type
fields []*StructFieldCode
isPtr bool
disableIndirectConversion bool
isIndirect bool
isRecursive bool
}
func (c *StructCode) Kind() CodeKind {
return CodeKindStruct
}
func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *Opcode {
if isEmbeddedStruct(field) {
return c.lastAnonymousFieldCode(firstField)
}
lastField := firstField
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {
// firstField is special StructHead operation for anonymous structure.
// So, StructHead's next operation is truly struct head operation.
lastField := firstField.Next
for lastField.NextField != nil {
lastField = lastField.NextField
}
return lastField
}
func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
ctx.incIndent()
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
endField := fieldCodes.Last()
if isEmbeddedStruct(field) {
firstField.End = endField
lastField := c.lastAnonymousFieldCode(firstField)
lastField.NextField = endField
}
if len(codes) > 0 {
codes.First().End = endField
} else {
firstField.End = endField
}
codes = codes.Add(fieldCodes...)
break
}
prevField = c.lastFieldCode(field, firstField)
codes = codes.Add(fieldCodes...)
}
if len(codes) == 0 {
head := &Opcode{
Op: OpStructHead,
Idx: opcodeOffset(ctx.ptrIndex),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
ctx.incOpcodeIndex()
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
head.NextField = end
head.Next = end
head.End = end
codes = codes.Add(head, end)
ctx.incIndex()
}
ctx.decIndent()
ctx.structTypeToCodes[uintptr(unsafe.Pointer(c.typ))] = codes
return codes
}
func (c *StructCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
// header => code => structField => code => end
// ^ |
// |__________|
if c.isRecursive {
recursive := newRecursiveCode(ctx, c.typ, &CompiledCode{})
recursive.Type = c.typ
ctx.incIndex()
*ctx.recursiveCodes = append(*ctx.recursiveCodes, recursive)
return Opcodes{recursive}
}
codes := Opcodes{}
var prevField *Opcode
for idx, field := range c.fields {
isFirstField := idx == 0
isEndField := idx == len(c.fields)-1
fieldCodes := field.ToAnonymousOpcode(ctx, isFirstField, isEndField)
for _, code := range fieldCodes {
if c.isIndirect {
code.Flags |= IndirectFlags
}
}
firstField := fieldCodes.First()
if len(codes) > 0 {
codes.Last().Next = firstField
firstField.Idx = codes.First().Idx
}
if prevField != nil {
prevField.NextField = firstField
}
if isEndField {
lastField := fieldCodes.Last()
if len(codes) > 0 {
codes.First().End = lastField
} else {
firstField.End = lastField
}
}
prevField = firstField
codes = codes.Add(fieldCodes...)
}
return codes
}
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
fields := make([]*StructFieldCode, 0, len(c.fields))
for _, field := range c.fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil && !structCode.isRecursive {
structCode.removeFieldsByTags(tags)
if len(structCode.fields) > 0 {
fields = append(fields, field)
}
continue
}
}
if tags.ExistsKey(field.key) {
continue
}
fields = append(fields, field)
}
c.fields = fields
}
func (c *StructCode) enableIndirect() {
if c.isIndirect {
return
}
c.isIndirect = true
if len(c.fields) == 0 {
return
}
structCode := c.fields[0].getStruct()
if structCode == nil {
return
}
structCode.enableIndirect()
}
func (c *StructCode) Filter(query *FieldQuery) Code {
fieldMap := map[string]*FieldQuery{}
for _, field := range query.Fields {
fieldMap[field.Name] = field
}
fields := make([]*StructFieldCode, 0, len(c.fields))
for _, field := range c.fields {
query, exists := fieldMap[field.key]
if !exists {
continue
}
fieldCode := &StructFieldCode{
typ: field.typ,
key: field.key,
tag: field.tag,
value: field.value,
offset: field.offset,
isAnonymous: field.isAnonymous,
isTaggedKey: field.isTaggedKey,
isNilableType: field.isNilableType,
isNilCheck: field.isNilCheck,
isAddrForMarshaler: field.isAddrForMarshaler,
isNextOpPtrType: field.isNextOpPtrType,
}
if len(query.Fields) > 0 {
fieldCode.value = fieldCode.value.Filter(query)
}
fields = append(fields, fieldCode)
}
return &StructCode{
typ: c.typ,
fields: fields,
isPtr: c.isPtr,
disableIndirectConversion: c.disableIndirectConversion,
isIndirect: c.isIndirect,
isRecursive: c.isRecursive,
}
}
type StructFieldCode struct {
typ *runtime.Type
key string
tag *runtime.StructTag
value Code
offset uintptr
isAnonymous bool
isTaggedKey bool
isNilableType bool
isNilCheck bool
isAddrForMarshaler bool
isNextOpPtrType bool
isMarshalerContext bool
}
func (c *StructFieldCode) getStruct() *StructCode {
value := c.value
ptr, ok := value.(*PtrCode)
if ok {
value = ptr.value
}
structCode, ok := value.(*StructCode)
if ok {
return structCode
}
return nil
}
func (c *StructFieldCode) getAnonymousStruct() *StructCode {
if !c.isAnonymous {
return nil
}
return c.getStruct()
}
func optimizeStructHeader(code *Opcode, tag *runtime.StructTag) OpType {
headType := code.ToHeaderType(tag.IsString)
if tag.IsOmitEmpty {
headType = headType.HeadToOmitEmptyHead()
}
return headType
}
func optimizeStructField(code *Opcode, tag *runtime.StructTag) OpType {
fieldType := code.ToFieldType(tag.IsString)
if tag.IsOmitEmpty {
fieldType = fieldType.FieldToOmitEmptyField()
}
return fieldType
}
func (c *StructFieldCode) headerOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructHeader(value, c.tag)
field.Op = op
if value.Flags&MarshalerContextFlags != 0 {
field.Flags |= MarshalerContextFlags
}
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
field.FieldQuery = value.FieldQuery
fieldCodes := Opcodes{field}
if op.IsMultipleOpHead() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) fieldOpcodes(ctx *compileContext, field *Opcode, valueCodes Opcodes) Opcodes {
value := valueCodes.First()
op := optimizeStructField(value, c.tag)
field.Op = op
if value.Flags&MarshalerContextFlags != 0 {
field.Flags |= MarshalerContextFlags
}
field.NumBitSize = value.NumBitSize
field.PtrNum = value.PtrNum
field.FieldQuery = value.FieldQuery
fieldCodes := Opcodes{field}
if op.IsMultipleOpField() {
field.Next = value
fieldCodes = fieldCodes.Add(valueCodes...)
} else {
ctx.decIndex()
}
return fieldCodes
}
func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) Opcodes {
end := &Opcode{
Op: OpStructEnd,
Idx: opcodeOffset(ctx.ptrIndex),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
codes.Last().Next = end
codes.First().NextField = end
codes = codes.Add(end)
ctx.incOpcodeIndex()
return codes
}
func (c *StructFieldCode) structKey(ctx *compileContext) string {
if ctx.escapeKey {
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
return fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, c.key)))
}
return fmt.Sprintf(`"%s":`, c.key)
}
func (c *StructFieldCode) flags() OpFlags {
var flags OpFlags
if c.isTaggedKey {
flags |= IsTaggedKeyFlags
}
if c.isNilableType {
flags |= IsNilableTypeFlags
}
if c.isNilCheck {
flags |= NilCheckFlags
}
if c.isAddrForMarshaler {
flags |= AddrForMarshalerFlags
}
if c.isNextOpPtrType {
flags |= IsNextOpPtrTypeFlags
}
if c.isAnonymous {
flags |= AnonymousKeyFlags
}
if c.isMarshalerContext {
flags |= MarshalerContextFlags
}
return flags
}
func (c *StructFieldCode) toValueOpcodes(ctx *compileContext) Opcodes {
if c.isAnonymous {
anonymCode, ok := c.value.(AnonymousCode)
if ok {
return anonymCode.ToAnonymousOpcode(ctx)
}
}
return c.value.ToOpcode(ctx)
}
func (c *StructFieldCode) ToOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags(),
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
codes := c.headerOpcodes(ctx, field, valueCodes)
if isEndField {
codes = c.addStructEndCode(ctx, codes)
}
return codes
}
codes := c.fieldOpcodes(ctx, field, valueCodes)
if isEndField {
if isEnableStructEndOptimization(c.value) {
field.Op = field.Op.FieldToEnd()
} else {
codes = c.addStructEndCode(ctx, codes)
}
}
return codes
}
func (c *StructFieldCode) ToAnonymousOpcode(ctx *compileContext, isFirstField, isEndField bool) Opcodes {
field := &Opcode{
Idx: opcodeOffset(ctx.ptrIndex),
Flags: c.flags() | AnonymousHeadFlags,
Key: c.structKey(ctx),
Offset: uint32(c.offset),
Type: c.typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
DisplayKey: c.key,
}
ctx.incIndex()
valueCodes := c.toValueOpcodes(ctx)
if isFirstField {
return c.headerOpcodes(ctx, field, valueCodes)
}
return c.fieldOpcodes(ctx, field, valueCodes)
}
func isEnableStructEndOptimization(value Code) bool {
switch value.Kind() {
case CodeKindInt,
CodeKindUint,
CodeKindFloat,
CodeKindString,
CodeKindBool,
CodeKindBytes:
return true
case CodeKindPtr:
return isEnableStructEndOptimization(value.(*PtrCode).value)
default:
return false
}
}
type InterfaceCode struct {
typ *runtime.Type
fieldQuery *FieldQuery
isPtr bool
}
func (c *InterfaceCode) Kind() CodeKind {
return CodeKindInterface
}
func (c *InterfaceCode) ToOpcode(ctx *compileContext) Opcodes {
var code *Opcode
switch {
case c.isPtr:
code = newOpCode(ctx, c.typ, OpInterfacePtr)
default:
code = newOpCode(ctx, c.typ, OpInterface)
}
code.FieldQuery = c.fieldQuery
if c.typ.NumMethod() > 0 {
code.Flags |= NonEmptyInterfaceFlags
}
ctx.incIndex()
return Opcodes{code}
}
func (c *InterfaceCode) Filter(query *FieldQuery) Code {
return &InterfaceCode{
typ: c.typ,
fieldQuery: query,
isPtr: c.isPtr,
}
}
type MarshalJSONCode struct {
typ *runtime.Type
fieldQuery *FieldQuery
isAddrForMarshaler bool
isNilableType bool
isMarshalerContext bool
}
func (c *MarshalJSONCode) Kind() CodeKind {
return CodeKindMarshalJSON
}
func (c *MarshalJSONCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalJSON)
code.FieldQuery = c.fieldQuery
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isMarshalerContext {
code.Flags |= MarshalerContextFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
func (c *MarshalJSONCode) Filter(query *FieldQuery) Code {
return &MarshalJSONCode{
typ: c.typ,
fieldQuery: query,
isAddrForMarshaler: c.isAddrForMarshaler,
isNilableType: c.isNilableType,
isMarshalerContext: c.isMarshalerContext,
}
}
type MarshalTextCode struct {
typ *runtime.Type
fieldQuery *FieldQuery
isAddrForMarshaler bool
isNilableType bool
}
func (c *MarshalTextCode) Kind() CodeKind {
return CodeKindMarshalText
}
func (c *MarshalTextCode) ToOpcode(ctx *compileContext) Opcodes {
code := newOpCode(ctx, c.typ, OpMarshalText)
code.FieldQuery = c.fieldQuery
if c.isAddrForMarshaler {
code.Flags |= AddrForMarshalerFlags
}
if c.isNilableType {
code.Flags |= IsNilableTypeFlags
} else {
code.Flags &= ^IsNilableTypeFlags
}
ctx.incIndex()
return Opcodes{code}
}
func (c *MarshalTextCode) Filter(query *FieldQuery) Code {
return &MarshalTextCode{
typ: c.typ,
fieldQuery: query,
isAddrForMarshaler: c.isAddrForMarshaler,
isNilableType: c.isNilableType,
}
}
type PtrCode struct {
typ *runtime.Type
value Code
ptrNum uint8
}
func (c *PtrCode) Kind() CodeKind {
return CodeKindPtr
}
func (c *PtrCode) ToOpcode(ctx *compileContext) Opcodes {
codes := c.value.ToOpcode(ctx)
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func (c *PtrCode) ToAnonymousOpcode(ctx *compileContext) Opcodes {
var codes Opcodes
anonymCode, ok := c.value.(AnonymousCode)
if ok {
codes = anonymCode.ToAnonymousOpcode(ctx)
} else {
codes = c.value.ToOpcode(ctx)
}
codes.First().Op = convertPtrOp(codes.First())
codes.First().PtrNum = c.ptrNum
return codes
}
func (c *PtrCode) Filter(query *FieldQuery) Code {
return &PtrCode{
typ: c.typ,
value: c.value.Filter(query),
ptrNum: c.ptrNum,
}
}
func convertPtrOp(code *Opcode) OpType {
ptrHeadOp := code.Op.HeadToPtrHead()
if code.Op != ptrHeadOp {
if code.PtrNum > 0 {
// ptr field and ptr head
code.PtrNum--
}
return ptrHeadOp
}
switch code.Op {
case OpInt:
return OpIntPtr
case OpUint:
return OpUintPtr
case OpFloat32:
return OpFloat32Ptr
case OpFloat64:
return OpFloat64Ptr
case OpString:
return OpStringPtr
case OpBool:
return OpBoolPtr
case OpBytes:
return OpBytesPtr
case OpNumber:
return OpNumberPtr
case OpArray:
return OpArrayPtr
case OpSlice:
return OpSlicePtr
case OpMap:
return OpMapPtr
case OpMarshalJSON:
return OpMarshalJSONPtr
case OpMarshalText:
return OpMarshalTextPtr
case OpInterface:
return OpInterfacePtr
case OpRecursive:
return OpRecursivePtr
}
return code.Op
}
func isEmbeddedStruct(field *StructFieldCode) bool {
if !field.isAnonymous {
return false
}
t := field.typ
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
return t.Kind() == reflect.Struct
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/compact.go
================================================
package encoder
import (
"bytes"
"fmt"
"strconv"
"unsafe"
"github.com/goccy/go-json/internal/errors"
)
var (
isWhiteSpace = [256]bool{
' ': true,
'\n': true,
'\t': true,
'\r': true,
}
isHTMLEscapeChar = [256]bool{
'<': true,
'>': true,
'&': true,
}
nul = byte('\000')
)
func Compact(buf *bytes.Buffer, src []byte, escape bool) error {
if len(src) == 0 {
return errors.ErrUnexpectedEndOfJSON("", 0)
}
buf.Grow(len(src))
dst := buf.Bytes()
ctx := TakeRuntimeContext()
ctxBuf := ctx.Buf[:0]
ctxBuf = append(append(ctxBuf, src...), nul)
ctx.Buf = ctxBuf
if err := compactAndWrite(buf, dst, ctxBuf, escape); err != nil {
ReleaseRuntimeContext(ctx)
return err
}
ReleaseRuntimeContext(ctx)
return nil
}
func compactAndWrite(buf *bytes.Buffer, dst []byte, src []byte, escape bool) error {
dst, err := compact(dst, src, escape)
if err != nil {
return err
}
if _, err := buf.Write(dst); err != nil {
return err
}
return nil
}
func compact(dst, src []byte, escape bool) ([]byte, error) {
buf, cursor, err := compactValue(dst, src, 0, escape)
if err != nil {
return nil, err
}
if err := validateEndBuf(src, cursor); err != nil {
return nil, err
}
return buf, nil
}
func validateEndBuf(src []byte, cursor int64) error {
for {
switch src[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case nul:
return nil
}
return errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after top-level value", src[cursor]),
cursor+1,
)
}
}
func skipWhiteSpace(buf []byte, cursor int64) int64 {
LOOP:
if isWhiteSpace[buf[cursor]] {
cursor++
goto LOOP
}
return cursor
}
func compactValue(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
for {
switch src[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case '{':
return compactObject(dst, src, cursor, escape)
case '}':
return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor)
case '[':
return compactArray(dst, src, cursor, escape)
case ']':
return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor)
case '"':
return compactString(dst, src, cursor, escape)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return compactNumber(dst, src, cursor)
case 't':
return compactTrue(dst, src, cursor)
case 'f':
return compactFalse(dst, src, cursor)
case 'n':
return compactNull(dst, src, cursor)
default:
return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor)
}
}
}
func compactObject(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
if src[cursor] == '{' {
dst = append(dst, '{')
} else {
return nil, 0, errors.ErrExpected("expected { character for object value", cursor)
}
cursor = skipWhiteSpace(src, cursor+1)
if src[cursor] == '}' {
dst = append(dst, '}')
return dst, cursor + 1, nil
}
var err error
for {
cursor = skipWhiteSpace(src, cursor)
dst, cursor, err = compactString(dst, src, cursor, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
if src[cursor] != ':' {
return nil, 0, errors.ErrExpected("colon after object key", cursor)
}
dst = append(dst, ':')
dst, cursor, err = compactValue(dst, src, cursor+1, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
switch src[cursor] {
case '}':
dst = append(dst, '}')
cursor++
return dst, cursor, nil
case ',':
dst = append(dst, ',')
default:
return nil, 0, errors.ErrExpected("comma after object value", cursor)
}
cursor++
}
}
func compactArray(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
if src[cursor] == '[' {
dst = append(dst, '[')
} else {
return nil, 0, errors.ErrExpected("expected [ character for array value", cursor)
}
cursor = skipWhiteSpace(src, cursor+1)
if src[cursor] == ']' {
dst = append(dst, ']')
return dst, cursor + 1, nil
}
var err error
for {
dst, cursor, err = compactValue(dst, src, cursor, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
switch src[cursor] {
case ']':
dst = append(dst, ']')
cursor++
return dst, cursor, nil
case ',':
dst = append(dst, ',')
default:
return nil, 0, errors.ErrExpected("comma after array value", cursor)
}
cursor++
}
}
func compactString(dst, src []byte, cursor int64, escape bool) ([]byte, int64, error) {
if src[cursor] != '"' {
return nil, 0, errors.ErrInvalidCharacter(src[cursor], "string", cursor)
}
start := cursor
for {
cursor++
c := src[cursor]
if escape {
if isHTMLEscapeChar[c] {
dst = append(dst, src[start:cursor]...)
dst = append(dst, `\u00`...)
dst = append(dst, hex[c>>4], hex[c&0xF])
start = cursor + 1
} else if c == 0xE2 && cursor+2 < int64(len(src)) && src[cursor+1] == 0x80 && src[cursor+2]&^1 == 0xA8 {
dst = append(dst, src[start:cursor]...)
dst = append(dst, `\u202`...)
dst = append(dst, hex[src[cursor+2]&0xF])
cursor += 2
start = cursor + 3
}
}
switch c {
case '\\':
cursor++
if src[cursor] == nul {
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src)))
}
case '"':
cursor++
return append(dst, src[start:cursor]...), cursor, nil
case nul:
return nil, 0, errors.ErrUnexpectedEndOfJSON("string", int64(len(src)))
}
}
}
func compactNumber(dst, src []byte, cursor int64) ([]byte, int64, error) {
start := cursor
for {
cursor++
if floatTable[src[cursor]] {
continue
}
break
}
num := src[start:cursor]
if _, err := strconv.ParseFloat(*(*string)(unsafe.Pointer(&num)), 64); err != nil {
return nil, 0, err
}
dst = append(dst, num...)
return dst, cursor, nil
}
func compactTrue(dst, src []byte, cursor int64) ([]byte, int64, error) {
if cursor+3 >= int64(len(src)) {
return nil, 0, errors.ErrUnexpectedEndOfJSON("true", cursor)
}
if !bytes.Equal(src[cursor:cursor+4], []byte(`true`)) {
return nil, 0, errors.ErrInvalidCharacter(src[cursor], "true", cursor)
}
dst = append(dst, "true"...)
cursor += 4
return dst, cursor, nil
}
func compactFalse(dst, src []byte, cursor int64) ([]byte, int64, error) {
if cursor+4 >= int64(len(src)) {
return nil, 0, errors.ErrUnexpectedEndOfJSON("false", cursor)
}
if !bytes.Equal(src[cursor:cursor+5], []byte(`false`)) {
return nil, 0, errors.ErrInvalidCharacter(src[cursor], "false", cursor)
}
dst = append(dst, "false"...)
cursor += 5
return dst, cursor, nil
}
func compactNull(dst, src []byte, cursor int64) ([]byte, int64, error) {
if cursor+3 >= int64(len(src)) {
return nil, 0, errors.ErrUnexpectedEndOfJSON("null", cursor)
}
if !bytes.Equal(src[cursor:cursor+4], []byte(`null`)) {
return nil, 0, errors.ErrInvalidCharacter(src[cursor], "null", cursor)
}
dst = append(dst, "null"...)
cursor += 4
return dst, cursor, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/compiler.go
================================================
package encoder
import (
"context"
"encoding"
"encoding/json"
"reflect"
"sync/atomic"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
type marshalerContext interface {
MarshalJSON(context.Context) ([]byte, error)
}
var (
marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
marshalJSONContextType = reflect.TypeOf((*marshalerContext)(nil)).Elem()
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
jsonNumberType = reflect.TypeOf(json.Number(""))
cachedOpcodeSets []*OpcodeSet
cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet
typeAddr *runtime.TypeAddr
)
func init() {
typeAddr = runtime.AnalyzeTypeAddr()
if typeAddr == nil {
typeAddr = &runtime.TypeAddr{}
}
cachedOpcodeSets = make([]*OpcodeSet, typeAddr.AddrRange>>typeAddr.AddrShift+1)
}
func loadOpcodeMap() map[uintptr]*OpcodeSet {
p := atomic.LoadPointer(&cachedOpcodeMap)
return *(*map[uintptr]*OpcodeSet)(unsafe.Pointer(&p))
}
func storeOpcodeSet(typ uintptr, set *OpcodeSet, m map[uintptr]*OpcodeSet) {
newOpcodeMap := make(map[uintptr]*OpcodeSet, len(m)+1)
newOpcodeMap[typ] = set
for k, v := range m {
newOpcodeMap[k] = v
}
atomic.StorePointer(&cachedOpcodeMap, *(*unsafe.Pointer)(unsafe.Pointer(&newOpcodeMap)))
}
func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) {
opcodeMap := loadOpcodeMap()
if codeSet, exists := opcodeMap[typeptr]; exists {
return codeSet, nil
}
codeSet, err := newCompiler().compile(typeptr)
if err != nil {
return nil, err
}
storeOpcodeSet(typeptr, codeSet, opcodeMap)
return codeSet, nil
}
func getFilteredCodeSetIfNeeded(ctx *RuntimeContext, codeSet *OpcodeSet) (*OpcodeSet, error) {
if (ctx.Option.Flag & ContextOption) == 0 {
return codeSet, nil
}
query := FieldQueryFromContext(ctx.Option.Context)
if query == nil {
return codeSet, nil
}
ctx.Option.Flag |= FieldQueryOption
cacheCodeSet := codeSet.getQueryCache(query.Hash())
if cacheCodeSet != nil {
return cacheCodeSet, nil
}
queryCodeSet, err := newCompiler().codeToOpcodeSet(codeSet.Type, codeSet.Code.Filter(query))
if err != nil {
return nil, err
}
codeSet.setQueryCache(query.Hash(), queryCodeSet)
return queryCodeSet, nil
}
type Compiler struct {
structTypeToCode map[uintptr]*StructCode
}
func newCompiler() *Compiler {
return &Compiler{
structTypeToCode: map[uintptr]*StructCode{},
}
}
func (c *Compiler) compile(typeptr uintptr) (*OpcodeSet, error) {
// noescape trick for header.typ ( reflect.*rtype )
typ := *(**runtime.Type)(unsafe.Pointer(&typeptr))
code, err := c.typeToCode(typ)
if err != nil {
return nil, err
}
return c.codeToOpcodeSet(typ, code)
}
func (c *Compiler) codeToOpcodeSet(typ *runtime.Type, code Code) (*OpcodeSet, error) {
noescapeKeyCode := c.codeToOpcode(&compileContext{
structTypeToCodes: map[uintptr]Opcodes{},
recursiveCodes: &Opcodes{},
}, typ, code)
if err := noescapeKeyCode.Validate(); err != nil {
return nil, err
}
escapeKeyCode := c.codeToOpcode(&compileContext{
structTypeToCodes: map[uintptr]Opcodes{},
recursiveCodes: &Opcodes{},
escapeKey: true,
}, typ, code)
noescapeKeyCode = copyOpcode(noescapeKeyCode)
escapeKeyCode = copyOpcode(escapeKeyCode)
setTotalLengthToInterfaceOp(noescapeKeyCode)
setTotalLengthToInterfaceOp(escapeKeyCode)
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
codeLength := noescapeKeyCode.TotalLength()
return &OpcodeSet{
Type: typ,
NoescapeKeyCode: noescapeKeyCode,
EscapeKeyCode: escapeKeyCode,
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
CodeLength: codeLength,
EndCode: ToEndCode(interfaceNoescapeKeyCode),
Code: code,
QueryCache: map[string]*OpcodeSet{},
}, nil
}
func (c *Compiler) typeToCode(typ *runtime.Type) (Code, error) {
switch {
case c.implementsMarshalJSON(typ):
return c.marshalJSONCode(typ)
case c.implementsMarshalText(typ):
return c.marshalTextCode(typ)
}
isPtr := false
orgType := typ
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
isPtr = true
}
switch {
case c.implementsMarshalJSON(typ):
return c.marshalJSONCode(orgType)
case c.implementsMarshalText(typ):
return c.marshalTextCode(orgType)
}
switch typ.Kind() {
case reflect.Slice:
elem := typ.Elem()
if elem.Kind() == reflect.Uint8 {
p := runtime.PtrTo(elem)
if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
return c.bytesCode(typ, isPtr)
}
}
return c.sliceCode(typ)
case reflect.Map:
if isPtr {
return c.ptrCode(runtime.PtrTo(typ))
}
return c.mapCode(typ)
case reflect.Struct:
return c.structCode(typ, isPtr)
case reflect.Int:
return c.intCode(typ, isPtr)
case reflect.Int8:
return c.int8Code(typ, isPtr)
case reflect.Int16:
return c.int16Code(typ, isPtr)
case reflect.Int32:
return c.int32Code(typ, isPtr)
case reflect.Int64:
return c.int64Code(typ, isPtr)
case reflect.Uint, reflect.Uintptr:
return c.uintCode(typ, isPtr)
case reflect.Uint8:
return c.uint8Code(typ, isPtr)
case reflect.Uint16:
return c.uint16Code(typ, isPtr)
case reflect.Uint32:
return c.uint32Code(typ, isPtr)
case reflect.Uint64:
return c.uint64Code(typ, isPtr)
case reflect.Float32:
return c.float32Code(typ, isPtr)
case reflect.Float64:
return c.float64Code(typ, isPtr)
case reflect.String:
return c.stringCode(typ, isPtr)
case reflect.Bool:
return c.boolCode(typ, isPtr)
case reflect.Interface:
return c.interfaceCode(typ, isPtr)
default:
if isPtr && typ.Implements(marshalTextType) {
typ = orgType
}
return c.typeToCodeWithPtr(typ, isPtr)
}
}
func (c *Compiler) typeToCodeWithPtr(typ *runtime.Type, isPtr bool) (Code, error) {
switch {
case c.implementsMarshalJSON(typ):
return c.marshalJSONCode(typ)
case c.implementsMarshalText(typ):
return c.marshalTextCode(typ)
}
switch typ.Kind() {
case reflect.Ptr:
return c.ptrCode(typ)
case reflect.Slice:
elem := typ.Elem()
if elem.Kind() == reflect.Uint8 {
p := runtime.PtrTo(elem)
if !c.implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
return c.bytesCode(typ, false)
}
}
return c.sliceCode(typ)
case reflect.Array:
return c.arrayCode(typ)
case reflect.Map:
return c.mapCode(typ)
case reflect.Struct:
return c.structCode(typ, isPtr)
case reflect.Interface:
return c.interfaceCode(typ, false)
case reflect.Int:
return c.intCode(typ, false)
case reflect.Int8:
return c.int8Code(typ, false)
case reflect.Int16:
return c.int16Code(typ, false)
case reflect.Int32:
return c.int32Code(typ, false)
case reflect.Int64:
return c.int64Code(typ, false)
case reflect.Uint:
return c.uintCode(typ, false)
case reflect.Uint8:
return c.uint8Code(typ, false)
case reflect.Uint16:
return c.uint16Code(typ, false)
case reflect.Uint32:
return c.uint32Code(typ, false)
case reflect.Uint64:
return c.uint64Code(typ, false)
case reflect.Uintptr:
return c.uintCode(typ, false)
case reflect.Float32:
return c.float32Code(typ, false)
case reflect.Float64:
return c.float64Code(typ, false)
case reflect.String:
return c.stringCode(typ, false)
case reflect.Bool:
return c.boolCode(typ, false)
}
return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)}
}
const intSize = 32 << (^uint(0) >> 63)
//nolint:unparam
func (c *Compiler) intCode(typ *runtime.Type, isPtr bool) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) int8Code(typ *runtime.Type, isPtr bool) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) int16Code(typ *runtime.Type, isPtr bool) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) int32Code(typ *runtime.Type, isPtr bool) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) int64Code(typ *runtime.Type, isPtr bool) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) uintCode(typ *runtime.Type, isPtr bool) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: intSize, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) uint8Code(typ *runtime.Type, isPtr bool) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 8, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) uint16Code(typ *runtime.Type, isPtr bool) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 16, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) uint32Code(typ *runtime.Type, isPtr bool) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) uint64Code(typ *runtime.Type, isPtr bool) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) float32Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) {
return &FloatCode{typ: typ, bitSize: 32, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) float64Code(typ *runtime.Type, isPtr bool) (*FloatCode, error) {
return &FloatCode{typ: typ, bitSize: 64, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) stringCode(typ *runtime.Type, isPtr bool) (*StringCode, error) {
return &StringCode{typ: typ, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) boolCode(typ *runtime.Type, isPtr bool) (*BoolCode, error) {
return &BoolCode{typ: typ, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) intStringCode(typ *runtime.Type) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: intSize, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) int8StringCode(typ *runtime.Type) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 8, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) int16StringCode(typ *runtime.Type) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 16, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) int32StringCode(typ *runtime.Type) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 32, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) int64StringCode(typ *runtime.Type) (*IntCode, error) {
return &IntCode{typ: typ, bitSize: 64, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) uintStringCode(typ *runtime.Type) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: intSize, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) uint8StringCode(typ *runtime.Type) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 8, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) uint16StringCode(typ *runtime.Type) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 16, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) uint32StringCode(typ *runtime.Type) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 32, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) uint64StringCode(typ *runtime.Type) (*UintCode, error) {
return &UintCode{typ: typ, bitSize: 64, isString: true}, nil
}
//nolint:unparam
func (c *Compiler) bytesCode(typ *runtime.Type, isPtr bool) (*BytesCode, error) {
return &BytesCode{typ: typ, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) interfaceCode(typ *runtime.Type, isPtr bool) (*InterfaceCode, error) {
return &InterfaceCode{typ: typ, isPtr: isPtr}, nil
}
//nolint:unparam
func (c *Compiler) marshalJSONCode(typ *runtime.Type) (*MarshalJSONCode, error) {
return &MarshalJSONCode{
typ: typ,
isAddrForMarshaler: c.isPtrMarshalJSONType(typ),
isNilableType: c.isNilableType(typ),
isMarshalerContext: typ.Implements(marshalJSONContextType) || runtime.PtrTo(typ).Implements(marshalJSONContextType),
}, nil
}
//nolint:unparam
func (c *Compiler) marshalTextCode(typ *runtime.Type) (*MarshalTextCode, error) {
return &MarshalTextCode{
typ: typ,
isAddrForMarshaler: c.isPtrMarshalTextType(typ),
isNilableType: c.isNilableType(typ),
}, nil
}
func (c *Compiler) ptrCode(typ *runtime.Type) (*PtrCode, error) {
code, err := c.typeToCodeWithPtr(typ.Elem(), true)
if err != nil {
return nil, err
}
ptr, ok := code.(*PtrCode)
if ok {
return &PtrCode{typ: typ, value: ptr.value, ptrNum: ptr.ptrNum + 1}, nil
}
return &PtrCode{typ: typ, value: code, ptrNum: 1}, nil
}
func (c *Compiler) sliceCode(typ *runtime.Type) (*SliceCode, error) {
elem := typ.Elem()
code, err := c.listElemCode(elem)
if err != nil {
return nil, err
}
if code.Kind() == CodeKindStruct {
structCode := code.(*StructCode)
structCode.enableIndirect()
}
return &SliceCode{typ: typ, value: code}, nil
}
func (c *Compiler) arrayCode(typ *runtime.Type) (*ArrayCode, error) {
elem := typ.Elem()
code, err := c.listElemCode(elem)
if err != nil {
return nil, err
}
if code.Kind() == CodeKindStruct {
structCode := code.(*StructCode)
structCode.enableIndirect()
}
return &ArrayCode{typ: typ, value: code}, nil
}
func (c *Compiler) mapCode(typ *runtime.Type) (*MapCode, error) {
keyCode, err := c.mapKeyCode(typ.Key())
if err != nil {
return nil, err
}
valueCode, err := c.mapValueCode(typ.Elem())
if err != nil {
return nil, err
}
if valueCode.Kind() == CodeKindStruct {
structCode := valueCode.(*StructCode)
structCode.enableIndirect()
}
return &MapCode{typ: typ, key: keyCode, value: valueCode}, nil
}
func (c *Compiler) listElemCode(typ *runtime.Type) (Code, error) {
switch {
case c.isPtrMarshalJSONType(typ):
return c.marshalJSONCode(typ)
case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType):
return c.marshalTextCode(typ)
case typ.Kind() == reflect.Map:
return c.ptrCode(runtime.PtrTo(typ))
default:
// isPtr was originally used to indicate whether the type of top level is pointer.
// However, since the slice/array element is a specification that can get the pointer address, explicitly set isPtr to true.
// See here for related issues: https://github.com/goccy/go-json/issues/370
code, err := c.typeToCodeWithPtr(typ, true)
if err != nil {
return nil, err
}
ptr, ok := code.(*PtrCode)
if ok {
if ptr.value.Kind() == CodeKindMap {
ptr.ptrNum++
}
}
return code, nil
}
}
func (c *Compiler) mapKeyCode(typ *runtime.Type) (Code, error) {
switch {
case c.implementsMarshalJSON(typ):
return c.marshalJSONCode(typ)
case c.implementsMarshalText(typ):
return c.marshalTextCode(typ)
}
switch typ.Kind() {
case reflect.Ptr:
return c.ptrCode(typ)
case reflect.String:
return c.stringCode(typ, false)
case reflect.Int:
return c.intStringCode(typ)
case reflect.Int8:
return c.int8StringCode(typ)
case reflect.Int16:
return c.int16StringCode(typ)
case reflect.Int32:
return c.int32StringCode(typ)
case reflect.Int64:
return c.int64StringCode(typ)
case reflect.Uint:
return c.uintStringCode(typ)
case reflect.Uint8:
return c.uint8StringCode(typ)
case reflect.Uint16:
return c.uint16StringCode(typ)
case reflect.Uint32:
return c.uint32StringCode(typ)
case reflect.Uint64:
return c.uint64StringCode(typ)
case reflect.Uintptr:
return c.uintStringCode(typ)
}
return nil, &errors.UnsupportedTypeError{Type: runtime.RType2Type(typ)}
}
func (c *Compiler) mapValueCode(typ *runtime.Type) (Code, error) {
switch typ.Kind() {
case reflect.Map:
return c.ptrCode(runtime.PtrTo(typ))
default:
code, err := c.typeToCodeWithPtr(typ, false)
if err != nil {
return nil, err
}
ptr, ok := code.(*PtrCode)
if ok {
if ptr.value.Kind() == CodeKindMap {
ptr.ptrNum++
}
}
return code, nil
}
}
func (c *Compiler) structCode(typ *runtime.Type, isPtr bool) (*StructCode, error) {
typeptr := uintptr(unsafe.Pointer(typ))
if code, exists := c.structTypeToCode[typeptr]; exists {
derefCode := *code
derefCode.isRecursive = true
return &derefCode, nil
}
indirect := runtime.IfaceIndir(typ)
code := &StructCode{typ: typ, isPtr: isPtr, isIndirect: indirect}
c.structTypeToCode[typeptr] = code
fieldNum := typ.NumField()
tags := c.typeToStructTags(typ)
fields := []*StructFieldCode{}
for i, tag := range tags {
isOnlyOneFirstField := i == 0 && fieldNum == 1
field, err := c.structFieldCode(code, tag, isPtr, isOnlyOneFirstField)
if err != nil {
return nil, err
}
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil {
structCode.removeFieldsByTags(tags)
if c.isAssignableIndirect(field, isPtr) {
if indirect {
structCode.isIndirect = true
} else {
structCode.isIndirect = false
}
}
}
} else {
structCode := field.getStruct()
if structCode != nil {
if indirect {
// if parent is indirect type, set child indirect property to true
structCode.isIndirect = true
} else {
// if parent is not indirect type, set child indirect property to false.
// but if parent's indirect is false and isPtr is true, then indirect must be true.
// Do this only if indirectConversion is enabled at the end of compileStruct.
structCode.isIndirect = false
}
}
}
fields = append(fields, field)
}
fieldMap := c.getFieldMap(fields)
duplicatedFieldMap := c.getDuplicatedFieldMap(fieldMap)
code.fields = c.filteredDuplicatedFields(fields, duplicatedFieldMap)
if !code.disableIndirectConversion && !indirect && isPtr {
code.enableIndirect()
}
delete(c.structTypeToCode, typeptr)
return code, nil
}
func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTag, isPtr, isOnlyOneFirstField bool) (*StructFieldCode, error) {
field := tag.Field
fieldType := runtime.Type2RType(field.Type)
isIndirectSpecialCase := isPtr && isOnlyOneFirstField
fieldCode := &StructFieldCode{
typ: fieldType,
key: tag.Key,
tag: tag,
offset: field.Offset,
isAnonymous: field.Anonymous && !tag.IsTaggedKey,
isTaggedKey: tag.IsTaggedKey,
isNilableType: c.isNilableType(fieldType),
isNilCheck: true,
}
switch {
case c.isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(fieldType, isIndirectSpecialCase):
code, err := c.marshalJSONCode(fieldType)
if err != nil {
return nil, err
}
fieldCode.value = code
fieldCode.isAddrForMarshaler = true
fieldCode.isNilCheck = false
structCode.isIndirect = false
structCode.disableIndirectConversion = true
case c.isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(fieldType, isIndirectSpecialCase):
code, err := c.marshalTextCode(fieldType)
if err != nil {
return nil, err
}
fieldCode.value = code
fieldCode.isAddrForMarshaler = true
fieldCode.isNilCheck = false
structCode.isIndirect = false
structCode.disableIndirectConversion = true
case isPtr && c.isPtrMarshalJSONType(fieldType):
// *struct{ field T }
// func (*T) MarshalJSON() ([]byte, error)
code, err := c.marshalJSONCode(fieldType)
if err != nil {
return nil, err
}
fieldCode.value = code
fieldCode.isAddrForMarshaler = true
fieldCode.isNilCheck = false
case isPtr && c.isPtrMarshalTextType(fieldType):
// *struct{ field T }
// func (*T) MarshalText() ([]byte, error)
code, err := c.marshalTextCode(fieldType)
if err != nil {
return nil, err
}
fieldCode.value = code
fieldCode.isAddrForMarshaler = true
fieldCode.isNilCheck = false
default:
code, err := c.typeToCodeWithPtr(fieldType, isPtr)
if err != nil {
return nil, err
}
switch code.Kind() {
case CodeKindPtr, CodeKindInterface:
fieldCode.isNextOpPtrType = true
}
fieldCode.value = code
}
return fieldCode, nil
}
func (c *Compiler) isAssignableIndirect(fieldCode *StructFieldCode, isPtr bool) bool {
if isPtr {
return false
}
codeType := fieldCode.value.Kind()
if codeType == CodeKindMarshalJSON {
return false
}
if codeType == CodeKindMarshalText {
return false
}
return true
}
func (c *Compiler) getFieldMap(fields []*StructFieldCode) map[string][]*StructFieldCode {
fieldMap := map[string][]*StructFieldCode{}
for _, field := range fields {
if field.isAnonymous {
for k, v := range c.getAnonymousFieldMap(field) {
fieldMap[k] = append(fieldMap[k], v...)
}
continue
}
fieldMap[field.key] = append(fieldMap[field.key], field)
}
return fieldMap
}
func (c *Compiler) getAnonymousFieldMap(field *StructFieldCode) map[string][]*StructFieldCode {
fieldMap := map[string][]*StructFieldCode{}
structCode := field.getAnonymousStruct()
if structCode == nil || structCode.isRecursive {
fieldMap[field.key] = append(fieldMap[field.key], field)
return fieldMap
}
for k, v := range c.getFieldMapFromAnonymousParent(structCode.fields) {
fieldMap[k] = append(fieldMap[k], v...)
}
return fieldMap
}
func (c *Compiler) getFieldMapFromAnonymousParent(fields []*StructFieldCode) map[string][]*StructFieldCode {
fieldMap := map[string][]*StructFieldCode{}
for _, field := range fields {
if field.isAnonymous {
for k, v := range c.getAnonymousFieldMap(field) {
// Do not handle tagged key when embedding more than once
for _, vv := range v {
vv.isTaggedKey = false
}
fieldMap[k] = append(fieldMap[k], v...)
}
continue
}
fieldMap[field.key] = append(fieldMap[field.key], field)
}
return fieldMap
}
func (c *Compiler) getDuplicatedFieldMap(fieldMap map[string][]*StructFieldCode) map[*StructFieldCode]struct{} {
duplicatedFieldMap := map[*StructFieldCode]struct{}{}
for _, fields := range fieldMap {
if len(fields) == 1 {
continue
}
if c.isTaggedKeyOnly(fields) {
for _, field := range fields {
if field.isTaggedKey {
continue
}
duplicatedFieldMap[field] = struct{}{}
}
} else {
for _, field := range fields {
duplicatedFieldMap[field] = struct{}{}
}
}
}
return duplicatedFieldMap
}
func (c *Compiler) filteredDuplicatedFields(fields []*StructFieldCode, duplicatedFieldMap map[*StructFieldCode]struct{}) []*StructFieldCode {
filteredFields := make([]*StructFieldCode, 0, len(fields))
for _, field := range fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil && !structCode.isRecursive {
structCode.fields = c.filteredDuplicatedFields(structCode.fields, duplicatedFieldMap)
if len(structCode.fields) > 0 {
filteredFields = append(filteredFields, field)
}
continue
}
}
if _, exists := duplicatedFieldMap[field]; exists {
continue
}
filteredFields = append(filteredFields, field)
}
return filteredFields
}
func (c *Compiler) isTaggedKeyOnly(fields []*StructFieldCode) bool {
var taggedKeyFieldCount int
for _, field := range fields {
if field.isTaggedKey {
taggedKeyFieldCount++
}
}
return taggedKeyFieldCount == 1
}
func (c *Compiler) typeToStructTags(typ *runtime.Type) runtime.StructTags {
tags := runtime.StructTags{}
fieldNum := typ.NumField()
for i := 0; i < fieldNum; i++ {
field := typ.Field(i)
if runtime.IsIgnoredStructField(field) {
continue
}
tags = append(tags, runtime.StructTagFromField(field))
}
return tags
}
// *struct{ field T } => struct { field *T }
// func (*T) MarshalJSON() ([]byte, error)
func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalJSONFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool {
return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalJSONType(typ)
}
// *struct{ field T } => struct { field *T }
// func (*T) MarshalText() ([]byte, error)
func (c *Compiler) isMovePointerPositionFromHeadToFirstMarshalTextFieldCase(typ *runtime.Type, isIndirectSpecialCase bool) bool {
return isIndirectSpecialCase && !c.isNilableType(typ) && c.isPtrMarshalTextType(typ)
}
func (c *Compiler) implementsMarshalJSON(typ *runtime.Type) bool {
if !c.implementsMarshalJSONType(typ) {
return false
}
if typ.Kind() != reflect.Ptr {
return true
}
// type kind is reflect.Ptr
if !c.implementsMarshalJSONType(typ.Elem()) {
return true
}
// needs to dereference
return false
}
func (c *Compiler) implementsMarshalText(typ *runtime.Type) bool {
if !typ.Implements(marshalTextType) {
return false
}
if typ.Kind() != reflect.Ptr {
return true
}
// type kind is reflect.Ptr
if !typ.Elem().Implements(marshalTextType) {
return true
}
// needs to dereference
return false
}
func (c *Compiler) isNilableType(typ *runtime.Type) bool {
if !runtime.IfaceIndir(typ) {
return true
}
switch typ.Kind() {
case reflect.Ptr:
return true
case reflect.Map:
return true
case reflect.Func:
return true
default:
return false
}
}
func (c *Compiler) implementsMarshalJSONType(typ *runtime.Type) bool {
return typ.Implements(marshalJSONType) || typ.Implements(marshalJSONContextType)
}
func (c *Compiler) isPtrMarshalJSONType(typ *runtime.Type) bool {
return !c.implementsMarshalJSONType(typ) && c.implementsMarshalJSONType(runtime.PtrTo(typ))
}
func (c *Compiler) isPtrMarshalTextType(typ *runtime.Type) bool {
return !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType)
}
func (c *Compiler) codeToOpcode(ctx *compileContext, typ *runtime.Type, code Code) *Opcode {
codes := code.ToOpcode(ctx)
codes.Last().Next = newEndOp(ctx, typ)
c.linkRecursiveCode(ctx)
return codes.First()
}
func (c *Compiler) linkRecursiveCode(ctx *compileContext) {
recursiveCodes := map[uintptr]*CompiledCode{}
for _, recursive := range *ctx.recursiveCodes {
typeptr := uintptr(unsafe.Pointer(recursive.Type))
codes := ctx.structTypeToCodes[typeptr]
if recursiveCode, ok := recursiveCodes[typeptr]; ok {
*recursive.Jmp = *recursiveCode
continue
}
code := copyOpcode(codes.First())
code.Op = code.Op.PtrHeadToHead()
lastCode := newEndOp(&compileContext{}, recursive.Type)
lastCode.Op = OpRecursiveEnd
// OpRecursiveEnd must set before call TotalLength
code.End.Next = lastCode
totalLength := code.TotalLength()
// Idx, ElemIdx, Length must set after call TotalLength
lastCode.Idx = uint32((totalLength + 1) * uintptrSize)
lastCode.ElemIdx = lastCode.Idx + uintptrSize
lastCode.Length = lastCode.Idx + 2*uintptrSize
// extend length to alloc slot for elemIdx + length
curTotalLength := uintptr(recursive.TotalLength()) + 3
nextTotalLength := uintptr(totalLength) + 3
compiled := recursive.Jmp
compiled.Code = code
compiled.CurLen = curTotalLength
compiled.NextLen = nextTotalLength
compiled.Linked = true
recursiveCodes[typeptr] = compiled
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/compiler_norace.go
================================================
//go:build !race
// +build !race
package encoder
func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr {
codeSet, err := compileToGetCodeSetSlowPath(typeptr)
if err != nil {
return nil, err
}
return getFilteredCodeSetIfNeeded(ctx, codeSet)
}
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
if err != nil {
return nil, err
}
return filtered, nil
}
codeSet, err := newCompiler().compile(typeptr)
if err != nil {
return nil, err
}
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
if err != nil {
return nil, err
}
cachedOpcodeSets[index] = codeSet
return filtered, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/compiler_race.go
================================================
//go:build race
// +build race
package encoder
import (
"sync"
)
var setsMu sync.RWMutex
func CompileToGetCodeSet(ctx *RuntimeContext, typeptr uintptr) (*OpcodeSet, error) {
if typeptr > typeAddr.MaxTypeAddr || typeptr < typeAddr.BaseTypeAddr {
codeSet, err := compileToGetCodeSetSlowPath(typeptr)
if err != nil {
return nil, err
}
return getFilteredCodeSetIfNeeded(ctx, codeSet)
}
index := (typeptr - typeAddr.BaseTypeAddr) >> typeAddr.AddrShift
setsMu.RLock()
if codeSet := cachedOpcodeSets[index]; codeSet != nil {
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
if err != nil {
setsMu.RUnlock()
return nil, err
}
setsMu.RUnlock()
return filtered, nil
}
setsMu.RUnlock()
codeSet, err := newCompiler().compile(typeptr)
if err != nil {
return nil, err
}
filtered, err := getFilteredCodeSetIfNeeded(ctx, codeSet)
if err != nil {
return nil, err
}
setsMu.Lock()
cachedOpcodeSets[index] = codeSet
setsMu.Unlock()
return filtered, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/context.go
================================================
package encoder
import (
"context"
"sync"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
type compileContext struct {
opcodeIndex uint32
ptrIndex int
indent uint32
escapeKey bool
structTypeToCodes map[uintptr]Opcodes
recursiveCodes *Opcodes
}
func (c *compileContext) incIndent() {
c.indent++
}
func (c *compileContext) decIndent() {
c.indent--
}
func (c *compileContext) incIndex() {
c.incOpcodeIndex()
c.incPtrIndex()
}
func (c *compileContext) decIndex() {
c.decOpcodeIndex()
c.decPtrIndex()
}
func (c *compileContext) incOpcodeIndex() {
c.opcodeIndex++
}
func (c *compileContext) decOpcodeIndex() {
c.opcodeIndex--
}
func (c *compileContext) incPtrIndex() {
c.ptrIndex++
}
func (c *compileContext) decPtrIndex() {
c.ptrIndex--
}
const (
bufSize = 1024
)
var (
runtimeContextPool = sync.Pool{
New: func() interface{} {
return &RuntimeContext{
Buf: make([]byte, 0, bufSize),
Ptrs: make([]uintptr, 128),
KeepRefs: make([]unsafe.Pointer, 0, 8),
Option: &Option{},
}
},
}
)
type RuntimeContext struct {
Context context.Context
Buf []byte
MarshalBuf []byte
Ptrs []uintptr
KeepRefs []unsafe.Pointer
SeenPtr []uintptr
BaseIndent uint32
Prefix []byte
IndentStr []byte
Option *Option
}
func (c *RuntimeContext) Init(p uintptr, codelen int) {
if len(c.Ptrs) < codelen {
c.Ptrs = make([]uintptr, codelen)
}
c.Ptrs[0] = p
c.KeepRefs = c.KeepRefs[:0]
c.SeenPtr = c.SeenPtr[:0]
c.BaseIndent = 0
}
func (c *RuntimeContext) Ptr() uintptr {
header := (*runtime.SliceHeader)(unsafe.Pointer(&c.Ptrs))
return uintptr(header.Data)
}
func TakeRuntimeContext() *RuntimeContext {
return runtimeContextPool.Get().(*RuntimeContext)
}
func ReleaseRuntimeContext(ctx *RuntimeContext) {
runtimeContextPool.Put(ctx)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/decode_rune.go
================================================
package encoder
import "unicode/utf8"
const (
// The default lowest and highest continuation byte.
locb = 128 //0b10000000
hicb = 191 //0b10111111
// These names of these constants are chosen to give nice alignment in the
// table below. The first nibble is an index into acceptRanges or F for
// special one-byte cases. The second nibble is the Rune length or the
// Status for the special one-byte case.
xx = 0xF1 // invalid: size 1
as = 0xF0 // ASCII: size 1
s1 = 0x02 // accept 0, size 2
s2 = 0x13 // accept 1, size 3
s3 = 0x03 // accept 0, size 3
s4 = 0x23 // accept 2, size 3
s5 = 0x34 // accept 3, size 4
s6 = 0x04 // accept 0, size 4
s7 = 0x44 // accept 4, size 4
)
// first is information about the first byte in a UTF-8 sequence.
var first = [256]uint8{
// 1 2 3 4 5 6 7 8 9 A B C D E F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
// 1 2 3 4 5 6 7 8 9 A B C D E F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
}
const (
lineSep = byte(168) //'\u2028'
paragraphSep = byte(169) //'\u2029'
)
type decodeRuneState int
const (
validUTF8State decodeRuneState = iota
runeErrorState
lineSepState
paragraphSepState
)
func decodeRuneInString(s string) (decodeRuneState, int) {
n := len(s)
s0 := s[0]
x := first[s0]
if x >= as {
// The following code simulates an additional check for x == xx and
// handling the ASCII and invalid cases accordingly. This mask-and-or
// approach prevents an additional branch.
mask := rune(x) << 31 >> 31 // Create 0x0000 or 0xFFFF.
if rune(s[0])&^mask|utf8.RuneError&mask == utf8.RuneError {
return runeErrorState, 1
}
return validUTF8State, 1
}
sz := int(x & 7)
if n < sz {
return runeErrorState, 1
}
s1 := s[1]
switch x >> 4 {
case 0:
if s1 < locb || hicb < s1 {
return runeErrorState, 1
}
case 1:
if s1 < 0xA0 || hicb < s1 {
return runeErrorState, 1
}
case 2:
if s1 < locb || 0x9F < s1 {
return runeErrorState, 1
}
case 3:
if s1 < 0x90 || hicb < s1 {
return runeErrorState, 1
}
case 4:
if s1 < locb || 0x8F < s1 {
return runeErrorState, 1
}
}
if sz <= 2 {
return validUTF8State, 2
}
s2 := s[2]
if s2 < locb || hicb < s2 {
return runeErrorState, 1
}
if sz <= 3 {
// separator character prefixes: [2]byte{226, 128}
if s0 == 226 && s1 == 128 {
switch s2 {
case lineSep:
return lineSepState, 3
case paragraphSep:
return paragraphSepState, 3
}
}
return validUTF8State, 3
}
s3 := s[3]
if s3 < locb || hicb < s3 {
return runeErrorState, 1
}
return validUTF8State, 4
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/encoder.go
================================================
package encoder
import (
"bytes"
"encoding"
"encoding/base64"
"encoding/json"
"fmt"
"math"
"reflect"
"strconv"
"strings"
"sync"
"unsafe"
"github.com/goccy/go-json/internal/errors"
"github.com/goccy/go-json/internal/runtime"
)
func (t OpType) IsMultipleOpHead() bool {
switch t {
case OpStructHead:
return true
case OpStructHeadSlice:
return true
case OpStructHeadArray:
return true
case OpStructHeadMap:
return true
case OpStructHeadStruct:
return true
case OpStructHeadOmitEmpty:
return true
case OpStructHeadOmitEmptySlice:
return true
case OpStructHeadOmitEmptyArray:
return true
case OpStructHeadOmitEmptyMap:
return true
case OpStructHeadOmitEmptyStruct:
return true
case OpStructHeadSlicePtr:
return true
case OpStructHeadOmitEmptySlicePtr:
return true
case OpStructHeadArrayPtr:
return true
case OpStructHeadOmitEmptyArrayPtr:
return true
case OpStructHeadMapPtr:
return true
case OpStructHeadOmitEmptyMapPtr:
return true
}
return false
}
func (t OpType) IsMultipleOpField() bool {
switch t {
case OpStructField:
return true
case OpStructFieldSlice:
return true
case OpStructFieldArray:
return true
case OpStructFieldMap:
return true
case OpStructFieldStruct:
return true
case OpStructFieldOmitEmpty:
return true
case OpStructFieldOmitEmptySlice:
return true
case OpStructFieldOmitEmptyArray:
return true
case OpStructFieldOmitEmptyMap:
return true
case OpStructFieldOmitEmptyStruct:
return true
case OpStructFieldSlicePtr:
return true
case OpStructFieldOmitEmptySlicePtr:
return true
case OpStructFieldArrayPtr:
return true
case OpStructFieldOmitEmptyArrayPtr:
return true
case OpStructFieldMapPtr:
return true
case OpStructFieldOmitEmptyMapPtr:
return true
}
return false
}
type OpcodeSet struct {
Type *runtime.Type
NoescapeKeyCode *Opcode
EscapeKeyCode *Opcode
InterfaceNoescapeKeyCode *Opcode
InterfaceEscapeKeyCode *Opcode
CodeLength int
EndCode *Opcode
Code Code
QueryCache map[string]*OpcodeSet
cacheMu sync.RWMutex
}
func (s *OpcodeSet) getQueryCache(hash string) *OpcodeSet {
s.cacheMu.RLock()
codeSet := s.QueryCache[hash]
s.cacheMu.RUnlock()
return codeSet
}
func (s *OpcodeSet) setQueryCache(hash string, codeSet *OpcodeSet) {
s.cacheMu.Lock()
s.QueryCache[hash] = codeSet
s.cacheMu.Unlock()
}
type CompiledCode struct {
Code *Opcode
Linked bool // whether recursive code already have linked
CurLen uintptr
NextLen uintptr
}
const StartDetectingCyclesAfter = 1000
func Load(base uintptr, idx uintptr) uintptr {
addr := base + idx
return **(**uintptr)(unsafe.Pointer(&addr))
}
func Store(base uintptr, idx uintptr, p uintptr) {
addr := base + idx
**(**uintptr)(unsafe.Pointer(&addr)) = p
}
func LoadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr {
addr := base + idx
p := **(**uintptr)(unsafe.Pointer(&addr))
if p == 0 {
return 0
}
return PtrToPtr(p)
/*
for i := 0; i < ptrNum; i++ {
if p == 0 {
return p
}
p = PtrToPtr(p)
}
return p
*/
}
func PtrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) }
func PtrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func PtrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func PtrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
func PtrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
func PtrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
func PtrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
func PtrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
func PtrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
}
func PtrToNPtr(p uintptr, ptrNum int) uintptr {
for i := 0; i < ptrNum; i++ {
if p == 0 {
return 0
}
p = PtrToPtr(p)
}
return p
}
func PtrToUnsafePtr(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
func PtrToInterface(code *Opcode, p uintptr) interface{} {
return *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
}
func ErrUnsupportedValue(code *Opcode, ptr uintptr) *errors.UnsupportedValueError {
v := *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&ptr)),
}))
return &errors.UnsupportedValueError{
Value: reflect.ValueOf(v),
Str: fmt.Sprintf("encountered a cycle via %s", code.Type),
}
}
func ErrUnsupportedFloat(v float64) *errors.UnsupportedValueError {
return &errors.UnsupportedValueError{
Value: reflect.ValueOf(v),
Str: strconv.FormatFloat(v, 'g', -1, 64),
}
}
func ErrMarshalerWithCode(code *Opcode, err error) *errors.MarshalerError {
return &errors.MarshalerError{
Type: runtime.RType2Type(code.Type),
Err: err,
}
}
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
type MapItem struct {
Key []byte
Value []byte
}
type Mapslice struct {
Items []MapItem
}
func (m *Mapslice) Len() int {
return len(m.Items)
}
func (m *Mapslice) Less(i, j int) bool {
return bytes.Compare(m.Items[i].Key, m.Items[j].Key) < 0
}
func (m *Mapslice) Swap(i, j int) {
m.Items[i], m.Items[j] = m.Items[j], m.Items[i]
}
//nolint:structcheck,unused
type mapIter struct {
key unsafe.Pointer
elem unsafe.Pointer
t unsafe.Pointer
h unsafe.Pointer
buckets unsafe.Pointer
bptr unsafe.Pointer
overflow unsafe.Pointer
oldoverflow unsafe.Pointer
startBucket uintptr
offset uint8
wrapped bool
B uint8
i uint8
bucket uintptr
checkBucket uintptr
}
type MapContext struct {
Start int
First int
Idx int
Slice *Mapslice
Buf []byte
Len int
Iter mapIter
}
var mapContextPool = sync.Pool{
New: func() interface{} {
return &MapContext{
Slice: &Mapslice{},
}
},
}
func NewMapContext(mapLen int, unorderedMap bool) *MapContext {
ctx := mapContextPool.Get().(*MapContext)
if !unorderedMap {
if len(ctx.Slice.Items) < mapLen {
ctx.Slice.Items = make([]MapItem, mapLen)
} else {
ctx.Slice.Items = ctx.Slice.Items[:mapLen]
}
}
ctx.Buf = ctx.Buf[:0]
ctx.Iter = mapIter{}
ctx.Idx = 0
ctx.Len = mapLen
return ctx
}
func ReleaseMapContext(c *MapContext) {
mapContextPool.Put(c)
}
//go:linkname MapIterInit runtime.mapiterinit
//go:noescape
func MapIterInit(mapType *runtime.Type, m unsafe.Pointer, it *mapIter)
//go:linkname MapIterKey reflect.mapiterkey
//go:noescape
func MapIterKey(it *mapIter) unsafe.Pointer
//go:linkname MapIterNext reflect.mapiternext
//go:noescape
func MapIterNext(it *mapIter)
//go:linkname MapLen reflect.maplen
//go:noescape
func MapLen(m unsafe.Pointer) int
func AppendByteSlice(_ *RuntimeContext, b []byte, src []byte) []byte {
if src == nil {
return append(b, `null`...)
}
encodedLen := base64.StdEncoding.EncodedLen(len(src))
b = append(b, '"')
pos := len(b)
remainLen := cap(b[pos:])
var buf []byte
if remainLen > encodedLen {
buf = b[pos : pos+encodedLen]
} else {
buf = make([]byte, encodedLen)
}
base64.StdEncoding.Encode(buf, src)
return append(append(b, buf...), '"')
}
func AppendFloat32(_ *RuntimeContext, b []byte, v float32) []byte {
f64 := float64(v)
abs := math.Abs(f64)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
f32 := float32(abs)
if f32 < 1e-6 || f32 >= 1e21 {
fmt = 'e'
}
}
return strconv.AppendFloat(b, f64, fmt, -1, 32)
}
func AppendFloat64(_ *RuntimeContext, b []byte, v float64) []byte {
abs := math.Abs(v)
fmt := byte('f')
// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
if abs != 0 {
if abs < 1e-6 || abs >= 1e21 {
fmt = 'e'
}
}
return strconv.AppendFloat(b, v, fmt, -1, 64)
}
func AppendBool(_ *RuntimeContext, b []byte, v bool) []byte {
if v {
return append(b, "true"...)
}
return append(b, "false"...)
}
var (
floatTable = [256]bool{
'0': true,
'1': true,
'2': true,
'3': true,
'4': true,
'5': true,
'6': true,
'7': true,
'8': true,
'9': true,
'.': true,
'e': true,
'E': true,
'+': true,
'-': true,
}
)
func AppendNumber(_ *RuntimeContext, b []byte, n json.Number) ([]byte, error) {
if len(n) == 0 {
return append(b, '0'), nil
}
for i := 0; i < len(n); i++ {
if !floatTable[n[i]] {
return nil, fmt.Errorf("json: invalid number literal %q", n)
}
}
b = append(b, n...)
return b, nil
}
func AppendMarshalJSON(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type
if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() {
rv = rv.Addr()
} else {
newV := reflect.New(rv.Type())
newV.Elem().Set(rv)
rv = newV
}
}
v = rv.Interface()
var bb []byte
if (code.Flags & MarshalerContextFlags) != 0 {
marshaler, ok := v.(marshalerContext)
if !ok {
return AppendNull(ctx, b), nil
}
stdctx := ctx.Option.Context
if ctx.Option.Flag&FieldQueryOption != 0 {
stdctx = SetFieldQueryToContext(stdctx, code.FieldQuery)
}
b, err := marshaler.MarshalJSON(stdctx)
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
bb = b
} else {
marshaler, ok := v.(json.Marshaler)
if !ok {
return AppendNull(ctx, b), nil
}
b, err := marshaler.MarshalJSON()
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
bb = b
}
marshalBuf := ctx.MarshalBuf[:0]
marshalBuf = append(append(marshalBuf, bb...), nul)
compactedBuf, err := compact(b, marshalBuf, (ctx.Option.Flag&HTMLEscapeOption) != 0)
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
ctx.MarshalBuf = marshalBuf
return compactedBuf, nil
}
func AppendMarshalJSONIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type
if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() {
rv = rv.Addr()
} else {
newV := reflect.New(rv.Type())
newV.Elem().Set(rv)
rv = newV
}
}
v = rv.Interface()
var bb []byte
if (code.Flags & MarshalerContextFlags) != 0 {
marshaler, ok := v.(marshalerContext)
if !ok {
return AppendNull(ctx, b), nil
}
b, err := marshaler.MarshalJSON(ctx.Option.Context)
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
bb = b
} else {
marshaler, ok := v.(json.Marshaler)
if !ok {
return AppendNull(ctx, b), nil
}
b, err := marshaler.MarshalJSON()
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
bb = b
}
marshalBuf := ctx.MarshalBuf[:0]
marshalBuf = append(append(marshalBuf, bb...), nul)
indentedBuf, err := doIndent(
b,
marshalBuf,
string(ctx.Prefix)+strings.Repeat(string(ctx.IndentStr), int(ctx.BaseIndent+code.Indent)),
string(ctx.IndentStr),
(ctx.Option.Flag&HTMLEscapeOption) != 0,
)
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
ctx.MarshalBuf = marshalBuf
return indentedBuf, nil
}
func AppendMarshalText(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type
if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() {
rv = rv.Addr()
} else {
newV := reflect.New(rv.Type())
newV.Elem().Set(rv)
rv = newV
}
}
v = rv.Interface()
marshaler, ok := v.(encoding.TextMarshaler)
if !ok {
return AppendNull(ctx, b), nil
}
bytes, err := marshaler.MarshalText()
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
}
func AppendMarshalTextIndent(ctx *RuntimeContext, code *Opcode, b []byte, v interface{}) ([]byte, error) {
rv := reflect.ValueOf(v) // convert by dynamic interface type
if (code.Flags & AddrForMarshalerFlags) != 0 {
if rv.CanAddr() {
rv = rv.Addr()
} else {
newV := reflect.New(rv.Type())
newV.Elem().Set(rv)
rv = newV
}
}
v = rv.Interface()
marshaler, ok := v.(encoding.TextMarshaler)
if !ok {
return AppendNull(ctx, b), nil
}
bytes, err := marshaler.MarshalText()
if err != nil {
return nil, &errors.MarshalerError{Type: reflect.TypeOf(v), Err: err}
}
return AppendString(ctx, b, *(*string)(unsafe.Pointer(&bytes))), nil
}
func AppendNull(_ *RuntimeContext, b []byte) []byte {
return append(b, "null"...)
}
func AppendComma(_ *RuntimeContext, b []byte) []byte {
return append(b, ',')
}
func AppendCommaIndent(_ *RuntimeContext, b []byte) []byte {
return append(b, ',', '\n')
}
func AppendStructEnd(_ *RuntimeContext, b []byte) []byte {
return append(b, '}', ',')
}
func AppendStructEndIndent(ctx *RuntimeContext, code *Opcode, b []byte) []byte {
b = append(b, '\n')
b = append(b, ctx.Prefix...)
indentNum := ctx.BaseIndent + code.Indent - 1
for i := uint32(0); i < indentNum; i++ {
b = append(b, ctx.IndentStr...)
}
return append(b, '}', ',', '\n')
}
func AppendIndent(ctx *RuntimeContext, b []byte, indent uint32) []byte {
b = append(b, ctx.Prefix...)
indentNum := ctx.BaseIndent + indent
for i := uint32(0); i < indentNum; i++ {
b = append(b, ctx.IndentStr...)
}
return b
}
func IsNilForMarshaler(v interface{}) bool {
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Bool:
return !rv.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return rv.Uint() == 0
case reflect.Float32, reflect.Float64:
return math.Float64bits(rv.Float()) == 0
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Func:
return rv.IsNil()
case reflect.Slice:
return rv.IsNil() || rv.Len() == 0
case reflect.String:
return rv.Len() == 0
}
return false
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/indent.go
================================================
package encoder
import (
"bytes"
"fmt"
"github.com/goccy/go-json/internal/errors"
)
func takeIndentSrcRuntimeContext(src []byte) (*RuntimeContext, []byte) {
ctx := TakeRuntimeContext()
buf := ctx.Buf[:0]
buf = append(append(buf, src...), nul)
ctx.Buf = buf
return ctx, buf
}
func Indent(buf *bytes.Buffer, src []byte, prefix, indentStr string) error {
if len(src) == 0 {
return errors.ErrUnexpectedEndOfJSON("", 0)
}
srcCtx, srcBuf := takeIndentSrcRuntimeContext(src)
dstCtx := TakeRuntimeContext()
dst := dstCtx.Buf[:0]
dst, err := indentAndWrite(buf, dst, srcBuf, prefix, indentStr)
if err != nil {
ReleaseRuntimeContext(srcCtx)
ReleaseRuntimeContext(dstCtx)
return err
}
dstCtx.Buf = dst
ReleaseRuntimeContext(srcCtx)
ReleaseRuntimeContext(dstCtx)
return nil
}
func indentAndWrite(buf *bytes.Buffer, dst []byte, src []byte, prefix, indentStr string) ([]byte, error) {
dst, err := doIndent(dst, src, prefix, indentStr, false)
if err != nil {
return nil, err
}
if _, err := buf.Write(dst); err != nil {
return nil, err
}
return dst, nil
}
func doIndent(dst, src []byte, prefix, indentStr string, escape bool) ([]byte, error) {
buf, cursor, err := indentValue(dst, src, 0, 0, []byte(prefix), []byte(indentStr), escape)
if err != nil {
return nil, err
}
if err := validateEndBuf(src, cursor); err != nil {
return nil, err
}
return buf, nil
}
func indentValue(
dst []byte,
src []byte,
indentNum int,
cursor int64,
prefix []byte,
indentBytes []byte,
escape bool) ([]byte, int64, error) {
for {
switch src[cursor] {
case ' ', '\t', '\n', '\r':
cursor++
continue
case '{':
return indentObject(dst, src, indentNum, cursor, prefix, indentBytes, escape)
case '}':
return nil, 0, errors.ErrSyntax("unexpected character '}'", cursor)
case '[':
return indentArray(dst, src, indentNum, cursor, prefix, indentBytes, escape)
case ']':
return nil, 0, errors.ErrSyntax("unexpected character ']'", cursor)
case '"':
return compactString(dst, src, cursor, escape)
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
return compactNumber(dst, src, cursor)
case 't':
return compactTrue(dst, src, cursor)
case 'f':
return compactFalse(dst, src, cursor)
case 'n':
return compactNull(dst, src, cursor)
default:
return nil, 0, errors.ErrSyntax(fmt.Sprintf("unexpected character '%c'", src[cursor]), cursor)
}
}
}
func indentObject(
dst []byte,
src []byte,
indentNum int,
cursor int64,
prefix []byte,
indentBytes []byte,
escape bool) ([]byte, int64, error) {
if src[cursor] == '{' {
dst = append(dst, '{')
} else {
return nil, 0, errors.ErrExpected("expected { character for object value", cursor)
}
cursor = skipWhiteSpace(src, cursor+1)
if src[cursor] == '}' {
dst = append(dst, '}')
return dst, cursor + 1, nil
}
indentNum++
var err error
for {
dst = append(append(dst, '\n'), prefix...)
for i := 0; i < indentNum; i++ {
dst = append(dst, indentBytes...)
}
cursor = skipWhiteSpace(src, cursor)
dst, cursor, err = compactString(dst, src, cursor, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
if src[cursor] != ':' {
return nil, 0, errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after object key", src[cursor]),
cursor+1,
)
}
dst = append(dst, ':', ' ')
dst, cursor, err = indentValue(dst, src, indentNum, cursor+1, prefix, indentBytes, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
switch src[cursor] {
case '}':
dst = append(append(dst, '\n'), prefix...)
for i := 0; i < indentNum-1; i++ {
dst = append(dst, indentBytes...)
}
dst = append(dst, '}')
cursor++
return dst, cursor, nil
case ',':
dst = append(dst, ',')
default:
return nil, 0, errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after object key:value pair", src[cursor]),
cursor+1,
)
}
cursor++
}
}
func indentArray(
dst []byte,
src []byte,
indentNum int,
cursor int64,
prefix []byte,
indentBytes []byte,
escape bool) ([]byte, int64, error) {
if src[cursor] == '[' {
dst = append(dst, '[')
} else {
return nil, 0, errors.ErrExpected("expected [ character for array value", cursor)
}
cursor = skipWhiteSpace(src, cursor+1)
if src[cursor] == ']' {
dst = append(dst, ']')
return dst, cursor + 1, nil
}
indentNum++
var err error
for {
dst = append(append(dst, '\n'), prefix...)
for i := 0; i < indentNum; i++ {
dst = append(dst, indentBytes...)
}
dst, cursor, err = indentValue(dst, src, indentNum, cursor, prefix, indentBytes, escape)
if err != nil {
return nil, 0, err
}
cursor = skipWhiteSpace(src, cursor)
switch src[cursor] {
case ']':
dst = append(append(dst, '\n'), prefix...)
for i := 0; i < indentNum-1; i++ {
dst = append(dst, indentBytes...)
}
dst = append(dst, ']')
cursor++
return dst, cursor, nil
case ',':
dst = append(dst, ',')
default:
return nil, 0, errors.ErrSyntax(
fmt.Sprintf("invalid character '%c' after array value", src[cursor]),
cursor+1,
)
}
cursor++
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/int.go
================================================
package encoder
import (
"unsafe"
)
var endianness int
func init() {
var b [2]byte
*(*uint16)(unsafe.Pointer(&b)) = uint16(0xABCD)
switch b[0] {
case 0xCD:
endianness = 0 // LE
case 0xAB:
endianness = 1 // BE
default:
panic("could not determine endianness")
}
}
// "00010203...96979899" cast to []uint16
var intLELookup = [100]uint16{
0x3030, 0x3130, 0x3230, 0x3330, 0x3430, 0x3530, 0x3630, 0x3730, 0x3830, 0x3930,
0x3031, 0x3131, 0x3231, 0x3331, 0x3431, 0x3531, 0x3631, 0x3731, 0x3831, 0x3931,
0x3032, 0x3132, 0x3232, 0x3332, 0x3432, 0x3532, 0x3632, 0x3732, 0x3832, 0x3932,
0x3033, 0x3133, 0x3233, 0x3333, 0x3433, 0x3533, 0x3633, 0x3733, 0x3833, 0x3933,
0x3034, 0x3134, 0x3234, 0x3334, 0x3434, 0x3534, 0x3634, 0x3734, 0x3834, 0x3934,
0x3035, 0x3135, 0x3235, 0x3335, 0x3435, 0x3535, 0x3635, 0x3735, 0x3835, 0x3935,
0x3036, 0x3136, 0x3236, 0x3336, 0x3436, 0x3536, 0x3636, 0x3736, 0x3836, 0x3936,
0x3037, 0x3137, 0x3237, 0x3337, 0x3437, 0x3537, 0x3637, 0x3737, 0x3837, 0x3937,
0x3038, 0x3138, 0x3238, 0x3338, 0x3438, 0x3538, 0x3638, 0x3738, 0x3838, 0x3938,
0x3039, 0x3139, 0x3239, 0x3339, 0x3439, 0x3539, 0x3639, 0x3739, 0x3839, 0x3939,
}
var intBELookup = [100]uint16{
0x3030, 0x3031, 0x3032, 0x3033, 0x3034, 0x3035, 0x3036, 0x3037, 0x3038, 0x3039,
0x3130, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, 0x3138, 0x3139,
0x3230, 0x3231, 0x3232, 0x3233, 0x3234, 0x3235, 0x3236, 0x3237, 0x3238, 0x3239,
0x3330, 0x3331, 0x3332, 0x3333, 0x3334, 0x3335, 0x3336, 0x3337, 0x3338, 0x3339,
0x3430, 0x3431, 0x3432, 0x3433, 0x3434, 0x3435, 0x3436, 0x3437, 0x3438, 0x3439,
0x3530, 0x3531, 0x3532, 0x3533, 0x3534, 0x3535, 0x3536, 0x3537, 0x3538, 0x3539,
0x3630, 0x3631, 0x3632, 0x3633, 0x3634, 0x3635, 0x3636, 0x3637, 0x3638, 0x3639,
0x3730, 0x3731, 0x3732, 0x3733, 0x3734, 0x3735, 0x3736, 0x3737, 0x3738, 0x3739,
0x3830, 0x3831, 0x3832, 0x3833, 0x3834, 0x3835, 0x3836, 0x3837, 0x3838, 0x3839,
0x3930, 0x3931, 0x3932, 0x3933, 0x3934, 0x3935, 0x3936, 0x3937, 0x3938, 0x3939,
}
var intLookup = [2]*[100]uint16{&intLELookup, &intBELookup}
func numMask(numBitSize uint8) uint64 {
return 1<>(code.NumBitSize-1))&1 == 1
if !negative {
if n < 10 {
return append(out, byte(n+'0'))
} else if n < 100 {
u := intLELookup[n]
return append(out, byte(u), byte(u>>8))
}
} else {
n = -n & mask
}
lookup := intLookup[endianness]
var b [22]byte
u := (*[11]uint16)(unsafe.Pointer(&b))
i := 11
for n >= 100 {
j := n % 100
n /= 100
i--
u[i] = lookup[j]
}
i--
u[i] = lookup[n]
i *= 2 // convert to byte index
if n < 10 {
i++ // remove leading zero
}
if negative {
i--
b[i] = '-'
}
return append(out, b[i:]...)
}
func AppendUint(_ *RuntimeContext, out []byte, p uintptr, code *Opcode) []byte {
var u64 uint64
switch code.NumBitSize {
case 8:
u64 = (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
u64 = (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
u64 = (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
u64 = **(**uint64)(unsafe.Pointer(&p))
}
mask := numMask(code.NumBitSize)
n := u64 & mask
if n < 10 {
return append(out, byte(n+'0'))
} else if n < 100 {
u := intLELookup[n]
return append(out, byte(u), byte(u>>8))
}
lookup := intLookup[endianness]
var b [22]byte
u := (*[11]uint16)(unsafe.Pointer(&b))
i := 11
for n >= 100 {
j := n % 100
n /= 100
i--
u[i] = lookup[j]
}
i--
u[i] = lookup[n]
i *= 2 // convert to byte index
if n < 10 {
i++ // remove leading zero
}
return append(out, b[i:]...)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/map112.go
================================================
//go:build !go1.13
// +build !go1.13
package encoder
import "unsafe"
//go:linkname MapIterValue reflect.mapitervalue
func MapIterValue(it *mapIter) unsafe.Pointer
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/map113.go
================================================
//go:build go1.13
// +build go1.13
package encoder
import "unsafe"
//go:linkname MapIterValue reflect.mapiterelem
func MapIterValue(it *mapIter) unsafe.Pointer
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/opcode.go
================================================
package encoder
import (
"fmt"
"strings"
"unsafe"
"github.com/goccy/go-json/internal/runtime"
)
const uintptrSize = 4 << (^uintptr(0) >> 63)
type OpFlags uint16
const (
AnonymousHeadFlags OpFlags = 1 << 0
AnonymousKeyFlags OpFlags = 1 << 1
IndirectFlags OpFlags = 1 << 2
IsTaggedKeyFlags OpFlags = 1 << 3
NilCheckFlags OpFlags = 1 << 4
AddrForMarshalerFlags OpFlags = 1 << 5
IsNextOpPtrTypeFlags OpFlags = 1 << 6
IsNilableTypeFlags OpFlags = 1 << 7
MarshalerContextFlags OpFlags = 1 << 8
NonEmptyInterfaceFlags OpFlags = 1 << 9
)
type Opcode struct {
Op OpType // operation type
Idx uint32 // offset to access ptr
Next *Opcode // next opcode
End *Opcode // array/slice/struct/map end
NextField *Opcode // next struct field
Key string // struct field key
Offset uint32 // offset size from struct header
PtrNum uint8 // pointer number: e.g. double pointer is 2.
NumBitSize uint8
Flags OpFlags
Type *runtime.Type // go type
Jmp *CompiledCode // for recursive call
FieldQuery *FieldQuery // field query for Interface / MarshalJSON / MarshalText
ElemIdx uint32 // offset to access array/slice elem
Length uint32 // offset to access slice length or array length
Indent uint32 // indent number
Size uint32 // array/slice elem size
DisplayIdx uint32 // opcode index
DisplayKey string // key text to display
}
func (c *Opcode) Validate() error {
var prevIdx uint32
for code := c; !code.IsEnd(); {
if prevIdx != 0 {
if code.DisplayIdx != prevIdx+1 {
return fmt.Errorf(
"invalid index. previous display index is %d but next is %d. dump = %s",
prevIdx, code.DisplayIdx, c.Dump(),
)
}
}
prevIdx = code.DisplayIdx
code = code.IterNext()
}
return nil
}
func (c *Opcode) IterNext() *Opcode {
if c == nil {
return nil
}
switch c.Op.CodeType() {
case CodeArrayElem, CodeSliceElem, CodeMapKey:
return c.End
default:
return c.Next
}
}
func (c *Opcode) IsEnd() bool {
if c == nil {
return true
}
return c.Op == OpEnd || c.Op == OpInterfaceEnd || c.Op == OpRecursiveEnd
}
func (c *Opcode) MaxIdx() uint32 {
max := uint32(0)
for _, value := range []uint32{
c.Idx,
c.ElemIdx,
c.Length,
c.Size,
} {
if max < value {
max = value
}
}
return max
}
func (c *Opcode) ToHeaderType(isString bool) OpType {
switch c.Op {
case OpInt:
if isString {
return OpStructHeadIntString
}
return OpStructHeadInt
case OpIntPtr:
if isString {
return OpStructHeadIntPtrString
}
return OpStructHeadIntPtr
case OpUint:
if isString {
return OpStructHeadUintString
}
return OpStructHeadUint
case OpUintPtr:
if isString {
return OpStructHeadUintPtrString
}
return OpStructHeadUintPtr
case OpFloat32:
if isString {
return OpStructHeadFloat32String
}
return OpStructHeadFloat32
case OpFloat32Ptr:
if isString {
return OpStructHeadFloat32PtrString
}
return OpStructHeadFloat32Ptr
case OpFloat64:
if isString {
return OpStructHeadFloat64String
}
return OpStructHeadFloat64
case OpFloat64Ptr:
if isString {
return OpStructHeadFloat64PtrString
}
return OpStructHeadFloat64Ptr
case OpString:
if isString {
return OpStructHeadStringString
}
return OpStructHeadString
case OpStringPtr:
if isString {
return OpStructHeadStringPtrString
}
return OpStructHeadStringPtr
case OpNumber:
if isString {
return OpStructHeadNumberString
}
return OpStructHeadNumber
case OpNumberPtr:
if isString {
return OpStructHeadNumberPtrString
}
return OpStructHeadNumberPtr
case OpBool:
if isString {
return OpStructHeadBoolString
}
return OpStructHeadBool
case OpBoolPtr:
if isString {
return OpStructHeadBoolPtrString
}
return OpStructHeadBoolPtr
case OpBytes:
return OpStructHeadBytes
case OpBytesPtr:
return OpStructHeadBytesPtr
case OpMap:
return OpStructHeadMap
case OpMapPtr:
c.Op = OpMap
return OpStructHeadMapPtr
case OpArray:
return OpStructHeadArray
case OpArrayPtr:
c.Op = OpArray
return OpStructHeadArrayPtr
case OpSlice:
return OpStructHeadSlice
case OpSlicePtr:
c.Op = OpSlice
return OpStructHeadSlicePtr
case OpMarshalJSON:
return OpStructHeadMarshalJSON
case OpMarshalJSONPtr:
return OpStructHeadMarshalJSONPtr
case OpMarshalText:
return OpStructHeadMarshalText
case OpMarshalTextPtr:
return OpStructHeadMarshalTextPtr
}
return OpStructHead
}
func (c *Opcode) ToFieldType(isString bool) OpType {
switch c.Op {
case OpInt:
if isString {
return OpStructFieldIntString
}
return OpStructFieldInt
case OpIntPtr:
if isString {
return OpStructFieldIntPtrString
}
return OpStructFieldIntPtr
case OpUint:
if isString {
return OpStructFieldUintString
}
return OpStructFieldUint
case OpUintPtr:
if isString {
return OpStructFieldUintPtrString
}
return OpStructFieldUintPtr
case OpFloat32:
if isString {
return OpStructFieldFloat32String
}
return OpStructFieldFloat32
case OpFloat32Ptr:
if isString {
return OpStructFieldFloat32PtrString
}
return OpStructFieldFloat32Ptr
case OpFloat64:
if isString {
return OpStructFieldFloat64String
}
return OpStructFieldFloat64
case OpFloat64Ptr:
if isString {
return OpStructFieldFloat64PtrString
}
return OpStructFieldFloat64Ptr
case OpString:
if isString {
return OpStructFieldStringString
}
return OpStructFieldString
case OpStringPtr:
if isString {
return OpStructFieldStringPtrString
}
return OpStructFieldStringPtr
case OpNumber:
if isString {
return OpStructFieldNumberString
}
return OpStructFieldNumber
case OpNumberPtr:
if isString {
return OpStructFieldNumberPtrString
}
return OpStructFieldNumberPtr
case OpBool:
if isString {
return OpStructFieldBoolString
}
return OpStructFieldBool
case OpBoolPtr:
if isString {
return OpStructFieldBoolPtrString
}
return OpStructFieldBoolPtr
case OpBytes:
return OpStructFieldBytes
case OpBytesPtr:
return OpStructFieldBytesPtr
case OpMap:
return OpStructFieldMap
case OpMapPtr:
c.Op = OpMap
return OpStructFieldMapPtr
case OpArray:
return OpStructFieldArray
case OpArrayPtr:
c.Op = OpArray
return OpStructFieldArrayPtr
case OpSlice:
return OpStructFieldSlice
case OpSlicePtr:
c.Op = OpSlice
return OpStructFieldSlicePtr
case OpMarshalJSON:
return OpStructFieldMarshalJSON
case OpMarshalJSONPtr:
return OpStructFieldMarshalJSONPtr
case OpMarshalText:
return OpStructFieldMarshalText
case OpMarshalTextPtr:
return OpStructFieldMarshalTextPtr
}
return OpStructField
}
func newOpCode(ctx *compileContext, typ *runtime.Type, op OpType) *Opcode {
return newOpCodeWithNext(ctx, typ, op, newEndOp(ctx, typ))
}
func opcodeOffset(idx int) uint32 {
return uint32(idx) * uintptrSize
}
func getCodeAddrByIdx(head *Opcode, idx uint32) *Opcode {
addr := uintptr(unsafe.Pointer(head)) + uintptr(idx)*unsafe.Sizeof(Opcode{})
return *(**Opcode)(unsafe.Pointer(&addr))
}
func copyOpcode(code *Opcode) *Opcode {
codeNum := ToEndCode(code).DisplayIdx + 1
codeSlice := make([]Opcode, codeNum)
head := (*Opcode)((*runtime.SliceHeader)(unsafe.Pointer(&codeSlice)).Data)
ptr := head
c := code
for {
*ptr = Opcode{
Op: c.Op,
Key: c.Key,
PtrNum: c.PtrNum,
NumBitSize: c.NumBitSize,
Flags: c.Flags,
Idx: c.Idx,
Offset: c.Offset,
Type: c.Type,
FieldQuery: c.FieldQuery,
DisplayIdx: c.DisplayIdx,
DisplayKey: c.DisplayKey,
ElemIdx: c.ElemIdx,
Length: c.Length,
Size: c.Size,
Indent: c.Indent,
Jmp: c.Jmp,
}
if c.End != nil {
ptr.End = getCodeAddrByIdx(head, c.End.DisplayIdx)
}
if c.NextField != nil {
ptr.NextField = getCodeAddrByIdx(head, c.NextField.DisplayIdx)
}
if c.Next != nil {
ptr.Next = getCodeAddrByIdx(head, c.Next.DisplayIdx)
}
if c.IsEnd() {
break
}
ptr = getCodeAddrByIdx(head, c.DisplayIdx+1)
c = c.IterNext()
}
return head
}
func setTotalLengthToInterfaceOp(code *Opcode) {
for c := code; !c.IsEnd(); {
if c.Op == OpInterface || c.Op == OpInterfacePtr {
c.Length = uint32(code.TotalLength())
}
c = c.IterNext()
}
}
func ToEndCode(code *Opcode) *Opcode {
c := code
for !c.IsEnd() {
c = c.IterNext()
}
return c
}
func copyToInterfaceOpcode(code *Opcode) *Opcode {
copied := copyOpcode(code)
c := copied
c = ToEndCode(c)
c.Idx += uintptrSize
c.ElemIdx = c.Idx + uintptrSize
c.Length = c.Idx + 2*uintptrSize
c.Op = OpInterfaceEnd
return copied
}
func newOpCodeWithNext(ctx *compileContext, typ *runtime.Type, op OpType, next *Opcode) *Opcode {
return &Opcode{
Op: op,
Idx: opcodeOffset(ctx.ptrIndex),
Next: next,
Type: typ,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
}
func newEndOp(ctx *compileContext, typ *runtime.Type) *Opcode {
return newOpCodeWithNext(ctx, typ, OpEnd, nil)
}
func (c *Opcode) TotalLength() int {
var idx int
code := c
for !code.IsEnd() {
maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx {
idx = maxIdx
}
if code.Op == OpRecursiveEnd {
break
}
code = code.IterNext()
}
maxIdx := int(code.MaxIdx() / uintptrSize)
if idx < maxIdx {
idx = maxIdx
}
return idx + 1
}
func (c *Opcode) dumpHead(code *Opcode) string {
var length uint32
if code.Op.CodeType() == CodeArrayHead {
length = code.Length
} else {
length = code.Length / uintptrSize
}
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
code.ElemIdx/uintptrSize,
length,
)
}
func (c *Opcode) dumpMapHead(code *Opcode) string {
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
)
}
func (c *Opcode) dumpMapEnd(code *Opcode) string {
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
)
}
func (c *Opcode) dumpElem(code *Opcode) string {
var length uint32
if code.Op.CodeType() == CodeArrayElem {
length = code.Length
} else {
length = code.Length / uintptrSize
}
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d][elemIdx:%d][length:%d][size:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
code.ElemIdx/uintptrSize,
length,
code.Size,
)
}
func (c *Opcode) dumpField(code *Opcode) string {
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d][key:%s][offset:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
code.DisplayKey,
code.Offset,
)
}
func (c *Opcode) dumpKey(code *Opcode) string {
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
)
}
func (c *Opcode) dumpValue(code *Opcode) string {
return fmt.Sprintf(
`[%03d]%s%s ([idx:%d])`,
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
)
}
func (c *Opcode) Dump() string {
codes := []string{}
for code := c; !code.IsEnd(); {
switch code.Op.CodeType() {
case CodeSliceHead:
codes = append(codes, c.dumpHead(code))
code = code.Next
case CodeMapHead:
codes = append(codes, c.dumpMapHead(code))
code = code.Next
case CodeArrayElem, CodeSliceElem:
codes = append(codes, c.dumpElem(code))
code = code.End
case CodeMapKey:
codes = append(codes, c.dumpKey(code))
code = code.End
case CodeMapValue:
codes = append(codes, c.dumpValue(code))
code = code.Next
case CodeMapEnd:
codes = append(codes, c.dumpMapEnd(code))
code = code.Next
case CodeStructField:
codes = append(codes, c.dumpField(code))
code = code.Next
case CodeStructEnd:
codes = append(codes, c.dumpField(code))
code = code.Next
default:
codes = append(codes, fmt.Sprintf(
"[%03d]%s%s ([idx:%d])",
code.DisplayIdx,
strings.Repeat("-", int(code.Indent)),
code.Op,
code.Idx/uintptrSize,
))
code = code.Next
}
}
return strings.Join(codes, "\n")
}
func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex()
length := opcodeOffset(ctx.ptrIndex)
return &Opcode{
Op: OpSlice,
Type: typ,
Idx: idx,
DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx,
Length: length,
Indent: ctx.indent,
}
}
func newSliceElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, size uintptr) *Opcode {
return &Opcode{
Op: OpSliceElem,
Type: typ,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx,
Length: head.Length,
Indent: ctx.indent,
Size: uint32(size),
}
}
func newArrayHeaderCode(ctx *compileContext, typ *runtime.Type, alen int) *Opcode {
idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex()
elemIdx := opcodeOffset(ctx.ptrIndex)
return &Opcode{
Op: OpArray,
Type: typ,
Idx: idx,
DisplayIdx: ctx.opcodeIndex,
ElemIdx: elemIdx,
Indent: ctx.indent,
Length: uint32(alen),
}
}
func newArrayElemCode(ctx *compileContext, typ *runtime.Type, head *Opcode, length int, size uintptr) *Opcode {
return &Opcode{
Op: OpArrayElem,
Type: typ,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex,
ElemIdx: head.ElemIdx,
Length: uint32(length),
Indent: ctx.indent,
Size: uint32(size),
}
}
func newMapHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {
idx := opcodeOffset(ctx.ptrIndex)
ctx.incPtrIndex()
return &Opcode{
Op: OpMap,
Type: typ,
Idx: idx,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
}
func newMapKeyCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{
Op: OpMapKey,
Type: typ,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
}
func newMapValueCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{
Op: OpMapValue,
Type: typ,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
}
}
func newMapEndCode(ctx *compileContext, typ *runtime.Type, head *Opcode) *Opcode {
return &Opcode{
Op: OpMapEnd,
Type: typ,
Idx: head.Idx,
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
Next: newEndOp(ctx, typ),
}
}
func newRecursiveCode(ctx *compileContext, typ *runtime.Type, jmp *CompiledCode) *Opcode {
return &Opcode{
Op: OpRecursive,
Type: typ,
Idx: opcodeOffset(ctx.ptrIndex),
Next: newEndOp(ctx, typ),
DisplayIdx: ctx.opcodeIndex,
Indent: ctx.indent,
Jmp: jmp,
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/option.go
================================================
package encoder
import (
"context"
"io"
)
type OptionFlag uint8
const (
HTMLEscapeOption OptionFlag = 1 << iota
IndentOption
UnorderedMapOption
DebugOption
ColorizeOption
ContextOption
NormalizeUTF8Option
FieldQueryOption
)
type Option struct {
Flag OptionFlag
ColorScheme *ColorScheme
Context context.Context
DebugOut io.Writer
}
type EncodeFormat struct {
Header string
Footer string
}
type EncodeFormatScheme struct {
Int EncodeFormat
Uint EncodeFormat
Float EncodeFormat
Bool EncodeFormat
String EncodeFormat
Binary EncodeFormat
ObjectKey EncodeFormat
Null EncodeFormat
}
type (
ColorScheme = EncodeFormatScheme
ColorFormat = EncodeFormat
)
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/optype.go
================================================
// Code generated by internal/cmd/generator. DO NOT EDIT!
package encoder
import (
"strings"
)
type CodeType int
const (
CodeOp CodeType = 0
CodeArrayHead CodeType = 1
CodeArrayElem CodeType = 2
CodeSliceHead CodeType = 3
CodeSliceElem CodeType = 4
CodeMapHead CodeType = 5
CodeMapKey CodeType = 6
CodeMapValue CodeType = 7
CodeMapEnd CodeType = 8
CodeRecursive CodeType = 9
CodeStructField CodeType = 10
CodeStructEnd CodeType = 11
)
var opTypeStrings = [400]string{
"End",
"Interface",
"Ptr",
"SliceElem",
"SliceEnd",
"ArrayElem",
"ArrayEnd",
"MapKey",
"MapValue",
"MapEnd",
"Recursive",
"RecursivePtr",
"RecursiveEnd",
"InterfaceEnd",
"Int",
"Uint",
"Float32",
"Float64",
"Bool",
"String",
"Bytes",
"Number",
"Array",
"Map",
"Slice",
"Struct",
"MarshalJSON",
"MarshalText",
"IntString",
"UintString",
"Float32String",
"Float64String",
"BoolString",
"StringString",
"NumberString",
"IntPtr",
"UintPtr",
"Float32Ptr",
"Float64Ptr",
"BoolPtr",
"StringPtr",
"BytesPtr",
"NumberPtr",
"ArrayPtr",
"MapPtr",
"SlicePtr",
"MarshalJSONPtr",
"MarshalTextPtr",
"InterfacePtr",
"IntPtrString",
"UintPtrString",
"Float32PtrString",
"Float64PtrString",
"BoolPtrString",
"StringPtrString",
"NumberPtrString",
"StructHeadInt",
"StructHeadOmitEmptyInt",
"StructPtrHeadInt",
"StructPtrHeadOmitEmptyInt",
"StructHeadUint",
"StructHeadOmitEmptyUint",
"StructPtrHeadUint",
"StructPtrHeadOmitEmptyUint",
"StructHeadFloat32",
"StructHeadOmitEmptyFloat32",
"StructPtrHeadFloat32",
"StructPtrHeadOmitEmptyFloat32",
"StructHeadFloat64",
"StructHeadOmitEmptyFloat64",
"StructPtrHeadFloat64",
"StructPtrHeadOmitEmptyFloat64",
"StructHeadBool",
"StructHeadOmitEmptyBool",
"StructPtrHeadBool",
"StructPtrHeadOmitEmptyBool",
"StructHeadString",
"StructHeadOmitEmptyString",
"StructPtrHeadString",
"StructPtrHeadOmitEmptyString",
"StructHeadBytes",
"StructHeadOmitEmptyBytes",
"StructPtrHeadBytes",
"StructPtrHeadOmitEmptyBytes",
"StructHeadNumber",
"StructHeadOmitEmptyNumber",
"StructPtrHeadNumber",
"StructPtrHeadOmitEmptyNumber",
"StructHeadArray",
"StructHeadOmitEmptyArray",
"StructPtrHeadArray",
"StructPtrHeadOmitEmptyArray",
"StructHeadMap",
"StructHeadOmitEmptyMap",
"StructPtrHeadMap",
"StructPtrHeadOmitEmptyMap",
"StructHeadSlice",
"StructHeadOmitEmptySlice",
"StructPtrHeadSlice",
"StructPtrHeadOmitEmptySlice",
"StructHeadStruct",
"StructHeadOmitEmptyStruct",
"StructPtrHeadStruct",
"StructPtrHeadOmitEmptyStruct",
"StructHeadMarshalJSON",
"StructHeadOmitEmptyMarshalJSON",
"StructPtrHeadMarshalJSON",
"StructPtrHeadOmitEmptyMarshalJSON",
"StructHeadMarshalText",
"StructHeadOmitEmptyMarshalText",
"StructPtrHeadMarshalText",
"StructPtrHeadOmitEmptyMarshalText",
"StructHeadIntString",
"StructHeadOmitEmptyIntString",
"StructPtrHeadIntString",
"StructPtrHeadOmitEmptyIntString",
"StructHeadUintString",
"StructHeadOmitEmptyUintString",
"StructPtrHeadUintString",
"StructPtrHeadOmitEmptyUintString",
"StructHeadFloat32String",
"StructHeadOmitEmptyFloat32String",
"StructPtrHeadFloat32String",
"StructPtrHeadOmitEmptyFloat32String",
"StructHeadFloat64String",
"StructHeadOmitEmptyFloat64String",
"StructPtrHeadFloat64String",
"StructPtrHeadOmitEmptyFloat64String",
"StructHeadBoolString",
"StructHeadOmitEmptyBoolString",
"StructPtrHeadBoolString",
"StructPtrHeadOmitEmptyBoolString",
"StructHeadStringString",
"StructHeadOmitEmptyStringString",
"StructPtrHeadStringString",
"StructPtrHeadOmitEmptyStringString",
"StructHeadNumberString",
"StructHeadOmitEmptyNumberString",
"StructPtrHeadNumberString",
"StructPtrHeadOmitEmptyNumberString",
"StructHeadIntPtr",
"StructHeadOmitEmptyIntPtr",
"StructPtrHeadIntPtr",
"StructPtrHeadOmitEmptyIntPtr",
"StructHeadUintPtr",
"StructHeadOmitEmptyUintPtr",
"StructPtrHeadUintPtr",
"StructPtrHeadOmitEmptyUintPtr",
"StructHeadFloat32Ptr",
"StructHeadOmitEmptyFloat32Ptr",
"StructPtrHeadFloat32Ptr",
"StructPtrHeadOmitEmptyFloat32Ptr",
"StructHeadFloat64Ptr",
"StructHeadOmitEmptyFloat64Ptr",
"StructPtrHeadFloat64Ptr",
"StructPtrHeadOmitEmptyFloat64Ptr",
"StructHeadBoolPtr",
"StructHeadOmitEmptyBoolPtr",
"StructPtrHeadBoolPtr",
"StructPtrHeadOmitEmptyBoolPtr",
"StructHeadStringPtr",
"StructHeadOmitEmptyStringPtr",
"StructPtrHeadStringPtr",
"StructPtrHeadOmitEmptyStringPtr",
"StructHeadBytesPtr",
"StructHeadOmitEmptyBytesPtr",
"StructPtrHeadBytesPtr",
"StructPtrHeadOmitEmptyBytesPtr",
"StructHeadNumberPtr",
"StructHeadOmitEmptyNumberPtr",
"StructPtrHeadNumberPtr",
"StructPtrHeadOmitEmptyNumberPtr",
"StructHeadArrayPtr",
"StructHeadOmitEmptyArrayPtr",
"StructPtrHeadArrayPtr",
"StructPtrHeadOmitEmptyArrayPtr",
"StructHeadMapPtr",
"StructHeadOmitEmptyMapPtr",
"StructPtrHeadMapPtr",
"StructPtrHeadOmitEmptyMapPtr",
"StructHeadSlicePtr",
"StructHeadOmitEmptySlicePtr",
"StructPtrHeadSlicePtr",
"StructPtrHeadOmitEmptySlicePtr",
"StructHeadMarshalJSONPtr",
"StructHeadOmitEmptyMarshalJSONPtr",
"StructPtrHeadMarshalJSONPtr",
"StructPtrHeadOmitEmptyMarshalJSONPtr",
"StructHeadMarshalTextPtr",
"StructHeadOmitEmptyMarshalTextPtr",
"StructPtrHeadMarshalTextPtr",
"StructPtrHeadOmitEmptyMarshalTextPtr",
"StructHeadInterfacePtr",
"StructHeadOmitEmptyInterfacePtr",
"StructPtrHeadInterfacePtr",
"StructPtrHeadOmitEmptyInterfacePtr",
"StructHeadIntPtrString",
"StructHeadOmitEmptyIntPtrString",
"StructPtrHeadIntPtrString",
"StructPtrHeadOmitEmptyIntPtrString",
"StructHeadUintPtrString",
"StructHeadOmitEmptyUintPtrString",
"StructPtrHeadUintPtrString",
"StructPtrHeadOmitEmptyUintPtrString",
"StructHeadFloat32PtrString",
"StructHeadOmitEmptyFloat32PtrString",
"StructPtrHeadFloat32PtrString",
"StructPtrHeadOmitEmptyFloat32PtrString",
"StructHeadFloat64PtrString",
"StructHeadOmitEmptyFloat64PtrString",
"StructPtrHeadFloat64PtrString",
"StructPtrHeadOmitEmptyFloat64PtrString",
"StructHeadBoolPtrString",
"StructHeadOmitEmptyBoolPtrString",
"StructPtrHeadBoolPtrString",
"StructPtrHeadOmitEmptyBoolPtrString",
"StructHeadStringPtrString",
"StructHeadOmitEmptyStringPtrString",
"StructPtrHeadStringPtrString",
"StructPtrHeadOmitEmptyStringPtrString",
"StructHeadNumberPtrString",
"StructHeadOmitEmptyNumberPtrString",
"StructPtrHeadNumberPtrString",
"StructPtrHeadOmitEmptyNumberPtrString",
"StructHead",
"StructHeadOmitEmpty",
"StructPtrHead",
"StructPtrHeadOmitEmpty",
"StructFieldInt",
"StructFieldOmitEmptyInt",
"StructEndInt",
"StructEndOmitEmptyInt",
"StructFieldUint",
"StructFieldOmitEmptyUint",
"StructEndUint",
"StructEndOmitEmptyUint",
"StructFieldFloat32",
"StructFieldOmitEmptyFloat32",
"StructEndFloat32",
"StructEndOmitEmptyFloat32",
"StructFieldFloat64",
"StructFieldOmitEmptyFloat64",
"StructEndFloat64",
"StructEndOmitEmptyFloat64",
"StructFieldBool",
"StructFieldOmitEmptyBool",
"StructEndBool",
"StructEndOmitEmptyBool",
"StructFieldString",
"StructFieldOmitEmptyString",
"StructEndString",
"StructEndOmitEmptyString",
"StructFieldBytes",
"StructFieldOmitEmptyBytes",
"StructEndBytes",
"StructEndOmitEmptyBytes",
"StructFieldNumber",
"StructFieldOmitEmptyNumber",
"StructEndNumber",
"StructEndOmitEmptyNumber",
"StructFieldArray",
"StructFieldOmitEmptyArray",
"StructEndArray",
"StructEndOmitEmptyArray",
"StructFieldMap",
"StructFieldOmitEmptyMap",
"StructEndMap",
"StructEndOmitEmptyMap",
"StructFieldSlice",
"StructFieldOmitEmptySlice",
"StructEndSlice",
"StructEndOmitEmptySlice",
"StructFieldStruct",
"StructFieldOmitEmptyStruct",
"StructEndStruct",
"StructEndOmitEmptyStruct",
"StructFieldMarshalJSON",
"StructFieldOmitEmptyMarshalJSON",
"StructEndMarshalJSON",
"StructEndOmitEmptyMarshalJSON",
"StructFieldMarshalText",
"StructFieldOmitEmptyMarshalText",
"StructEndMarshalText",
"StructEndOmitEmptyMarshalText",
"StructFieldIntString",
"StructFieldOmitEmptyIntString",
"StructEndIntString",
"StructEndOmitEmptyIntString",
"StructFieldUintString",
"StructFieldOmitEmptyUintString",
"StructEndUintString",
"StructEndOmitEmptyUintString",
"StructFieldFloat32String",
"StructFieldOmitEmptyFloat32String",
"StructEndFloat32String",
"StructEndOmitEmptyFloat32String",
"StructFieldFloat64String",
"StructFieldOmitEmptyFloat64String",
"StructEndFloat64String",
"StructEndOmitEmptyFloat64String",
"StructFieldBoolString",
"StructFieldOmitEmptyBoolString",
"StructEndBoolString",
"StructEndOmitEmptyBoolString",
"StructFieldStringString",
"StructFieldOmitEmptyStringString",
"StructEndStringString",
"StructEndOmitEmptyStringString",
"StructFieldNumberString",
"StructFieldOmitEmptyNumberString",
"StructEndNumberString",
"StructEndOmitEmptyNumberString",
"StructFieldIntPtr",
"StructFieldOmitEmptyIntPtr",
"StructEndIntPtr",
"StructEndOmitEmptyIntPtr",
"StructFieldUintPtr",
"StructFieldOmitEmptyUintPtr",
"StructEndUintPtr",
"StructEndOmitEmptyUintPtr",
"StructFieldFloat32Ptr",
"StructFieldOmitEmptyFloat32Ptr",
"StructEndFloat32Ptr",
"StructEndOmitEmptyFloat32Ptr",
"StructFieldFloat64Ptr",
"StructFieldOmitEmptyFloat64Ptr",
"StructEndFloat64Ptr",
"StructEndOmitEmptyFloat64Ptr",
"StructFieldBoolPtr",
"StructFieldOmitEmptyBoolPtr",
"StructEndBoolPtr",
"StructEndOmitEmptyBoolPtr",
"StructFieldStringPtr",
"StructFieldOmitEmptyStringPtr",
"StructEndStringPtr",
"StructEndOmitEmptyStringPtr",
"StructFieldBytesPtr",
"StructFieldOmitEmptyBytesPtr",
"StructEndBytesPtr",
"StructEndOmitEmptyBytesPtr",
"StructFieldNumberPtr",
"StructFieldOmitEmptyNumberPtr",
"StructEndNumberPtr",
"StructEndOmitEmptyNumberPtr",
"StructFieldArrayPtr",
"StructFieldOmitEmptyArrayPtr",
"StructEndArrayPtr",
"StructEndOmitEmptyArrayPtr",
"StructFieldMapPtr",
"StructFieldOmitEmptyMapPtr",
"StructEndMapPtr",
"StructEndOmitEmptyMapPtr",
"StructFieldSlicePtr",
"StructFieldOmitEmptySlicePtr",
"StructEndSlicePtr",
"StructEndOmitEmptySlicePtr",
"StructFieldMarshalJSONPtr",
"StructFieldOmitEmptyMarshalJSONPtr",
"StructEndMarshalJSONPtr",
"StructEndOmitEmptyMarshalJSONPtr",
"StructFieldMarshalTextPtr",
"StructFieldOmitEmptyMarshalTextPtr",
"StructEndMarshalTextPtr",
"StructEndOmitEmptyMarshalTextPtr",
"StructFieldInterfacePtr",
"StructFieldOmitEmptyInterfacePtr",
"StructEndInterfacePtr",
"StructEndOmitEmptyInterfacePtr",
"StructFieldIntPtrString",
"StructFieldOmitEmptyIntPtrString",
"StructEndIntPtrString",
"StructEndOmitEmptyIntPtrString",
"StructFieldUintPtrString",
"StructFieldOmitEmptyUintPtrString",
"StructEndUintPtrString",
"StructEndOmitEmptyUintPtrString",
"StructFieldFloat32PtrString",
"StructFieldOmitEmptyFloat32PtrString",
"StructEndFloat32PtrString",
"StructEndOmitEmptyFloat32PtrString",
"StructFieldFloat64PtrString",
"StructFieldOmitEmptyFloat64PtrString",
"StructEndFloat64PtrString",
"StructEndOmitEmptyFloat64PtrString",
"StructFieldBoolPtrString",
"StructFieldOmitEmptyBoolPtrString",
"StructEndBoolPtrString",
"StructEndOmitEmptyBoolPtrString",
"StructFieldStringPtrString",
"StructFieldOmitEmptyStringPtrString",
"StructEndStringPtrString",
"StructEndOmitEmptyStringPtrString",
"StructFieldNumberPtrString",
"StructFieldOmitEmptyNumberPtrString",
"StructEndNumberPtrString",
"StructEndOmitEmptyNumberPtrString",
"StructField",
"StructFieldOmitEmpty",
"StructEnd",
"StructEndOmitEmpty",
}
type OpType uint16
const (
OpEnd OpType = 0
OpInterface OpType = 1
OpPtr OpType = 2
OpSliceElem OpType = 3
OpSliceEnd OpType = 4
OpArrayElem OpType = 5
OpArrayEnd OpType = 6
OpMapKey OpType = 7
OpMapValue OpType = 8
OpMapEnd OpType = 9
OpRecursive OpType = 10
OpRecursivePtr OpType = 11
OpRecursiveEnd OpType = 12
OpInterfaceEnd OpType = 13
OpInt OpType = 14
OpUint OpType = 15
OpFloat32 OpType = 16
OpFloat64 OpType = 17
OpBool OpType = 18
OpString OpType = 19
OpBytes OpType = 20
OpNumber OpType = 21
OpArray OpType = 22
OpMap OpType = 23
OpSlice OpType = 24
OpStruct OpType = 25
OpMarshalJSON OpType = 26
OpMarshalText OpType = 27
OpIntString OpType = 28
OpUintString OpType = 29
OpFloat32String OpType = 30
OpFloat64String OpType = 31
OpBoolString OpType = 32
OpStringString OpType = 33
OpNumberString OpType = 34
OpIntPtr OpType = 35
OpUintPtr OpType = 36
OpFloat32Ptr OpType = 37
OpFloat64Ptr OpType = 38
OpBoolPtr OpType = 39
OpStringPtr OpType = 40
OpBytesPtr OpType = 41
OpNumberPtr OpType = 42
OpArrayPtr OpType = 43
OpMapPtr OpType = 44
OpSlicePtr OpType = 45
OpMarshalJSONPtr OpType = 46
OpMarshalTextPtr OpType = 47
OpInterfacePtr OpType = 48
OpIntPtrString OpType = 49
OpUintPtrString OpType = 50
OpFloat32PtrString OpType = 51
OpFloat64PtrString OpType = 52
OpBoolPtrString OpType = 53
OpStringPtrString OpType = 54
OpNumberPtrString OpType = 55
OpStructHeadInt OpType = 56
OpStructHeadOmitEmptyInt OpType = 57
OpStructPtrHeadInt OpType = 58
OpStructPtrHeadOmitEmptyInt OpType = 59
OpStructHeadUint OpType = 60
OpStructHeadOmitEmptyUint OpType = 61
OpStructPtrHeadUint OpType = 62
OpStructPtrHeadOmitEmptyUint OpType = 63
OpStructHeadFloat32 OpType = 64
OpStructHeadOmitEmptyFloat32 OpType = 65
OpStructPtrHeadFloat32 OpType = 66
OpStructPtrHeadOmitEmptyFloat32 OpType = 67
OpStructHeadFloat64 OpType = 68
OpStructHeadOmitEmptyFloat64 OpType = 69
OpStructPtrHeadFloat64 OpType = 70
OpStructPtrHeadOmitEmptyFloat64 OpType = 71
OpStructHeadBool OpType = 72
OpStructHeadOmitEmptyBool OpType = 73
OpStructPtrHeadBool OpType = 74
OpStructPtrHeadOmitEmptyBool OpType = 75
OpStructHeadString OpType = 76
OpStructHeadOmitEmptyString OpType = 77
OpStructPtrHeadString OpType = 78
OpStructPtrHeadOmitEmptyString OpType = 79
OpStructHeadBytes OpType = 80
OpStructHeadOmitEmptyBytes OpType = 81
OpStructPtrHeadBytes OpType = 82
OpStructPtrHeadOmitEmptyBytes OpType = 83
OpStructHeadNumber OpType = 84
OpStructHeadOmitEmptyNumber OpType = 85
OpStructPtrHeadNumber OpType = 86
OpStructPtrHeadOmitEmptyNumber OpType = 87
OpStructHeadArray OpType = 88
OpStructHeadOmitEmptyArray OpType = 89
OpStructPtrHeadArray OpType = 90
OpStructPtrHeadOmitEmptyArray OpType = 91
OpStructHeadMap OpType = 92
OpStructHeadOmitEmptyMap OpType = 93
OpStructPtrHeadMap OpType = 94
OpStructPtrHeadOmitEmptyMap OpType = 95
OpStructHeadSlice OpType = 96
OpStructHeadOmitEmptySlice OpType = 97
OpStructPtrHeadSlice OpType = 98
OpStructPtrHeadOmitEmptySlice OpType = 99
OpStructHeadStruct OpType = 100
OpStructHeadOmitEmptyStruct OpType = 101
OpStructPtrHeadStruct OpType = 102
OpStructPtrHeadOmitEmptyStruct OpType = 103
OpStructHeadMarshalJSON OpType = 104
OpStructHeadOmitEmptyMarshalJSON OpType = 105
OpStructPtrHeadMarshalJSON OpType = 106
OpStructPtrHeadOmitEmptyMarshalJSON OpType = 107
OpStructHeadMarshalText OpType = 108
OpStructHeadOmitEmptyMarshalText OpType = 109
OpStructPtrHeadMarshalText OpType = 110
OpStructPtrHeadOmitEmptyMarshalText OpType = 111
OpStructHeadIntString OpType = 112
OpStructHeadOmitEmptyIntString OpType = 113
OpStructPtrHeadIntString OpType = 114
OpStructPtrHeadOmitEmptyIntString OpType = 115
OpStructHeadUintString OpType = 116
OpStructHeadOmitEmptyUintString OpType = 117
OpStructPtrHeadUintString OpType = 118
OpStructPtrHeadOmitEmptyUintString OpType = 119
OpStructHeadFloat32String OpType = 120
OpStructHeadOmitEmptyFloat32String OpType = 121
OpStructPtrHeadFloat32String OpType = 122
OpStructPtrHeadOmitEmptyFloat32String OpType = 123
OpStructHeadFloat64String OpType = 124
OpStructHeadOmitEmptyFloat64String OpType = 125
OpStructPtrHeadFloat64String OpType = 126
OpStructPtrHeadOmitEmptyFloat64String OpType = 127
OpStructHeadBoolString OpType = 128
OpStructHeadOmitEmptyBoolString OpType = 129
OpStructPtrHeadBoolString OpType = 130
OpStructPtrHeadOmitEmptyBoolString OpType = 131
OpStructHeadStringString OpType = 132
OpStructHeadOmitEmptyStringString OpType = 133
OpStructPtrHeadStringString OpType = 134
OpStructPtrHeadOmitEmptyStringString OpType = 135
OpStructHeadNumberString OpType = 136
OpStructHeadOmitEmptyNumberString OpType = 137
OpStructPtrHeadNumberString OpType = 138
OpStructPtrHeadOmitEmptyNumberString OpType = 139
OpStructHeadIntPtr OpType = 140
OpStructHeadOmitEmptyIntPtr OpType = 141
OpStructPtrHeadIntPtr OpType = 142
OpStructPtrHeadOmitEmptyIntPtr OpType = 143
OpStructHeadUintPtr OpType = 144
OpStructHeadOmitEmptyUintPtr OpType = 145
OpStructPtrHeadUintPtr OpType = 146
OpStructPtrHeadOmitEmptyUintPtr OpType = 147
OpStructHeadFloat32Ptr OpType = 148
OpStructHeadOmitEmptyFloat32Ptr OpType = 149
OpStructPtrHeadFloat32Ptr OpType = 150
OpStructPtrHeadOmitEmptyFloat32Ptr OpType = 151
OpStructHeadFloat64Ptr OpType = 152
OpStructHeadOmitEmptyFloat64Ptr OpType = 153
OpStructPtrHeadFloat64Ptr OpType = 154
OpStructPtrHeadOmitEmptyFloat64Ptr OpType = 155
OpStructHeadBoolPtr OpType = 156
OpStructHeadOmitEmptyBoolPtr OpType = 157
OpStructPtrHeadBoolPtr OpType = 158
OpStructPtrHeadOmitEmptyBoolPtr OpType = 159
OpStructHeadStringPtr OpType = 160
OpStructHeadOmitEmptyStringPtr OpType = 161
OpStructPtrHeadStringPtr OpType = 162
OpStructPtrHeadOmitEmptyStringPtr OpType = 163
OpStructHeadBytesPtr OpType = 164
OpStructHeadOmitEmptyBytesPtr OpType = 165
OpStructPtrHeadBytesPtr OpType = 166
OpStructPtrHeadOmitEmptyBytesPtr OpType = 167
OpStructHeadNumberPtr OpType = 168
OpStructHeadOmitEmptyNumberPtr OpType = 169
OpStructPtrHeadNumberPtr OpType = 170
OpStructPtrHeadOmitEmptyNumberPtr OpType = 171
OpStructHeadArrayPtr OpType = 172
OpStructHeadOmitEmptyArrayPtr OpType = 173
OpStructPtrHeadArrayPtr OpType = 174
OpStructPtrHeadOmitEmptyArrayPtr OpType = 175
OpStructHeadMapPtr OpType = 176
OpStructHeadOmitEmptyMapPtr OpType = 177
OpStructPtrHeadMapPtr OpType = 178
OpStructPtrHeadOmitEmptyMapPtr OpType = 179
OpStructHeadSlicePtr OpType = 180
OpStructHeadOmitEmptySlicePtr OpType = 181
OpStructPtrHeadSlicePtr OpType = 182
OpStructPtrHeadOmitEmptySlicePtr OpType = 183
OpStructHeadMarshalJSONPtr OpType = 184
OpStructHeadOmitEmptyMarshalJSONPtr OpType = 185
OpStructPtrHeadMarshalJSONPtr OpType = 186
OpStructPtrHeadOmitEmptyMarshalJSONPtr OpType = 187
OpStructHeadMarshalTextPtr OpType = 188
OpStructHeadOmitEmptyMarshalTextPtr OpType = 189
OpStructPtrHeadMarshalTextPtr OpType = 190
OpStructPtrHeadOmitEmptyMarshalTextPtr OpType = 191
OpStructHeadInterfacePtr OpType = 192
OpStructHeadOmitEmptyInterfacePtr OpType = 193
OpStructPtrHeadInterfacePtr OpType = 194
OpStructPtrHeadOmitEmptyInterfacePtr OpType = 195
OpStructHeadIntPtrString OpType = 196
OpStructHeadOmitEmptyIntPtrString OpType = 197
OpStructPtrHeadIntPtrString OpType = 198
OpStructPtrHeadOmitEmptyIntPtrString OpType = 199
OpStructHeadUintPtrString OpType = 200
OpStructHeadOmitEmptyUintPtrString OpType = 201
OpStructPtrHeadUintPtrString OpType = 202
OpStructPtrHeadOmitEmptyUintPtrString OpType = 203
OpStructHeadFloat32PtrString OpType = 204
OpStructHeadOmitEmptyFloat32PtrString OpType = 205
OpStructPtrHeadFloat32PtrString OpType = 206
OpStructPtrHeadOmitEmptyFloat32PtrString OpType = 207
OpStructHeadFloat64PtrString OpType = 208
OpStructHeadOmitEmptyFloat64PtrString OpType = 209
OpStructPtrHeadFloat64PtrString OpType = 210
OpStructPtrHeadOmitEmptyFloat64PtrString OpType = 211
OpStructHeadBoolPtrString OpType = 212
OpStructHeadOmitEmptyBoolPtrString OpType = 213
OpStructPtrHeadBoolPtrString OpType = 214
OpStructPtrHeadOmitEmptyBoolPtrString OpType = 215
OpStructHeadStringPtrString OpType = 216
OpStructHeadOmitEmptyStringPtrString OpType = 217
OpStructPtrHeadStringPtrString OpType = 218
OpStructPtrHeadOmitEmptyStringPtrString OpType = 219
OpStructHeadNumberPtrString OpType = 220
OpStructHeadOmitEmptyNumberPtrString OpType = 221
OpStructPtrHeadNumberPtrString OpType = 222
OpStructPtrHeadOmitEmptyNumberPtrString OpType = 223
OpStructHead OpType = 224
OpStructHeadOmitEmpty OpType = 225
OpStructPtrHead OpType = 226
OpStructPtrHeadOmitEmpty OpType = 227
OpStructFieldInt OpType = 228
OpStructFieldOmitEmptyInt OpType = 229
OpStructEndInt OpType = 230
OpStructEndOmitEmptyInt OpType = 231
OpStructFieldUint OpType = 232
OpStructFieldOmitEmptyUint OpType = 233
OpStructEndUint OpType = 234
OpStructEndOmitEmptyUint OpType = 235
OpStructFieldFloat32 OpType = 236
OpStructFieldOmitEmptyFloat32 OpType = 237
OpStructEndFloat32 OpType = 238
OpStructEndOmitEmptyFloat32 OpType = 239
OpStructFieldFloat64 OpType = 240
OpStructFieldOmitEmptyFloat64 OpType = 241
OpStructEndFloat64 OpType = 242
OpStructEndOmitEmptyFloat64 OpType = 243
OpStructFieldBool OpType = 244
OpStructFieldOmitEmptyBool OpType = 245
OpStructEndBool OpType = 246
OpStructEndOmitEmptyBool OpType = 247
OpStructFieldString OpType = 248
OpStructFieldOmitEmptyString OpType = 249
OpStructEndString OpType = 250
OpStructEndOmitEmptyString OpType = 251
OpStructFieldBytes OpType = 252
OpStructFieldOmitEmptyBytes OpType = 253
OpStructEndBytes OpType = 254
OpStructEndOmitEmptyBytes OpType = 255
OpStructFieldNumber OpType = 256
OpStructFieldOmitEmptyNumber OpType = 257
OpStructEndNumber OpType = 258
OpStructEndOmitEmptyNumber OpType = 259
OpStructFieldArray OpType = 260
OpStructFieldOmitEmptyArray OpType = 261
OpStructEndArray OpType = 262
OpStructEndOmitEmptyArray OpType = 263
OpStructFieldMap OpType = 264
OpStructFieldOmitEmptyMap OpType = 265
OpStructEndMap OpType = 266
OpStructEndOmitEmptyMap OpType = 267
OpStructFieldSlice OpType = 268
OpStructFieldOmitEmptySlice OpType = 269
OpStructEndSlice OpType = 270
OpStructEndOmitEmptySlice OpType = 271
OpStructFieldStruct OpType = 272
OpStructFieldOmitEmptyStruct OpType = 273
OpStructEndStruct OpType = 274
OpStructEndOmitEmptyStruct OpType = 275
OpStructFieldMarshalJSON OpType = 276
OpStructFieldOmitEmptyMarshalJSON OpType = 277
OpStructEndMarshalJSON OpType = 278
OpStructEndOmitEmptyMarshalJSON OpType = 279
OpStructFieldMarshalText OpType = 280
OpStructFieldOmitEmptyMarshalText OpType = 281
OpStructEndMarshalText OpType = 282
OpStructEndOmitEmptyMarshalText OpType = 283
OpStructFieldIntString OpType = 284
OpStructFieldOmitEmptyIntString OpType = 285
OpStructEndIntString OpType = 286
OpStructEndOmitEmptyIntString OpType = 287
OpStructFieldUintString OpType = 288
OpStructFieldOmitEmptyUintString OpType = 289
OpStructEndUintString OpType = 290
OpStructEndOmitEmptyUintString OpType = 291
OpStructFieldFloat32String OpType = 292
OpStructFieldOmitEmptyFloat32String OpType = 293
OpStructEndFloat32String OpType = 294
OpStructEndOmitEmptyFloat32String OpType = 295
OpStructFieldFloat64String OpType = 296
OpStructFieldOmitEmptyFloat64String OpType = 297
OpStructEndFloat64String OpType = 298
OpStructEndOmitEmptyFloat64String OpType = 299
OpStructFieldBoolString OpType = 300
OpStructFieldOmitEmptyBoolString OpType = 301
OpStructEndBoolString OpType = 302
OpStructEndOmitEmptyBoolString OpType = 303
OpStructFieldStringString OpType = 304
OpStructFieldOmitEmptyStringString OpType = 305
OpStructEndStringString OpType = 306
OpStructEndOmitEmptyStringString OpType = 307
OpStructFieldNumberString OpType = 308
OpStructFieldOmitEmptyNumberString OpType = 309
OpStructEndNumberString OpType = 310
OpStructEndOmitEmptyNumberString OpType = 311
OpStructFieldIntPtr OpType = 312
OpStructFieldOmitEmptyIntPtr OpType = 313
OpStructEndIntPtr OpType = 314
OpStructEndOmitEmptyIntPtr OpType = 315
OpStructFieldUintPtr OpType = 316
OpStructFieldOmitEmptyUintPtr OpType = 317
OpStructEndUintPtr OpType = 318
OpStructEndOmitEmptyUintPtr OpType = 319
OpStructFieldFloat32Ptr OpType = 320
OpStructFieldOmitEmptyFloat32Ptr OpType = 321
OpStructEndFloat32Ptr OpType = 322
OpStructEndOmitEmptyFloat32Ptr OpType = 323
OpStructFieldFloat64Ptr OpType = 324
OpStructFieldOmitEmptyFloat64Ptr OpType = 325
OpStructEndFloat64Ptr OpType = 326
OpStructEndOmitEmptyFloat64Ptr OpType = 327
OpStructFieldBoolPtr OpType = 328
OpStructFieldOmitEmptyBoolPtr OpType = 329
OpStructEndBoolPtr OpType = 330
OpStructEndOmitEmptyBoolPtr OpType = 331
OpStructFieldStringPtr OpType = 332
OpStructFieldOmitEmptyStringPtr OpType = 333
OpStructEndStringPtr OpType = 334
OpStructEndOmitEmptyStringPtr OpType = 335
OpStructFieldBytesPtr OpType = 336
OpStructFieldOmitEmptyBytesPtr OpType = 337
OpStructEndBytesPtr OpType = 338
OpStructEndOmitEmptyBytesPtr OpType = 339
OpStructFieldNumberPtr OpType = 340
OpStructFieldOmitEmptyNumberPtr OpType = 341
OpStructEndNumberPtr OpType = 342
OpStructEndOmitEmptyNumberPtr OpType = 343
OpStructFieldArrayPtr OpType = 344
OpStructFieldOmitEmptyArrayPtr OpType = 345
OpStructEndArrayPtr OpType = 346
OpStructEndOmitEmptyArrayPtr OpType = 347
OpStructFieldMapPtr OpType = 348
OpStructFieldOmitEmptyMapPtr OpType = 349
OpStructEndMapPtr OpType = 350
OpStructEndOmitEmptyMapPtr OpType = 351
OpStructFieldSlicePtr OpType = 352
OpStructFieldOmitEmptySlicePtr OpType = 353
OpStructEndSlicePtr OpType = 354
OpStructEndOmitEmptySlicePtr OpType = 355
OpStructFieldMarshalJSONPtr OpType = 356
OpStructFieldOmitEmptyMarshalJSONPtr OpType = 357
OpStructEndMarshalJSONPtr OpType = 358
OpStructEndOmitEmptyMarshalJSONPtr OpType = 359
OpStructFieldMarshalTextPtr OpType = 360
OpStructFieldOmitEmptyMarshalTextPtr OpType = 361
OpStructEndMarshalTextPtr OpType = 362
OpStructEndOmitEmptyMarshalTextPtr OpType = 363
OpStructFieldInterfacePtr OpType = 364
OpStructFieldOmitEmptyInterfacePtr OpType = 365
OpStructEndInterfacePtr OpType = 366
OpStructEndOmitEmptyInterfacePtr OpType = 367
OpStructFieldIntPtrString OpType = 368
OpStructFieldOmitEmptyIntPtrString OpType = 369
OpStructEndIntPtrString OpType = 370
OpStructEndOmitEmptyIntPtrString OpType = 371
OpStructFieldUintPtrString OpType = 372
OpStructFieldOmitEmptyUintPtrString OpType = 373
OpStructEndUintPtrString OpType = 374
OpStructEndOmitEmptyUintPtrString OpType = 375
OpStructFieldFloat32PtrString OpType = 376
OpStructFieldOmitEmptyFloat32PtrString OpType = 377
OpStructEndFloat32PtrString OpType = 378
OpStructEndOmitEmptyFloat32PtrString OpType = 379
OpStructFieldFloat64PtrString OpType = 380
OpStructFieldOmitEmptyFloat64PtrString OpType = 381
OpStructEndFloat64PtrString OpType = 382
OpStructEndOmitEmptyFloat64PtrString OpType = 383
OpStructFieldBoolPtrString OpType = 384
OpStructFieldOmitEmptyBoolPtrString OpType = 385
OpStructEndBoolPtrString OpType = 386
OpStructEndOmitEmptyBoolPtrString OpType = 387
OpStructFieldStringPtrString OpType = 388
OpStructFieldOmitEmptyStringPtrString OpType = 389
OpStructEndStringPtrString OpType = 390
OpStructEndOmitEmptyStringPtrString OpType = 391
OpStructFieldNumberPtrString OpType = 392
OpStructFieldOmitEmptyNumberPtrString OpType = 393
OpStructEndNumberPtrString OpType = 394
OpStructEndOmitEmptyNumberPtrString OpType = 395
OpStructField OpType = 396
OpStructFieldOmitEmpty OpType = 397
OpStructEnd OpType = 398
OpStructEndOmitEmpty OpType = 399
)
func (t OpType) String() string {
if int(t) >= 400 {
return ""
}
return opTypeStrings[int(t)]
}
func (t OpType) CodeType() CodeType {
if strings.Contains(t.String(), "Struct") {
if strings.Contains(t.String(), "End") {
return CodeStructEnd
}
return CodeStructField
}
switch t {
case OpArray, OpArrayPtr:
return CodeArrayHead
case OpArrayElem:
return CodeArrayElem
case OpSlice, OpSlicePtr:
return CodeSliceHead
case OpSliceElem:
return CodeSliceElem
case OpMap, OpMapPtr:
return CodeMapHead
case OpMapKey:
return CodeMapKey
case OpMapValue:
return CodeMapValue
case OpMapEnd:
return CodeMapEnd
}
return CodeOp
}
func (t OpType) HeadToPtrHead() OpType {
if strings.Index(t.String(), "PtrHead") > 0 {
return t
}
idx := strings.Index(t.String(), "Head")
if idx == -1 {
return t
}
suffix := "PtrHead" + t.String()[idx+len("Head"):]
const toPtrOffset = 2
if strings.Contains(OpType(int(t)+toPtrOffset).String(), suffix) {
return OpType(int(t) + toPtrOffset)
}
return t
}
func (t OpType) HeadToOmitEmptyHead() OpType {
const toOmitEmptyOffset = 1
if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") {
return OpType(int(t) + toOmitEmptyOffset)
}
return t
}
func (t OpType) PtrHeadToHead() OpType {
idx := strings.Index(t.String(), "PtrHead")
if idx == -1 {
return t
}
suffix := t.String()[idx+len("Ptr"):]
const toPtrOffset = 2
if strings.Contains(OpType(int(t)-toPtrOffset).String(), suffix) {
return OpType(int(t) - toPtrOffset)
}
return t
}
func (t OpType) FieldToEnd() OpType {
idx := strings.Index(t.String(), "Field")
if idx == -1 {
return t
}
suffix := t.String()[idx+len("Field"):]
if suffix == "" || suffix == "OmitEmpty" {
return t
}
const toEndOffset = 2
if strings.Contains(OpType(int(t)+toEndOffset).String(), "End"+suffix) {
return OpType(int(t) + toEndOffset)
}
return t
}
func (t OpType) FieldToOmitEmptyField() OpType {
const toOmitEmptyOffset = 1
if strings.Contains(OpType(int(t)+toOmitEmptyOffset).String(), "OmitEmpty") {
return OpType(int(t) + toOmitEmptyOffset)
}
return t
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/query.go
================================================
package encoder
import (
"context"
"fmt"
"reflect"
)
var (
Marshal func(interface{}) ([]byte, error)
Unmarshal func([]byte, interface{}) error
)
type FieldQuery struct {
Name string
Fields []*FieldQuery
hash string
}
func (q *FieldQuery) Hash() string {
if q.hash != "" {
return q.hash
}
b, _ := Marshal(q)
q.hash = string(b)
return q.hash
}
func (q *FieldQuery) MarshalJSON() ([]byte, error) {
if q.Name != "" {
if len(q.Fields) > 0 {
return Marshal(map[string][]*FieldQuery{q.Name: q.Fields})
}
return Marshal(q.Name)
}
return Marshal(q.Fields)
}
func (q *FieldQuery) QueryString() (FieldQueryString, error) {
b, err := Marshal(q)
if err != nil {
return "", err
}
return FieldQueryString(b), nil
}
type FieldQueryString string
func (s FieldQueryString) Build() (*FieldQuery, error) {
var query interface{}
if err := Unmarshal([]byte(s), &query); err != nil {
return nil, err
}
return s.build(reflect.ValueOf(query))
}
func (s FieldQueryString) build(v reflect.Value) (*FieldQuery, error) {
switch v.Type().Kind() {
case reflect.String:
return s.buildString(v)
case reflect.Map:
return s.buildMap(v)
case reflect.Slice:
return s.buildSlice(v)
case reflect.Interface:
return s.build(reflect.ValueOf(v.Interface()))
}
return nil, fmt.Errorf("failed to build field query")
}
func (s FieldQueryString) buildString(v reflect.Value) (*FieldQuery, error) {
b := []byte(v.String())
switch b[0] {
case '[', '{':
var query interface{}
if err := Unmarshal(b, &query); err != nil {
return nil, err
}
if str, ok := query.(string); ok {
return &FieldQuery{Name: str}, nil
}
return s.build(reflect.ValueOf(query))
}
return &FieldQuery{Name: string(b)}, nil
}
func (s FieldQueryString) buildSlice(v reflect.Value) (*FieldQuery, error) {
fields := make([]*FieldQuery, 0, v.Len())
for i := 0; i < v.Len(); i++ {
def, err := s.build(v.Index(i))
if err != nil {
return nil, err
}
fields = append(fields, def)
}
return &FieldQuery{Fields: fields}, nil
}
func (s FieldQueryString) buildMap(v reflect.Value) (*FieldQuery, error) {
keys := v.MapKeys()
if len(keys) != 1 {
return nil, fmt.Errorf("failed to build field query object")
}
key := keys[0]
if key.Type().Kind() != reflect.String {
return nil, fmt.Errorf("failed to build field query. invalid object key type")
}
name := key.String()
def, err := s.build(v.MapIndex(key))
if err != nil {
return nil, err
}
return &FieldQuery{
Name: name,
Fields: def.Fields,
}, nil
}
type queryKey struct{}
func FieldQueryFromContext(ctx context.Context) *FieldQuery {
query := ctx.Value(queryKey{})
if query == nil {
return nil
}
q, ok := query.(*FieldQuery)
if !ok {
return nil
}
return q
}
func SetFieldQueryToContext(ctx context.Context, query *FieldQuery) context.Context {
return context.WithValue(ctx, queryKey{}, query)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/string.go
================================================
package encoder
import (
"math/bits"
"reflect"
"unsafe"
)
const (
lsb = 0x0101010101010101
msb = 0x8080808080808080
)
var hex = "0123456789abcdef"
//nolint:govet
func stringToUint64Slice(s string) []uint64 {
return *(*[]uint64)(unsafe.Pointer(&reflect.SliceHeader{
Data: ((*reflect.StringHeader)(unsafe.Pointer(&s))).Data,
Len: len(s) / 8,
Cap: len(s) / 8,
}))
}
func AppendString(ctx *RuntimeContext, buf []byte, s string) []byte {
if ctx.Option.Flag&HTMLEscapeOption != 0 {
if ctx.Option.Flag&NormalizeUTF8Option != 0 {
return appendNormalizedHTMLString(buf, s)
}
return appendHTMLString(buf, s)
}
if ctx.Option.Flag&NormalizeUTF8Option != 0 {
return appendNormalizedString(buf, s)
}
return appendString(buf, s)
}
func appendNormalizedHTMLString(buf []byte, s string) []byte {
valLen := len(s)
if valLen == 0 {
return append(buf, `""`...)
}
buf = append(buf, '"')
var (
i, j int
)
if valLen >= 8 {
chunks := stringToUint64Slice(s)
for _, n := range chunks {
// combine masks before checking for the MSB of each byte. We include
// `n` in the mask to check whether any of the *input* byte MSBs were
// set (i.e. the byte was outside the ASCII range).
mask := n | (n - (lsb * 0x20)) |
((n ^ (lsb * '"')) - lsb) |
((n ^ (lsb * '\\')) - lsb) |
((n ^ (lsb * '<')) - lsb) |
((n ^ (lsb * '>')) - lsb) |
((n ^ (lsb * '&')) - lsb)
if (mask & msb) != 0 {
j = bits.TrailingZeros64(mask&msb) / 8
goto ESCAPE_END
}
}
for i := len(chunks) * 8; i < valLen; i++ {
if needEscapeHTMLNormalizeUTF8[s[i]] {
j = i
goto ESCAPE_END
}
}
// no found any escape characters.
return append(append(buf, s...), '"')
}
ESCAPE_END:
for j < valLen {
c := s[j]
if !needEscapeHTMLNormalizeUTF8[c] {
// fast path: most of the time, printable ascii characters are used
j++
continue
}
switch c {
case '\\', '"':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', c)
i = j + 1
j = j + 1
continue
case '\n':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'n')
i = j + 1
j = j + 1
continue
case '\r':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'r')
i = j + 1
j = j + 1
continue
case '\t':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 't')
i = j + 1
j = j + 1
continue
case '<', '>', '&':
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
}
state, size := decodeRuneInString(s[j:])
switch state {
case runeErrorState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\ufffd`...)
i = j + 1
j = j + 1
continue
// U+2028 is LINE SEPARATOR.
// U+2029 is PARAGRAPH SEPARATOR.
// They are both technically valid characters in JSON strings,
// but don't work in JSONP, which has to be evaluated as JavaScript,
// and can lead to security holes there. It is valid JSON to
// escape them, so we do so unconditionally.
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
case lineSepState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\u2028`...)
i = j + 3
j = j + 3
continue
case paragraphSepState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\u2029`...)
i = j + 3
j = j + 3
continue
}
j += size
}
return append(append(buf, s[i:]...), '"')
}
func appendHTMLString(buf []byte, s string) []byte {
valLen := len(s)
if valLen == 0 {
return append(buf, `""`...)
}
buf = append(buf, '"')
var (
i, j int
)
if valLen >= 8 {
chunks := stringToUint64Slice(s)
for _, n := range chunks {
// combine masks before checking for the MSB of each byte. We include
// `n` in the mask to check whether any of the *input* byte MSBs were
// set (i.e. the byte was outside the ASCII range).
mask := n | (n - (lsb * 0x20)) |
((n ^ (lsb * '"')) - lsb) |
((n ^ (lsb * '\\')) - lsb) |
((n ^ (lsb * '<')) - lsb) |
((n ^ (lsb * '>')) - lsb) |
((n ^ (lsb * '&')) - lsb)
if (mask & msb) != 0 {
j = bits.TrailingZeros64(mask&msb) / 8
goto ESCAPE_END
}
}
for i := len(chunks) * 8; i < valLen; i++ {
if needEscapeHTML[s[i]] {
j = i
goto ESCAPE_END
}
}
// no found any escape characters.
return append(append(buf, s...), '"')
}
ESCAPE_END:
for j < valLen {
c := s[j]
if !needEscapeHTML[c] {
// fast path: most of the time, printable ascii characters are used
j++
continue
}
switch c {
case '\\', '"':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', c)
i = j + 1
j = j + 1
continue
case '\n':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'n')
i = j + 1
j = j + 1
continue
case '\r':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'r')
i = j + 1
j = j + 1
continue
case '\t':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 't')
i = j + 1
j = j + 1
continue
case '<', '>', '&':
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
}
j++
}
return append(append(buf, s[i:]...), '"')
}
func appendNormalizedString(buf []byte, s string) []byte {
valLen := len(s)
if valLen == 0 {
return append(buf, `""`...)
}
buf = append(buf, '"')
var (
i, j int
)
if valLen >= 8 {
chunks := stringToUint64Slice(s)
for _, n := range chunks {
// combine masks before checking for the MSB of each byte. We include
// `n` in the mask to check whether any of the *input* byte MSBs were
// set (i.e. the byte was outside the ASCII range).
mask := n | (n - (lsb * 0x20)) |
((n ^ (lsb * '"')) - lsb) |
((n ^ (lsb * '\\')) - lsb)
if (mask & msb) != 0 {
j = bits.TrailingZeros64(mask&msb) / 8
goto ESCAPE_END
}
}
valLen := len(s)
for i := len(chunks) * 8; i < valLen; i++ {
if needEscapeNormalizeUTF8[s[i]] {
j = i
goto ESCAPE_END
}
}
return append(append(buf, s...), '"')
}
ESCAPE_END:
for j < valLen {
c := s[j]
if !needEscapeNormalizeUTF8[c] {
// fast path: most of the time, printable ascii characters are used
j++
continue
}
switch c {
case '\\', '"':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', c)
i = j + 1
j = j + 1
continue
case '\n':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'n')
i = j + 1
j = j + 1
continue
case '\r':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'r')
i = j + 1
j = j + 1
continue
case '\t':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 't')
i = j + 1
j = j + 1
continue
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
}
state, size := decodeRuneInString(s[j:])
switch state {
case runeErrorState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\ufffd`...)
i = j + 1
j = j + 1
continue
// U+2028 is LINE SEPARATOR.
// U+2029 is PARAGRAPH SEPARATOR.
// They are both technically valid characters in JSON strings,
// but don't work in JSONP, which has to be evaluated as JavaScript,
// and can lead to security holes there. It is valid JSON to
// escape them, so we do so unconditionally.
// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
case lineSepState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\u2028`...)
i = j + 3
j = j + 3
continue
case paragraphSepState:
buf = append(buf, s[i:j]...)
buf = append(buf, `\u2029`...)
i = j + 3
j = j + 3
continue
}
j += size
}
return append(append(buf, s[i:]...), '"')
}
func appendString(buf []byte, s string) []byte {
valLen := len(s)
if valLen == 0 {
return append(buf, `""`...)
}
buf = append(buf, '"')
var (
i, j int
)
if valLen >= 8 {
chunks := stringToUint64Slice(s)
for _, n := range chunks {
// combine masks before checking for the MSB of each byte. We include
// `n` in the mask to check whether any of the *input* byte MSBs were
// set (i.e. the byte was outside the ASCII range).
mask := n | (n - (lsb * 0x20)) |
((n ^ (lsb * '"')) - lsb) |
((n ^ (lsb * '\\')) - lsb)
if (mask & msb) != 0 {
j = bits.TrailingZeros64(mask&msb) / 8
goto ESCAPE_END
}
}
valLen := len(s)
for i := len(chunks) * 8; i < valLen; i++ {
if needEscape[s[i]] {
j = i
goto ESCAPE_END
}
}
return append(append(buf, s...), '"')
}
ESCAPE_END:
for j < valLen {
c := s[j]
if !needEscape[c] {
// fast path: most of the time, printable ascii characters are used
j++
continue
}
switch c {
case '\\', '"':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', c)
i = j + 1
j = j + 1
continue
case '\n':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'n')
i = j + 1
j = j + 1
continue
case '\r':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 'r')
i = j + 1
j = j + 1
continue
case '\t':
buf = append(buf, s[i:j]...)
buf = append(buf, '\\', 't')
i = j + 1
j = j + 1
continue
case 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0B, 0x0C, 0x0E, 0x0F, // 0x00-0x0F
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F: // 0x10-0x1F
buf = append(buf, s[i:j]...)
buf = append(buf, `\u00`...)
buf = append(buf, hex[c>>4], hex[c&0xF])
i = j + 1
j = j + 1
continue
}
j++
}
return append(append(buf, s[i:]...), '"')
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/string_table.go
================================================
package encoder
var needEscapeHTMLNormalizeUTF8 = [256]bool{
'"': true,
'&': true,
'<': true,
'>': true,
'\\': true,
0x00: true,
0x01: true,
0x02: true,
0x03: true,
0x04: true,
0x05: true,
0x06: true,
0x07: true,
0x08: true,
0x09: true,
0x0a: true,
0x0b: true,
0x0c: true,
0x0d: true,
0x0e: true,
0x0f: true,
0x10: true,
0x11: true,
0x12: true,
0x13: true,
0x14: true,
0x15: true,
0x16: true,
0x17: true,
0x18: true,
0x19: true,
0x1a: true,
0x1b: true,
0x1c: true,
0x1d: true,
0x1e: true,
0x1f: true,
/* 0x20 - 0x7f */
0x80: true,
0x81: true,
0x82: true,
0x83: true,
0x84: true,
0x85: true,
0x86: true,
0x87: true,
0x88: true,
0x89: true,
0x8a: true,
0x8b: true,
0x8c: true,
0x8d: true,
0x8e: true,
0x8f: true,
0x90: true,
0x91: true,
0x92: true,
0x93: true,
0x94: true,
0x95: true,
0x96: true,
0x97: true,
0x98: true,
0x99: true,
0x9a: true,
0x9b: true,
0x9c: true,
0x9d: true,
0x9e: true,
0x9f: true,
0xa0: true,
0xa1: true,
0xa2: true,
0xa3: true,
0xa4: true,
0xa5: true,
0xa6: true,
0xa7: true,
0xa8: true,
0xa9: true,
0xaa: true,
0xab: true,
0xac: true,
0xad: true,
0xae: true,
0xaf: true,
0xb0: true,
0xb1: true,
0xb2: true,
0xb3: true,
0xb4: true,
0xb5: true,
0xb6: true,
0xb7: true,
0xb8: true,
0xb9: true,
0xba: true,
0xbb: true,
0xbc: true,
0xbd: true,
0xbe: true,
0xbf: true,
0xc0: true,
0xc1: true,
0xc2: true,
0xc3: true,
0xc4: true,
0xc5: true,
0xc6: true,
0xc7: true,
0xc8: true,
0xc9: true,
0xca: true,
0xcb: true,
0xcc: true,
0xcd: true,
0xce: true,
0xcf: true,
0xd0: true,
0xd1: true,
0xd2: true,
0xd3: true,
0xd4: true,
0xd5: true,
0xd6: true,
0xd7: true,
0xd8: true,
0xd9: true,
0xda: true,
0xdb: true,
0xdc: true,
0xdd: true,
0xde: true,
0xdf: true,
0xe0: true,
0xe1: true,
0xe2: true,
0xe3: true,
0xe4: true,
0xe5: true,
0xe6: true,
0xe7: true,
0xe8: true,
0xe9: true,
0xea: true,
0xeb: true,
0xec: true,
0xed: true,
0xee: true,
0xef: true,
0xf0: true,
0xf1: true,
0xf2: true,
0xf3: true,
0xf4: true,
0xf5: true,
0xf6: true,
0xf7: true,
0xf8: true,
0xf9: true,
0xfa: true,
0xfb: true,
0xfc: true,
0xfd: true,
0xfe: true,
0xff: true,
}
var needEscapeNormalizeUTF8 = [256]bool{
'"': true,
'\\': true,
0x00: true,
0x01: true,
0x02: true,
0x03: true,
0x04: true,
0x05: true,
0x06: true,
0x07: true,
0x08: true,
0x09: true,
0x0a: true,
0x0b: true,
0x0c: true,
0x0d: true,
0x0e: true,
0x0f: true,
0x10: true,
0x11: true,
0x12: true,
0x13: true,
0x14: true,
0x15: true,
0x16: true,
0x17: true,
0x18: true,
0x19: true,
0x1a: true,
0x1b: true,
0x1c: true,
0x1d: true,
0x1e: true,
0x1f: true,
/* 0x20 - 0x7f */
0x80: true,
0x81: true,
0x82: true,
0x83: true,
0x84: true,
0x85: true,
0x86: true,
0x87: true,
0x88: true,
0x89: true,
0x8a: true,
0x8b: true,
0x8c: true,
0x8d: true,
0x8e: true,
0x8f: true,
0x90: true,
0x91: true,
0x92: true,
0x93: true,
0x94: true,
0x95: true,
0x96: true,
0x97: true,
0x98: true,
0x99: true,
0x9a: true,
0x9b: true,
0x9c: true,
0x9d: true,
0x9e: true,
0x9f: true,
0xa0: true,
0xa1: true,
0xa2: true,
0xa3: true,
0xa4: true,
0xa5: true,
0xa6: true,
0xa7: true,
0xa8: true,
0xa9: true,
0xaa: true,
0xab: true,
0xac: true,
0xad: true,
0xae: true,
0xaf: true,
0xb0: true,
0xb1: true,
0xb2: true,
0xb3: true,
0xb4: true,
0xb5: true,
0xb6: true,
0xb7: true,
0xb8: true,
0xb9: true,
0xba: true,
0xbb: true,
0xbc: true,
0xbd: true,
0xbe: true,
0xbf: true,
0xc0: true,
0xc1: true,
0xc2: true,
0xc3: true,
0xc4: true,
0xc5: true,
0xc6: true,
0xc7: true,
0xc8: true,
0xc9: true,
0xca: true,
0xcb: true,
0xcc: true,
0xcd: true,
0xce: true,
0xcf: true,
0xd0: true,
0xd1: true,
0xd2: true,
0xd3: true,
0xd4: true,
0xd5: true,
0xd6: true,
0xd7: true,
0xd8: true,
0xd9: true,
0xda: true,
0xdb: true,
0xdc: true,
0xdd: true,
0xde: true,
0xdf: true,
0xe0: true,
0xe1: true,
0xe2: true,
0xe3: true,
0xe4: true,
0xe5: true,
0xe6: true,
0xe7: true,
0xe8: true,
0xe9: true,
0xea: true,
0xeb: true,
0xec: true,
0xed: true,
0xee: true,
0xef: true,
0xf0: true,
0xf1: true,
0xf2: true,
0xf3: true,
0xf4: true,
0xf5: true,
0xf6: true,
0xf7: true,
0xf8: true,
0xf9: true,
0xfa: true,
0xfb: true,
0xfc: true,
0xfd: true,
0xfe: true,
0xff: true,
}
var needEscapeHTML = [256]bool{
'"': true,
'&': true,
'<': true,
'>': true,
'\\': true,
0x00: true,
0x01: true,
0x02: true,
0x03: true,
0x04: true,
0x05: true,
0x06: true,
0x07: true,
0x08: true,
0x09: true,
0x0a: true,
0x0b: true,
0x0c: true,
0x0d: true,
0x0e: true,
0x0f: true,
0x10: true,
0x11: true,
0x12: true,
0x13: true,
0x14: true,
0x15: true,
0x16: true,
0x17: true,
0x18: true,
0x19: true,
0x1a: true,
0x1b: true,
0x1c: true,
0x1d: true,
0x1e: true,
0x1f: true,
/* 0x20 - 0xff */
}
var needEscape = [256]bool{
'"': true,
'\\': true,
0x00: true,
0x01: true,
0x02: true,
0x03: true,
0x04: true,
0x05: true,
0x06: true,
0x07: true,
0x08: true,
0x09: true,
0x0a: true,
0x0b: true,
0x0c: true,
0x0d: true,
0x0e: true,
0x0f: true,
0x10: true,
0x11: true,
0x12: true,
0x13: true,
0x14: true,
0x15: true,
0x16: true,
0x17: true,
0x18: true,
0x19: true,
0x1a: true,
0x1b: true,
0x1c: true,
0x1d: true,
0x1e: true,
0x1f: true,
/* 0x20 - 0xff */
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go
================================================
package vm
import (
"fmt"
"github.com/goccy/go-json/internal/encoder"
)
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
defer func() {
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
if err := recover(); err != nil {
w := ctx.Option.DebugOut
fmt.Fprintln(w, "=============[DEBUG]===============")
fmt.Fprintln(w, "* [TYPE]")
fmt.Fprintln(w, codeSet.Type)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [ALL OPCODE]")
fmt.Fprintln(w, code.Dump())
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [CONTEXT]")
fmt.Fprintf(w, "%+v\n", ctx)
fmt.Fprintln(w, "===================================")
panic(err)
}
}()
return Run(ctx, b, codeSet)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm/hack.go
================================================
package vm
import (
// HACK: compile order
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_indent"
)
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm/util.go
================================================
package vm
import (
"encoding/json"
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
const uintptrSize = 4 << (^uintptr(0) >> 63)
var (
appendInt = encoder.AppendInt
appendUint = encoder.AppendUint
appendFloat32 = encoder.AppendFloat32
appendFloat64 = encoder.AppendFloat64
appendString = encoder.AppendString
appendByteSlice = encoder.AppendByteSlice
appendNumber = encoder.AppendNumber
errUnsupportedValue = encoder.ErrUnsupportedValue
errUnsupportedFloat = encoder.ErrUnsupportedFloat
mapiterinit = encoder.MapIterInit
mapiterkey = encoder.MapIterKey
mapitervalue = encoder.MapIterValue
mapiternext = encoder.MapIterNext
maplen = encoder.MapLen
)
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
type nonEmptyInterface struct {
itab *struct {
ityp *runtime.Type // static interface type
typ *runtime.Type // dynamic concrete type
// unused fields...
}
ptr unsafe.Pointer
}
func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
}
func load(base uintptr, idx uint32) uintptr {
addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr))
}
func store(base uintptr, idx uint32, p uintptr) {
addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p
}
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr))
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
}
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
return *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
}
func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
if v {
return append(b, "true"...)
}
return append(b, "false"...)
}
func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null"...)
}
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',')
}
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null,"...)
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
last := len(b) - 1
b[last] = ':'
return b
}
func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte {
b = append(b, key...)
b[len(b)-1] = ':'
return append(b, value...)
}
func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
b[len(b)-1] = '}'
b = append(b, ',')
return b
}
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalJSON(ctx, code, b, v)
}
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalText(ctx, code, b, v)
}
func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
return append(b, '[')
}
func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = ']'
return append(b, ',')
}
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '[', ']', ',')
}
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '}', ',')
}
func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = '}'
return append(b, ',')
}
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{')
}
func appendStructKey(_ *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return append(b, code.Key...)
}
func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
return append(b, '}', ',')
}
func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
if b[last] == ',' {
b[last] = '}'
return appendComma(ctx, b)
}
return appendStructEnd(ctx, code, b)
}
func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {}
func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {}
func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm/vm.go
================================================
// Code generated by internal/cmd/generator. DO NOT EDIT!
package vm
import (
"math"
"reflect"
"sort"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
recursiveLevel := 0
ptrOffset := uintptr(0)
ctxptr := ctx.Ptr()
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
for {
switch code.Op {
default:
return nil, errUnimplementedOp(code.Op)
case encoder.OpPtr:
p := load(ctxptr, code.Idx)
code = code.Next
store(ctxptr, code.Idx, ptrToPtr(p))
case encoder.OpIntPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInt:
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpUint:
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpIntString:
b = append(b, '"')
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintString:
b = append(b, '"')
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat32Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat32:
b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat64Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat64:
v := ptrToFloat64(load(ctxptr, code.Idx))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStringPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpString:
b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBoolPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBool:
b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBytesPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBytes:
b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpNumberPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpNumber:
bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpInterfacePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInterface:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if p == seen {
return nil, errUnsupportedValue(code, p)
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, p)
var (
typ *runtime.Type
ifacePtr unsafe.Pointer
)
up := ptrToUnsafePtr(p)
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
iface := (*nonEmptyInterface)(up)
ifacePtr = iface.ptr
if iface.itab != nil {
typ = iface.itab.typ
}
} else {
iface := (*emptyInterface)(up)
ifacePtr = iface.ptr
typ = iface.typ
}
if ifacePtr == nil {
isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ)
if !isDirectedNil {
b = appendNullComma(ctx, b)
code = code.Next
break
}
}
ctx.KeepRefs = append(ctx.KeepRefs, up)
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
if err != nil {
return nil, err
}
totalLength := uintptr(code.Length) + 3
nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3
var c *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
c = ifaceCodeSet.InterfaceEscapeKeyCode
} else {
c = ifaceCodeSet.InterfaceNoescapeKeyCode
}
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += totalLength * uintptrSize
oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent += code.Indent
newLen := offsetNum + totalLength + nextTotalLength
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
end := ifaceCodeSet.EndCode
store(ctxptr, c.Idx, uintptr(ifacePtr))
store(ctxptr, end.Idx, oldOffset)
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpInterfaceEnd:
recursiveLevel--
// restore ctxptr
offset := load(ctxptr, code.Idx)
restoreIndent(ctx, code, ctxptr)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
b = append(b, `""`...)
b = appendComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpSlicePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpSlice:
p := load(ctxptr, code.Idx)
slice := ptrToSlice(p)
if p == 0 || slice.Data == nil {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.ElemIdx, 0)
store(ctxptr, code.Length, uintptr(slice.Len))
store(ctxptr, code.Idx, uintptr(slice.Data))
if slice.Len > 0 {
b = appendArrayHead(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, uintptr(slice.Data))
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpSliceElem:
idx := load(ctxptr, code.ElemIdx)
length := load(ctxptr, code.Length)
idx++
if idx < length {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
data := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, data+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpArrayPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpArray:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
if code.Length > 0 {
b = appendArrayHead(ctx, code, b)
store(ctxptr, code.ElemIdx, 0)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpArrayElem:
idx := load(ctxptr, code.ElemIdx)
idx++
if idx < uintptr(code.Length) {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
p := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, p+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpMapPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpMap:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
uptr := ptrToUnsafePtr(p)
mlen := maplen(uptr)
if mlen <= 0 {
b = appendEmptyObject(ctx, b)
code = code.End.Next
break
}
b = appendStructHead(ctx, b)
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
mapiterinit(code.Type, uptr, &mapCtx.Iter)
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
if unorderedMap {
b = appendMapKeyIndent(ctx, code.Next, b)
} else {
mapCtx.Start = len(b)
mapCtx.First = len(b)
}
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
case encoder.OpMapKey:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
idx := mapCtx.Idx
idx++
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
if idx < mapCtx.Len {
b = appendMapKeyIndent(ctx, code, b)
mapCtx.Idx = int(idx)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
b = appendObjectEnd(ctx, code, b)
encoder.ReleaseMapContext(mapCtx)
code = code.End.Next
}
} else {
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
if idx < mapCtx.Len {
mapCtx.Idx = int(idx)
mapCtx.Start = len(b)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
code = code.End
}
}
case encoder.OpMapValue:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
b = appendColon(ctx, b)
} else {
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
mapCtx.Start = len(b)
}
value := mapitervalue(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(value))
mapiternext(&mapCtx.Iter)
code = code.Next
case encoder.OpMapEnd:
// this operation only used by sorted map.
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
sort.Sort(mapCtx.Slice)
buf := mapCtx.Buf
for _, item := range mapCtx.Slice.Items {
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
}
buf = appendMapEnd(ctx, code, buf)
b = b[:mapCtx.First]
b = append(b, buf...)
mapCtx.Buf = buf
encoder.ReleaseMapContext(mapCtx)
code = code.Next
case encoder.OpRecursivePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpRecursive:
ptr := load(ctxptr, code.Idx)
if ptr != 0 {
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if ptr == seen {
return nil, errUnsupportedValue(code, ptr)
}
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, ptr)
c := code.Jmp.Code
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += code.Jmp.CurLen * uintptrSize
oldBaseIndent := ctx.BaseIndent
indentDiffFromTop := c.Indent - 1
ctx.BaseIndent += code.Indent - indentDiffFromTop
newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
store(ctxptr, c.Idx, ptr)
store(ctxptr, c.End.Next.Idx, oldOffset)
store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpRecursiveEnd:
recursiveLevel--
// restore ctxptr
restoreIndent(ctx, code, ctxptr)
offset := load(ctxptr, code.Idx)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpStructPtrHead:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHead:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if len(code.Key) > 0 {
if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
}
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
u64 := ptrToUint64(p, code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset)))))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
}
case encoder.OpStructPtrHeadNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructPtrHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadArray, encoder.OpStructHeadSlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyArray:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyArray:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptySlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptySlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
if maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p)
}
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructField:
if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
p := load(ctxptr, code.Idx) + uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmpty:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringString:
p := load(ctxptr, code.Idx)
s := ptrToString(p + uintptr(code.Offset))
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldMarshalJSON:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalJSONPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldMarshalText:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalTextPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldArrayPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArrayPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldSlice:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlice:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldSlicePtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldMap:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMap:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldMapPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldStruct:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyStruct:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b)
code = code.Next
case encoder.OpStructEndInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendStructEnd(ctx, code, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
s := ptrToString(p + uintptr(code.Offset))
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytesPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
code = code.Next
case encoder.OpStructEndOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpEnd:
goto END
}
}
END:
return b, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color/debug_vm.go
================================================
package vm_color
import (
"fmt"
"github.com/goccy/go-json/internal/encoder"
)
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
defer func() {
if err := recover(); err != nil {
w := ctx.Option.DebugOut
fmt.Fprintln(w, "=============[DEBUG]===============")
fmt.Fprintln(w, "* [TYPE]")
fmt.Fprintln(w, codeSet.Type)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [ALL OPCODE]")
fmt.Fprintln(w, code.Dump())
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [CONTEXT]")
fmt.Fprintf(w, "%+v\n", ctx)
fmt.Fprintln(w, "===================================")
panic(err)
}
}()
return Run(ctx, b, codeSet)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color/hack.go
================================================
package vm_color
import (
// HACK: compile order
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_color_indent"
)
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color/util.go
================================================
package vm_color
import (
"encoding/json"
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
const uintptrSize = 4 << (^uintptr(0) >> 63)
var (
errUnsupportedValue = encoder.ErrUnsupportedValue
errUnsupportedFloat = encoder.ErrUnsupportedFloat
mapiterinit = encoder.MapIterInit
mapiterkey = encoder.MapIterKey
mapitervalue = encoder.MapIterValue
mapiternext = encoder.MapIterNext
maplen = encoder.MapLen
)
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
type nonEmptyInterface struct {
itab *struct {
ityp *runtime.Type // static interface type
typ *runtime.Type // dynamic concrete type
// unused fields...
}
ptr unsafe.Pointer
}
func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
}
func load(base uintptr, idx uint32) uintptr {
addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr))
}
func store(base uintptr, idx uint32, p uintptr) {
addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p
}
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr))
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
}
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
return *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
}
func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...)
b = encoder.AppendInt(ctx, b, p, code)
return append(b, format.Footer...)
}
func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Uint
b = append(b, format.Header...)
b = encoder.AppendUint(ctx, b, p, code)
return append(b, format.Footer...)
}
func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte {
format := ctx.Option.ColorScheme.Float
b = append(b, format.Header...)
b = encoder.AppendFloat32(ctx, b, v)
return append(b, format.Footer...)
}
func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte {
format := ctx.Option.ColorScheme.Float
b = append(b, format.Header...)
b = encoder.AppendFloat64(ctx, b, v)
return append(b, format.Footer...)
}
func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte {
format := ctx.Option.ColorScheme.String
b = append(b, format.Header...)
b = encoder.AppendString(ctx, b, v)
return append(b, format.Footer...)
}
func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte {
format := ctx.Option.ColorScheme.Binary
b = append(b, format.Header...)
b = encoder.AppendByteSlice(ctx, b, src)
return append(b, format.Footer...)
}
func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) {
format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...)
bb, err := encoder.AppendNumber(ctx, b, n)
if err != nil {
return nil, err
}
return append(bb, format.Footer...), nil
}
func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte {
format := ctx.Option.ColorScheme.Bool
b = append(b, format.Header...)
if v {
b = append(b, "true"...)
} else {
b = append(b, "false"...)
}
return append(b, format.Footer...)
}
func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(b, format.Footer...)
}
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',')
}
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(append(b, format.Footer...), ',')
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
last := len(b) - 1
b[last] = ':'
return b
}
func appendMapKeyValue(_ *encoder.RuntimeContext, _ *encoder.Opcode, b, key, value []byte) []byte {
b = append(b, key[:len(key)-1]...)
b = append(b, ':')
return append(b, value...)
}
func appendMapEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = '}'
b = append(b, ',')
return b
}
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalJSON(ctx, code, b, v)
}
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
format := ctx.Option.ColorScheme.String
b = append(b, format.Header...)
bb, err := encoder.AppendMarshalText(ctx, code, b, v)
if err != nil {
return nil, err
}
return append(bb, format.Footer...), nil
}
func appendArrayHead(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
return append(b, '[')
}
func appendArrayEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = ']'
return append(b, ',')
}
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '[', ']', ',')
}
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '}', ',')
}
func appendObjectEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = '}'
return append(b, ',')
}
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{')
}
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
format := ctx.Option.ColorScheme.ObjectKey
b = append(b, format.Header...)
b = append(b, code.Key[:len(code.Key)-1]...)
b = append(b, format.Footer...)
return append(b, ':')
}
func appendStructEnd(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte {
return append(b, '}', ',')
}
func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
if b[last] == ',' {
b[last] = '}'
return appendComma(ctx, b)
}
return appendStructEnd(ctx, code, b)
}
func restoreIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, _ uintptr) {}
func storeIndent(_ uintptr, _ *encoder.Opcode, _ uintptr) {}
func appendMapKeyIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
func appendArrayElemIndent(_ *encoder.RuntimeContext, _ *encoder.Opcode, b []byte) []byte { return b }
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color/vm.go
================================================
// Code generated by internal/cmd/generator. DO NOT EDIT!
package vm_color
import (
"math"
"reflect"
"sort"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
recursiveLevel := 0
ptrOffset := uintptr(0)
ctxptr := ctx.Ptr()
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
for {
switch code.Op {
default:
return nil, errUnimplementedOp(code.Op)
case encoder.OpPtr:
p := load(ctxptr, code.Idx)
code = code.Next
store(ctxptr, code.Idx, ptrToPtr(p))
case encoder.OpIntPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInt:
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpUint:
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpIntString:
b = append(b, '"')
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintString:
b = append(b, '"')
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat32Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat32:
b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat64Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat64:
v := ptrToFloat64(load(ctxptr, code.Idx))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStringPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpString:
b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBoolPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBool:
b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBytesPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBytes:
b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpNumberPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpNumber:
bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpInterfacePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInterface:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if p == seen {
return nil, errUnsupportedValue(code, p)
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, p)
var (
typ *runtime.Type
ifacePtr unsafe.Pointer
)
up := ptrToUnsafePtr(p)
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
iface := (*nonEmptyInterface)(up)
ifacePtr = iface.ptr
if iface.itab != nil {
typ = iface.itab.typ
}
} else {
iface := (*emptyInterface)(up)
ifacePtr = iface.ptr
typ = iface.typ
}
if ifacePtr == nil {
isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ)
if !isDirectedNil {
b = appendNullComma(ctx, b)
code = code.Next
break
}
}
ctx.KeepRefs = append(ctx.KeepRefs, up)
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
if err != nil {
return nil, err
}
totalLength := uintptr(code.Length) + 3
nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3
var c *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
c = ifaceCodeSet.InterfaceEscapeKeyCode
} else {
c = ifaceCodeSet.InterfaceNoescapeKeyCode
}
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += totalLength * uintptrSize
oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent += code.Indent
newLen := offsetNum + totalLength + nextTotalLength
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
end := ifaceCodeSet.EndCode
store(ctxptr, c.Idx, uintptr(ifacePtr))
store(ctxptr, end.Idx, oldOffset)
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpInterfaceEnd:
recursiveLevel--
// restore ctxptr
offset := load(ctxptr, code.Idx)
restoreIndent(ctx, code, ctxptr)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
b = append(b, `""`...)
b = appendComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpSlicePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpSlice:
p := load(ctxptr, code.Idx)
slice := ptrToSlice(p)
if p == 0 || slice.Data == nil {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.ElemIdx, 0)
store(ctxptr, code.Length, uintptr(slice.Len))
store(ctxptr, code.Idx, uintptr(slice.Data))
if slice.Len > 0 {
b = appendArrayHead(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, uintptr(slice.Data))
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpSliceElem:
idx := load(ctxptr, code.ElemIdx)
length := load(ctxptr, code.Length)
idx++
if idx < length {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
data := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, data+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpArrayPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpArray:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
if code.Length > 0 {
b = appendArrayHead(ctx, code, b)
store(ctxptr, code.ElemIdx, 0)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpArrayElem:
idx := load(ctxptr, code.ElemIdx)
idx++
if idx < uintptr(code.Length) {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
p := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, p+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpMapPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpMap:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
uptr := ptrToUnsafePtr(p)
mlen := maplen(uptr)
if mlen <= 0 {
b = appendEmptyObject(ctx, b)
code = code.End.Next
break
}
b = appendStructHead(ctx, b)
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
mapiterinit(code.Type, uptr, &mapCtx.Iter)
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
if unorderedMap {
b = appendMapKeyIndent(ctx, code.Next, b)
} else {
mapCtx.Start = len(b)
mapCtx.First = len(b)
}
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
case encoder.OpMapKey:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
idx := mapCtx.Idx
idx++
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
if idx < mapCtx.Len {
b = appendMapKeyIndent(ctx, code, b)
mapCtx.Idx = int(idx)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
b = appendObjectEnd(ctx, code, b)
encoder.ReleaseMapContext(mapCtx)
code = code.End.Next
}
} else {
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
if idx < mapCtx.Len {
mapCtx.Idx = int(idx)
mapCtx.Start = len(b)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
code = code.End
}
}
case encoder.OpMapValue:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
b = appendColon(ctx, b)
} else {
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
mapCtx.Start = len(b)
}
value := mapitervalue(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(value))
mapiternext(&mapCtx.Iter)
code = code.Next
case encoder.OpMapEnd:
// this operation only used by sorted map.
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
sort.Sort(mapCtx.Slice)
buf := mapCtx.Buf
for _, item := range mapCtx.Slice.Items {
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
}
buf = appendMapEnd(ctx, code, buf)
b = b[:mapCtx.First]
b = append(b, buf...)
mapCtx.Buf = buf
encoder.ReleaseMapContext(mapCtx)
code = code.Next
case encoder.OpRecursivePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpRecursive:
ptr := load(ctxptr, code.Idx)
if ptr != 0 {
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if ptr == seen {
return nil, errUnsupportedValue(code, ptr)
}
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, ptr)
c := code.Jmp.Code
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += code.Jmp.CurLen * uintptrSize
oldBaseIndent := ctx.BaseIndent
indentDiffFromTop := c.Indent - 1
ctx.BaseIndent += code.Indent - indentDiffFromTop
newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
store(ctxptr, c.Idx, ptr)
store(ctxptr, c.End.Next.Idx, oldOffset)
store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpRecursiveEnd:
recursiveLevel--
// restore ctxptr
restoreIndent(ctx, code, ctxptr)
offset := load(ctxptr, code.Idx)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpStructPtrHead:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHead:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if len(code.Key) > 0 {
if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
}
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
u64 := ptrToUint64(p, code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset)))))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
}
case encoder.OpStructPtrHeadNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructPtrHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadArray, encoder.OpStructHeadSlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyArray:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyArray:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptySlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptySlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
if maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p)
}
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructField:
if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
p := load(ctxptr, code.Idx) + uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmpty:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringString:
p := load(ctxptr, code.Idx)
s := ptrToString(p + uintptr(code.Offset))
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldMarshalJSON:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalJSONPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldMarshalText:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalTextPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldArrayPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArrayPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldSlice:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlice:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldSlicePtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldMap:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMap:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldMapPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldStruct:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyStruct:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b)
code = code.Next
case encoder.OpStructEndInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendStructEnd(ctx, code, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
s := ptrToString(p + uintptr(code.Offset))
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytesPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
code = code.Next
case encoder.OpStructEndOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpEnd:
goto END
}
}
END:
return b, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/debug_vm.go
================================================
package vm_color_indent
import (
"fmt"
"github.com/goccy/go-json/internal/encoder"
)
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
defer func() {
if err := recover(); err != nil {
w := ctx.Option.DebugOut
fmt.Fprintln(w, "=============[DEBUG]===============")
fmt.Fprintln(w, "* [TYPE]")
fmt.Fprintln(w, codeSet.Type)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [ALL OPCODE]")
fmt.Fprintln(w, code.Dump())
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [CONTEXT]")
fmt.Fprintf(w, "%+v\n", ctx)
fmt.Fprintln(w, "===================================")
panic(err)
}
}()
return Run(ctx, b, codeSet)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go
================================================
package vm_color_indent
import (
"encoding/json"
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
const uintptrSize = 4 << (^uintptr(0) >> 63)
var (
appendIndent = encoder.AppendIndent
appendStructEnd = encoder.AppendStructEndIndent
errUnsupportedValue = encoder.ErrUnsupportedValue
errUnsupportedFloat = encoder.ErrUnsupportedFloat
mapiterinit = encoder.MapIterInit
mapiterkey = encoder.MapIterKey
mapitervalue = encoder.MapIterValue
mapiternext = encoder.MapIterNext
maplen = encoder.MapLen
)
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
type nonEmptyInterface struct {
itab *struct {
ityp *runtime.Type // static interface type
typ *runtime.Type // dynamic concrete type
// unused fields...
}
ptr unsafe.Pointer
}
func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
}
func load(base uintptr, idx uint32) uintptr {
addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr))
}
func store(base uintptr, idx uint32, p uintptr) {
addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p
}
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr))
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
}
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
return *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
}
func appendInt(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...)
b = encoder.AppendInt(ctx, b, p, code)
return append(b, format.Footer...)
}
func appendUint(ctx *encoder.RuntimeContext, b []byte, p uintptr, code *encoder.Opcode) []byte {
format := ctx.Option.ColorScheme.Uint
b = append(b, format.Header...)
b = encoder.AppendUint(ctx, b, p, code)
return append(b, format.Footer...)
}
func appendFloat32(ctx *encoder.RuntimeContext, b []byte, v float32) []byte {
format := ctx.Option.ColorScheme.Float
b = append(b, format.Header...)
b = encoder.AppendFloat32(ctx, b, v)
return append(b, format.Footer...)
}
func appendFloat64(ctx *encoder.RuntimeContext, b []byte, v float64) []byte {
format := ctx.Option.ColorScheme.Float
b = append(b, format.Header...)
b = encoder.AppendFloat64(ctx, b, v)
return append(b, format.Footer...)
}
func appendString(ctx *encoder.RuntimeContext, b []byte, v string) []byte {
format := ctx.Option.ColorScheme.String
b = append(b, format.Header...)
b = encoder.AppendString(ctx, b, v)
return append(b, format.Footer...)
}
func appendByteSlice(ctx *encoder.RuntimeContext, b []byte, src []byte) []byte {
format := ctx.Option.ColorScheme.Binary
b = append(b, format.Header...)
b = encoder.AppendByteSlice(ctx, b, src)
return append(b, format.Footer...)
}
func appendNumber(ctx *encoder.RuntimeContext, b []byte, n json.Number) ([]byte, error) {
format := ctx.Option.ColorScheme.Int
b = append(b, format.Header...)
bb, err := encoder.AppendNumber(ctx, b, n)
if err != nil {
return nil, err
}
return append(bb, format.Footer...), nil
}
func appendBool(ctx *encoder.RuntimeContext, b []byte, v bool) []byte {
format := ctx.Option.ColorScheme.Bool
b = append(b, format.Header...)
if v {
b = append(b, "true"...)
} else {
b = append(b, "false"...)
}
return append(b, format.Footer...)
}
func appendNull(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(b, format.Footer...)
}
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',', '\n')
}
func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {
format := ctx.Option.ColorScheme.Null
b = append(b, format.Header...)
b = append(b, "null"...)
return append(append(b, format.Footer...), ',', '\n')
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ':', ' ')
}
func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte {
b = appendIndent(ctx, b, code.Indent+1)
b = append(b, key...)
b[len(b)-2] = ':'
b[len(b)-1] = ' '
return append(b, value...)
}
func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = b[:len(b)-2]
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent)
return append(b, '}', ',', '\n')
}
func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = append(b, '[', '\n')
return appendIndent(ctx, b, code.Indent+1)
}
func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = b[:len(b)-2]
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent)
return append(b, ']', ',', '\n')
}
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '[', ']', ',', '\n')
}
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '}', ',', '\n')
}
func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = '\n'
b = appendIndent(ctx, b, code.Indent-1)
return append(b, '}', ',', '\n')
}
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalJSONIndent(ctx, code, b, v)
}
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
format := ctx.Option.ColorScheme.String
b = append(b, format.Header...)
bb, err := encoder.AppendMarshalTextIndent(ctx, code, b, v)
if err != nil {
return nil, err
}
return append(bb, format.Footer...), nil
}
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '\n')
}
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = appendIndent(ctx, b, code.Indent)
format := ctx.Option.ColorScheme.ObjectKey
b = append(b, format.Header...)
b = append(b, code.Key[:len(code.Key)-1]...)
b = append(b, format.Footer...)
return append(b, ':', ' ')
}
func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
if b[last-1] == '{' {
b[last] = '}'
} else {
if b[last] == '\n' {
// to remove ',' and '\n' characters
b = b[:len(b)-2]
}
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent-1)
b = append(b, '}')
}
return appendComma(ctx, b)
}
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
ctx.BaseIndent = uint32(load(ctxptr, code.Length))
}
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {
store(ctxptr, code.Length, indent)
}
func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return appendIndent(ctx, b, code.Indent+1)
}
func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return appendIndent(ctx, b, code.Indent)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/vm.go
================================================
// Code generated by internal/cmd/generator. DO NOT EDIT!
package vm_color_indent
import (
"math"
"reflect"
"sort"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
recursiveLevel := 0
ptrOffset := uintptr(0)
ctxptr := ctx.Ptr()
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
for {
switch code.Op {
default:
return nil, errUnimplementedOp(code.Op)
case encoder.OpPtr:
p := load(ctxptr, code.Idx)
code = code.Next
store(ctxptr, code.Idx, ptrToPtr(p))
case encoder.OpIntPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInt:
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpUint:
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpIntString:
b = append(b, '"')
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintString:
b = append(b, '"')
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat32Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat32:
b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat64Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat64:
v := ptrToFloat64(load(ctxptr, code.Idx))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStringPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpString:
b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBoolPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBool:
b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBytesPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBytes:
b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpNumberPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpNumber:
bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpInterfacePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInterface:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if p == seen {
return nil, errUnsupportedValue(code, p)
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, p)
var (
typ *runtime.Type
ifacePtr unsafe.Pointer
)
up := ptrToUnsafePtr(p)
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
iface := (*nonEmptyInterface)(up)
ifacePtr = iface.ptr
if iface.itab != nil {
typ = iface.itab.typ
}
} else {
iface := (*emptyInterface)(up)
ifacePtr = iface.ptr
typ = iface.typ
}
if ifacePtr == nil {
isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ)
if !isDirectedNil {
b = appendNullComma(ctx, b)
code = code.Next
break
}
}
ctx.KeepRefs = append(ctx.KeepRefs, up)
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
if err != nil {
return nil, err
}
totalLength := uintptr(code.Length) + 3
nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3
var c *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
c = ifaceCodeSet.InterfaceEscapeKeyCode
} else {
c = ifaceCodeSet.InterfaceNoescapeKeyCode
}
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += totalLength * uintptrSize
oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent += code.Indent
newLen := offsetNum + totalLength + nextTotalLength
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
end := ifaceCodeSet.EndCode
store(ctxptr, c.Idx, uintptr(ifacePtr))
store(ctxptr, end.Idx, oldOffset)
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpInterfaceEnd:
recursiveLevel--
// restore ctxptr
offset := load(ctxptr, code.Idx)
restoreIndent(ctx, code, ctxptr)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
b = append(b, `""`...)
b = appendComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpSlicePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpSlice:
p := load(ctxptr, code.Idx)
slice := ptrToSlice(p)
if p == 0 || slice.Data == nil {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.ElemIdx, 0)
store(ctxptr, code.Length, uintptr(slice.Len))
store(ctxptr, code.Idx, uintptr(slice.Data))
if slice.Len > 0 {
b = appendArrayHead(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, uintptr(slice.Data))
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpSliceElem:
idx := load(ctxptr, code.ElemIdx)
length := load(ctxptr, code.Length)
idx++
if idx < length {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
data := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, data+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpArrayPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpArray:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
if code.Length > 0 {
b = appendArrayHead(ctx, code, b)
store(ctxptr, code.ElemIdx, 0)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpArrayElem:
idx := load(ctxptr, code.ElemIdx)
idx++
if idx < uintptr(code.Length) {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
p := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, p+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpMapPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpMap:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
uptr := ptrToUnsafePtr(p)
mlen := maplen(uptr)
if mlen <= 0 {
b = appendEmptyObject(ctx, b)
code = code.End.Next
break
}
b = appendStructHead(ctx, b)
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
mapiterinit(code.Type, uptr, &mapCtx.Iter)
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
if unorderedMap {
b = appendMapKeyIndent(ctx, code.Next, b)
} else {
mapCtx.Start = len(b)
mapCtx.First = len(b)
}
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
case encoder.OpMapKey:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
idx := mapCtx.Idx
idx++
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
if idx < mapCtx.Len {
b = appendMapKeyIndent(ctx, code, b)
mapCtx.Idx = int(idx)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
b = appendObjectEnd(ctx, code, b)
encoder.ReleaseMapContext(mapCtx)
code = code.End.Next
}
} else {
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
if idx < mapCtx.Len {
mapCtx.Idx = int(idx)
mapCtx.Start = len(b)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
code = code.End
}
}
case encoder.OpMapValue:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
b = appendColon(ctx, b)
} else {
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
mapCtx.Start = len(b)
}
value := mapitervalue(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(value))
mapiternext(&mapCtx.Iter)
code = code.Next
case encoder.OpMapEnd:
// this operation only used by sorted map.
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
sort.Sort(mapCtx.Slice)
buf := mapCtx.Buf
for _, item := range mapCtx.Slice.Items {
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
}
buf = appendMapEnd(ctx, code, buf)
b = b[:mapCtx.First]
b = append(b, buf...)
mapCtx.Buf = buf
encoder.ReleaseMapContext(mapCtx)
code = code.Next
case encoder.OpRecursivePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpRecursive:
ptr := load(ctxptr, code.Idx)
if ptr != 0 {
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if ptr == seen {
return nil, errUnsupportedValue(code, ptr)
}
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, ptr)
c := code.Jmp.Code
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += code.Jmp.CurLen * uintptrSize
oldBaseIndent := ctx.BaseIndent
indentDiffFromTop := c.Indent - 1
ctx.BaseIndent += code.Indent - indentDiffFromTop
newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
store(ctxptr, c.Idx, ptr)
store(ctxptr, c.End.Next.Idx, oldOffset)
store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpRecursiveEnd:
recursiveLevel--
// restore ctxptr
restoreIndent(ctx, code, ctxptr)
offset := load(ctxptr, code.Idx)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpStructPtrHead:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHead:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if len(code.Key) > 0 {
if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
}
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
u64 := ptrToUint64(p, code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset)))))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
}
case encoder.OpStructPtrHeadNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructPtrHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadArray, encoder.OpStructHeadSlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyArray:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyArray:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptySlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptySlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
if maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p)
}
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructField:
if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
p := load(ctxptr, code.Idx) + uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmpty:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringString:
p := load(ctxptr, code.Idx)
s := ptrToString(p + uintptr(code.Offset))
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldMarshalJSON:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalJSONPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldMarshalText:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalTextPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldArrayPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArrayPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldSlice:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlice:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldSlicePtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldMap:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMap:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldMapPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldStruct:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyStruct:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b)
code = code.Next
case encoder.OpStructEndInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendStructEnd(ctx, code, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
s := ptrToString(p + uintptr(code.Offset))
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytesPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
code = code.Next
case encoder.OpStructEndOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpEnd:
goto END
}
}
END:
return b, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_indent/debug_vm.go
================================================
package vm_indent
import (
"fmt"
"github.com/goccy/go-json/internal/encoder"
)
func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
defer func() {
if err := recover(); err != nil {
w := ctx.Option.DebugOut
fmt.Fprintln(w, "=============[DEBUG]===============")
fmt.Fprintln(w, "* [TYPE]")
fmt.Fprintln(w, codeSet.Type)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [ALL OPCODE]")
fmt.Fprintln(w, code.Dump())
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "* [CONTEXT]")
fmt.Fprintf(w, "%+v\n", ctx)
fmt.Fprintln(w, "===================================")
panic(err)
}
}()
return Run(ctx, b, codeSet)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_indent/hack.go
================================================
package vm_indent
import (
// HACK: compile order
// `vm`, `vm_indent`, `vm_color`, `vm_color_indent` packages uses a lot of memory to compile,
// so forcibly make dependencies and avoid compiling in concurrent.
// dependency order: vm => vm_indent => vm_color => vm_color_indent
_ "github.com/goccy/go-json/internal/encoder/vm_color"
)
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go
================================================
package vm_indent
import (
"encoding/json"
"fmt"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
const uintptrSize = 4 << (^uintptr(0) >> 63)
var (
appendInt = encoder.AppendInt
appendUint = encoder.AppendUint
appendFloat32 = encoder.AppendFloat32
appendFloat64 = encoder.AppendFloat64
appendString = encoder.AppendString
appendByteSlice = encoder.AppendByteSlice
appendNumber = encoder.AppendNumber
appendStructEnd = encoder.AppendStructEndIndent
appendIndent = encoder.AppendIndent
errUnsupportedValue = encoder.ErrUnsupportedValue
errUnsupportedFloat = encoder.ErrUnsupportedFloat
mapiterinit = encoder.MapIterInit
mapiterkey = encoder.MapIterKey
mapitervalue = encoder.MapIterValue
mapiternext = encoder.MapIterNext
maplen = encoder.MapLen
)
type emptyInterface struct {
typ *runtime.Type
ptr unsafe.Pointer
}
type nonEmptyInterface struct {
itab *struct {
ityp *runtime.Type // static interface type
typ *runtime.Type // dynamic concrete type
// unused fields...
}
ptr unsafe.Pointer
}
func errUnimplementedOp(op encoder.OpType) error {
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
}
func load(base uintptr, idx uint32) uintptr {
addr := base + uintptr(idx)
return **(**uintptr)(unsafe.Pointer(&addr))
}
func store(base uintptr, idx uint32, p uintptr) {
addr := base + uintptr(idx)
**(**uintptr)(unsafe.Pointer(&addr)) = p
}
func loadNPtr(base uintptr, idx uint32, ptrNum uint8) uintptr {
addr := base + uintptr(idx)
p := **(**uintptr)(unsafe.Pointer(&addr))
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUint64(p uintptr, bitSize uint8) uint64 {
switch bitSize {
case 8:
return (uint64)(**(**uint8)(unsafe.Pointer(&p)))
case 16:
return (uint64)(**(**uint16)(unsafe.Pointer(&p)))
case 32:
return (uint64)(**(**uint32)(unsafe.Pointer(&p)))
case 64:
return **(**uint64)(unsafe.Pointer(&p))
}
return 0
}
func ptrToFloat32(p uintptr) float32 { return **(**float32)(unsafe.Pointer(&p)) }
func ptrToFloat64(p uintptr) float64 { return **(**float64)(unsafe.Pointer(&p)) }
func ptrToBool(p uintptr) bool { return **(**bool)(unsafe.Pointer(&p)) }
func ptrToBytes(p uintptr) []byte { return **(**[]byte)(unsafe.Pointer(&p)) }
func ptrToNumber(p uintptr) json.Number { return **(**json.Number)(unsafe.Pointer(&p)) }
func ptrToString(p uintptr) string { return **(**string)(unsafe.Pointer(&p)) }
func ptrToSlice(p uintptr) *runtime.SliceHeader { return *(**runtime.SliceHeader)(unsafe.Pointer(&p)) }
func ptrToPtr(p uintptr) uintptr {
return uintptr(**(**unsafe.Pointer)(unsafe.Pointer(&p)))
}
func ptrToNPtr(p uintptr, ptrNum uint8) uintptr {
for i := uint8(0); i < ptrNum; i++ {
if p == 0 {
return 0
}
p = ptrToPtr(p)
}
return p
}
func ptrToUnsafePtr(p uintptr) unsafe.Pointer {
return *(*unsafe.Pointer)(unsafe.Pointer(&p))
}
func ptrToInterface(code *encoder.Opcode, p uintptr) interface{} {
return *(*interface{})(unsafe.Pointer(&emptyInterface{
typ: code.Type,
ptr: *(*unsafe.Pointer)(unsafe.Pointer(&p)),
}))
}
func appendBool(_ *encoder.RuntimeContext, b []byte, v bool) []byte {
if v {
return append(b, "true"...)
}
return append(b, "false"...)
}
func appendNull(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null"...)
}
func appendComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ',', '\n')
}
func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, "null,\n"...)
}
func appendColon(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, ':', ' ')
}
func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte {
b = appendIndent(ctx, b, code.Indent+1)
b = append(b, key...)
b[len(b)-2] = ':'
b[len(b)-1] = ' '
return append(b, value...)
}
func appendMapEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = b[:len(b)-2]
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent)
return append(b, '}', ',', '\n')
}
func appendArrayHead(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = append(b, '[', '\n')
return appendIndent(ctx, b, code.Indent+1)
}
func appendArrayEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = b[:len(b)-2]
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent)
return append(b, ']', ',', '\n')
}
func appendEmptyArray(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '[', ']', ',', '\n')
}
func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '}', ',', '\n')
}
func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
b[last] = '\n'
b = appendIndent(ctx, b, code.Indent-1)
return append(b, '}', ',', '\n')
}
func appendMarshalJSON(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalJSONIndent(ctx, code, b, v)
}
func appendMarshalText(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte, v interface{}) ([]byte, error) {
return encoder.AppendMarshalTextIndent(ctx, code, b, v)
}
func appendStructHead(_ *encoder.RuntimeContext, b []byte) []byte {
return append(b, '{', '\n')
}
func appendStructKey(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
b = appendIndent(ctx, b, code.Indent)
b = append(b, code.Key...)
return append(b, ' ')
}
func appendStructEndSkipLast(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
last := len(b) - 1
if b[last-1] == '{' {
b[last] = '}'
} else {
if b[last] == '\n' {
// to remove ',' and '\n' characters
b = b[:len(b)-2]
}
b = append(b, '\n')
b = appendIndent(ctx, b, code.Indent-1)
b = append(b, '}')
}
return appendComma(ctx, b)
}
func restoreIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, ctxptr uintptr) {
ctx.BaseIndent = uint32(load(ctxptr, code.Length))
}
func storeIndent(ctxptr uintptr, code *encoder.Opcode, indent uintptr) {
store(ctxptr, code.Length, indent)
}
func appendArrayElemIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return appendIndent(ctx, b, code.Indent+1)
}
func appendMapKeyIndent(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {
return appendIndent(ctx, b, code.Indent)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/encoder/vm_indent/vm.go
================================================
// Code generated by internal/cmd/generator. DO NOT EDIT!
package vm_indent
import (
"math"
"reflect"
"sort"
"unsafe"
"github.com/goccy/go-json/internal/encoder"
"github.com/goccy/go-json/internal/runtime"
)
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
recursiveLevel := 0
ptrOffset := uintptr(0)
ctxptr := ctx.Ptr()
var code *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
code = codeSet.EscapeKeyCode
} else {
code = codeSet.NoescapeKeyCode
}
for {
switch code.Op {
default:
return nil, errUnimplementedOp(code.Op)
case encoder.OpPtr:
p := load(ctxptr, code.Idx)
code = code.Next
store(ctxptr, code.Idx, ptrToPtr(p))
case encoder.OpIntPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInt:
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpUint:
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpIntString:
b = append(b, '"')
b = appendInt(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpUintString:
b = append(b, '"')
b = appendUint(ctx, b, load(ctxptr, code.Idx), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat32Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat32:
b = appendFloat32(ctx, b, ptrToFloat32(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpFloat64Ptr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpFloat64:
v := ptrToFloat64(load(ctxptr, code.Idx))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStringPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpString:
b = appendString(ctx, b, ptrToString(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBoolPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBool:
b = appendBool(ctx, b, ptrToBool(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpBytesPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpBytes:
b = appendByteSlice(ctx, b, ptrToBytes(load(ctxptr, code.Idx)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpNumberPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpNumber:
bb, err := appendNumber(ctx, b, ptrToNumber(load(ctxptr, code.Idx)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpInterfacePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpInterface:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if p == seen {
return nil, errUnsupportedValue(code, p)
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, p)
var (
typ *runtime.Type
ifacePtr unsafe.Pointer
)
up := ptrToUnsafePtr(p)
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
iface := (*nonEmptyInterface)(up)
ifacePtr = iface.ptr
if iface.itab != nil {
typ = iface.itab.typ
}
} else {
iface := (*emptyInterface)(up)
ifacePtr = iface.ptr
typ = iface.typ
}
if ifacePtr == nil {
isDirectedNil := typ != nil && typ.Kind() == reflect.Struct && !runtime.IfaceIndir(typ)
if !isDirectedNil {
b = appendNullComma(ctx, b)
code = code.Next
break
}
}
ctx.KeepRefs = append(ctx.KeepRefs, up)
ifaceCodeSet, err := encoder.CompileToGetCodeSet(ctx, uintptr(unsafe.Pointer(typ)))
if err != nil {
return nil, err
}
totalLength := uintptr(code.Length) + 3
nextTotalLength := uintptr(ifaceCodeSet.CodeLength) + 3
var c *encoder.Opcode
if (ctx.Option.Flag & encoder.HTMLEscapeOption) != 0 {
c = ifaceCodeSet.InterfaceEscapeKeyCode
} else {
c = ifaceCodeSet.InterfaceNoescapeKeyCode
}
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += totalLength * uintptrSize
oldBaseIndent := ctx.BaseIndent
ctx.BaseIndent += code.Indent
newLen := offsetNum + totalLength + nextTotalLength
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
end := ifaceCodeSet.EndCode
store(ctxptr, c.Idx, uintptr(ifacePtr))
store(ctxptr, end.Idx, oldOffset)
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpInterfaceEnd:
recursiveLevel--
// restore ctxptr
offset := load(ctxptr, code.Idx)
restoreIndent(ctx, code, ctxptr)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToPtr(p))
fallthrough
case encoder.OpMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
b = append(b, `""`...)
b = appendComma(ctx, b)
code = code.Next
break
}
if (code.Flags&encoder.IsNilableTypeFlags) != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p)
}
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpSlicePtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpSlice:
p := load(ctxptr, code.Idx)
slice := ptrToSlice(p)
if p == 0 || slice.Data == nil {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.ElemIdx, 0)
store(ctxptr, code.Length, uintptr(slice.Len))
store(ctxptr, code.Idx, uintptr(slice.Data))
if slice.Len > 0 {
b = appendArrayHead(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, uintptr(slice.Data))
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpSliceElem:
idx := load(ctxptr, code.ElemIdx)
length := load(ctxptr, code.Length)
idx++
if idx < length {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
data := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, data+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpArrayPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpArray:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
if code.Length > 0 {
b = appendArrayHead(ctx, code, b)
store(ctxptr, code.ElemIdx, 0)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
b = appendEmptyArray(ctx, b)
code = code.End.Next
}
case encoder.OpArrayElem:
idx := load(ctxptr, code.ElemIdx)
idx++
if idx < uintptr(code.Length) {
b = appendArrayElemIndent(ctx, code, b)
store(ctxptr, code.ElemIdx, idx)
p := load(ctxptr, code.Idx)
size := uintptr(code.Size)
code = code.Next
store(ctxptr, code.Idx, p+idx*size)
} else {
b = appendArrayEnd(ctx, code, b)
code = code.End.Next
}
case encoder.OpMapPtr:
p := loadNPtr(ctxptr, code.Idx, code.PtrNum)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
store(ctxptr, code.Idx, p)
fallthrough
case encoder.OpMap:
p := load(ctxptr, code.Idx)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.End.Next
break
}
uptr := ptrToUnsafePtr(p)
mlen := maplen(uptr)
if mlen <= 0 {
b = appendEmptyObject(ctx, b)
code = code.End.Next
break
}
b = appendStructHead(ctx, b)
unorderedMap := (ctx.Option.Flag & encoder.UnorderedMapOption) != 0
mapCtx := encoder.NewMapContext(mlen, unorderedMap)
mapiterinit(code.Type, uptr, &mapCtx.Iter)
store(ctxptr, code.Idx, uintptr(unsafe.Pointer(mapCtx)))
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(mapCtx))
if unorderedMap {
b = appendMapKeyIndent(ctx, code.Next, b)
} else {
mapCtx.Start = len(b)
mapCtx.First = len(b)
}
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
case encoder.OpMapKey:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
idx := mapCtx.Idx
idx++
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
if idx < mapCtx.Len {
b = appendMapKeyIndent(ctx, code, b)
mapCtx.Idx = int(idx)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
b = appendObjectEnd(ctx, code, b)
encoder.ReleaseMapContext(mapCtx)
code = code.End.Next
}
} else {
mapCtx.Slice.Items[mapCtx.Idx].Value = b[mapCtx.Start:len(b)]
if idx < mapCtx.Len {
mapCtx.Idx = int(idx)
mapCtx.Start = len(b)
key := mapiterkey(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(key))
code = code.Next
} else {
code = code.End
}
}
case encoder.OpMapValue:
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
if (ctx.Option.Flag & encoder.UnorderedMapOption) != 0 {
b = appendColon(ctx, b)
} else {
mapCtx.Slice.Items[mapCtx.Idx].Key = b[mapCtx.Start:len(b)]
mapCtx.Start = len(b)
}
value := mapitervalue(&mapCtx.Iter)
store(ctxptr, code.Next.Idx, uintptr(value))
mapiternext(&mapCtx.Iter)
code = code.Next
case encoder.OpMapEnd:
// this operation only used by sorted map.
mapCtx := (*encoder.MapContext)(ptrToUnsafePtr(load(ctxptr, code.Idx)))
sort.Sort(mapCtx.Slice)
buf := mapCtx.Buf
for _, item := range mapCtx.Slice.Items {
buf = appendMapKeyValue(ctx, code, buf, item.Key, item.Value)
}
buf = appendMapEnd(ctx, code, buf)
b = b[:mapCtx.First]
b = append(b, buf...)
mapCtx.Buf = buf
encoder.ReleaseMapContext(mapCtx)
code = code.Next
case encoder.OpRecursivePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
code = code.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpRecursive:
ptr := load(ctxptr, code.Idx)
if ptr != 0 {
if recursiveLevel > encoder.StartDetectingCyclesAfter {
for _, seen := range ctx.SeenPtr {
if ptr == seen {
return nil, errUnsupportedValue(code, ptr)
}
}
}
}
ctx.SeenPtr = append(ctx.SeenPtr, ptr)
c := code.Jmp.Code
curlen := uintptr(len(ctx.Ptrs))
offsetNum := ptrOffset / uintptrSize
oldOffset := ptrOffset
ptrOffset += code.Jmp.CurLen * uintptrSize
oldBaseIndent := ctx.BaseIndent
indentDiffFromTop := c.Indent - 1
ctx.BaseIndent += code.Indent - indentDiffFromTop
newLen := offsetNum + code.Jmp.CurLen + code.Jmp.NextLen
if curlen < newLen {
ctx.Ptrs = append(ctx.Ptrs, make([]uintptr, newLen-curlen)...)
}
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
store(ctxptr, c.Idx, ptr)
store(ctxptr, c.End.Next.Idx, oldOffset)
store(ctxptr, c.End.Next.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
storeIndent(ctxptr, c.End.Next, uintptr(oldBaseIndent))
code = c
recursiveLevel++
case encoder.OpRecursiveEnd:
recursiveLevel--
// restore ctxptr
restoreIndent(ctx, code, ctxptr)
offset := load(ctxptr, code.Idx)
ctx.SeenPtr = ctx.SeenPtr[:len(ctx.SeenPtr)-1]
codePtr := load(ctxptr, code.ElemIdx)
code = (*encoder.Opcode)(ptrToUnsafePtr(codePtr))
ctxptr = ctx.Ptr() + offset
ptrOffset = offset
case encoder.OpStructPtrHead:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHead:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if len(code.Key) > 0 {
if (code.Flags&encoder.IsTaggedKeyFlags) != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
}
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmpty:
p := load(ctxptr, code.Idx)
if p == 0 && ((code.Flags&encoder.IndirectFlags) != 0 || code.Next.Op == encoder.OpStructEnd) {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if p == 0 || (ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyInt:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyInt:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyIntString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
u64 := ptrToUint64(p, code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUint:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUint:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyUintString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat32(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64String:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToFloat64(p + uintptr(code.Offset))
if v == 0 {
code = code.NextField
} else {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNull(ctx, b)
b = appendComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p+uintptr(code.Offset)))))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyStringString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToString(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBool:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBool:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
} else {
code = code.NextField
}
case encoder.OpStructPtrHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytes:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyBytes:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumber:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumber:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
}
case encoder.OpStructPtrHeadNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberString:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
v := ptrToNumber(p + uintptr(code.Offset))
if v == "" {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructPtrHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructPtrHeadArray, encoder.OpStructPtrHeadSlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadArray, encoder.OpStructHeadSlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyArray:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyArray:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptySlice:
if (code.Flags & encoder.IndirectFlags) != 0 {
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptySlice:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadArrayPtr, encoder.OpStructPtrHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadArrayPtr, encoder.OpStructHeadSlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyArrayPtr, encoder.OpStructPtrHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyArrayPtr, encoder.OpStructHeadOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructPtrHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMap:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p != 0 && (code.Flags&encoder.IndirectFlags) != 0 {
p = ptrToPtr(p + uintptr(code.Offset))
}
if maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
b = appendNullComma(ctx, b)
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
break
}
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 {
code = code.NextField
} else {
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructPtrHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalJSON {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalJSON {
p = ptrToPtr(p)
}
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
}
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
if (code.Flags&encoder.IndirectFlags) != 0 || code.Op == encoder.OpStructPtrHeadOmitEmptyMarshalText {
p = ptrToPtr(p)
}
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructPtrHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
b = appendStructKey(ctx, code, b)
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructPtrHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
store(ctxptr, code.Idx, ptrToNPtr(p, code.PtrNum))
fallthrough
case encoder.OpStructHeadOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
if p == 0 && (code.Flags&encoder.IndirectFlags) != 0 {
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendNullComma(ctx, b)
}
code = code.End.Next
break
}
if (code.Flags & encoder.IndirectFlags) != 0 {
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
}
if code.Flags&encoder.AnonymousHeadFlags == 0 {
b = appendStructHead(ctx, b)
}
if p == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
b = appendComma(ctx, b)
code = code.Next
}
case encoder.OpStructField:
if code.Flags&encoder.IsTaggedKeyFlags != 0 || code.Flags&encoder.AnonymousKeyFlags == 0 {
b = appendStructKey(ctx, code, b)
}
p := load(ctxptr, code.Idx) + uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmpty:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNullComma(ctx, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringString:
p := load(ctxptr, code.Idx)
s := ptrToString(p + uintptr(code.Offset))
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
b = appendStructKey(ctx, code, b)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendComma(ctx, b)
}
code = code.Next
case encoder.OpStructFieldMarshalJSON:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSON:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
iface := ptrToInterface(code, p)
if (code.Flags&encoder.NilCheckFlags) != 0 && encoder.IsNilForMarshaler(iface) {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, iface)
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalJSONPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalJSONPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalJSON(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldMarshalText:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalText:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if (code.Flags & encoder.IsNilableTypeFlags) != 0 {
p = ptrToPtr(p)
}
if p == 0 && (code.Flags&encoder.NilCheckFlags) != 0 {
code = code.NextField
break
}
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
code = code.Next
case encoder.OpStructFieldMarshalTextPtr:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = bb
}
b = appendComma(ctx, b)
code = code.Next
case encoder.OpStructFieldOmitEmptyMarshalTextPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendMarshalText(ctx, code, b, ptrToInterface(code, p))
if err != nil {
return nil, err
}
b = appendComma(ctx, bb)
}
code = code.Next
case encoder.OpStructFieldArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArray:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldArrayPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyArrayPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldSlice:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlice:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
slice := ptrToSlice(p)
if slice.Len == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldSlicePtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptySlicePtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldMap:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMap:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p == 0 || maplen(ptrToUnsafePtr(p)) == 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructFieldMapPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyMapPtr:
p := load(ctxptr, code.Idx)
p = ptrToPtr(p + uintptr(code.Offset))
if p != 0 {
p = ptrToNPtr(p, code.PtrNum)
}
if p != 0 {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
} else {
code = code.NextField
}
case encoder.OpStructFieldStruct:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
code = code.Next
store(ctxptr, code.Idx, p)
case encoder.OpStructFieldOmitEmptyStruct:
p := load(ctxptr, code.Idx)
p += uintptr(code.Offset)
if ptrToPtr(p) == 0 && (code.Flags&encoder.IsNextOpPtrTypeFlags) != 0 {
code = code.NextField
} else {
b = appendStructKey(ctx, code, b)
code = code.Next
store(ctxptr, code.Idx, p)
}
case encoder.OpStructEnd:
b = appendStructEndSkipLast(ctx, code, b)
code = code.Next
case encoder.OpStructEndInt:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyInt:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendInt(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendInt(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndIntPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyIntPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendInt(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUint:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUint:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintString:
p := load(ctxptr, code.Idx)
u64 := ptrToUint64(p+uintptr(code.Offset), code.NumBitSize)
v := u64 & ((1 << code.NumBitSize) - 1)
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p+uintptr(code.Offset), code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendUint(ctx, b, p, code)
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendUint(ctx, b, p, code)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndUintPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyUintPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendUint(ctx, b, p, code)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32String:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32String:
p := load(ctxptr, code.Idx)
v := ptrToFloat32(p + uintptr(code.Offset))
if v != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendFloat32(ctx, b, ptrToFloat32(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat32PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat32PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat32(ctx, b, ptrToFloat32(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64String:
p := load(ctxptr, code.Idx)
v := ptrToFloat64(p + uintptr(code.Offset))
if v != 0 {
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64Ptr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
b = appendStructEnd(ctx, code, b)
code = code.Next
break
}
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64Ptr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndFloat64PtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = appendFloat64(ctx, b, v)
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyFloat64PtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
v := ptrToFloat64(p)
if math.IsInf(v, 0) || math.IsNaN(v) {
return nil, errUnsupportedFloat(v)
}
b = append(b, '"')
b = appendFloat64(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
s := ptrToString(p + uintptr(code.Offset))
b = appendString(ctx, b, string(appendString(ctx, []byte{}, s)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringString:
p := load(ctxptr, code.Idx)
v := ptrToString(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, v)))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, ptrToString(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, ptrToString(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndStringPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyStringPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendString(ctx, b, string(appendString(ctx, []byte{}, ptrToString(p))))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBool:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBool:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p+uintptr(code.Offset)))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolString:
p := load(ctxptr, code.Idx)
v := ptrToBool(p + uintptr(code.Offset))
if v {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, v)
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendBool(ctx, b, ptrToBool(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendBool(ctx, b, ptrToBool(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBoolPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBoolPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
b = appendBool(ctx, b, ptrToBool(p))
b = append(b, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytes:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p+uintptr(code.Offset)))
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytes:
p := load(ctxptr, code.Idx)
v := ptrToBytes(p + uintptr(code.Offset))
if len(v) > 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, v)
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndBytesPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = appendByteSlice(ctx, b, ptrToBytes(p))
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyBytesPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = appendByteSlice(ctx, b, ptrToBytes(p))
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumber:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
code = code.Next
case encoder.OpStructEndOmitEmptyNumber:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberString:
p := load(ctxptr, code.Idx)
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p+uintptr(code.Offset)))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberString:
p := load(ctxptr, code.Idx)
v := ptrToNumber(p + uintptr(code.Offset))
if v != "" {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, v)
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtr:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = bb
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtr:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = appendStructEnd(ctx, code, bb)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpStructEndNumberPtrString:
b = appendStructKey(ctx, code, b)
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p == 0 {
b = appendNull(ctx, b)
} else {
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
}
b = appendStructEnd(ctx, code, b)
code = code.Next
case encoder.OpStructEndOmitEmptyNumberPtrString:
p := load(ctxptr, code.Idx)
p = ptrToNPtr(p+uintptr(code.Offset), code.PtrNum)
if p != 0 {
b = appendStructKey(ctx, code, b)
b = append(b, '"')
bb, err := appendNumber(ctx, b, ptrToNumber(p))
if err != nil {
return nil, err
}
b = append(bb, '"')
b = appendStructEnd(ctx, code, b)
} else {
b = appendStructEndSkipLast(ctx, code, b)
}
code = code.Next
case encoder.OpEnd:
goto END
}
}
END:
return b, nil
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/errors/error.go
================================================
package errors
import (
"fmt"
"reflect"
"strconv"
)
type InvalidUTF8Error struct {
S string // the whole string value that caused the error
}
func (e *InvalidUTF8Error) Error() string {
return fmt.Sprintf("json: invalid UTF-8 in string: %s", strconv.Quote(e.S))
}
type InvalidUnmarshalError struct {
Type reflect.Type
}
func (e *InvalidUnmarshalError) Error() string {
if e.Type == nil {
return "json: Unmarshal(nil)"
}
if e.Type.Kind() != reflect.Ptr {
return fmt.Sprintf("json: Unmarshal(non-pointer %s)", e.Type)
}
return fmt.Sprintf("json: Unmarshal(nil %s)", e.Type)
}
// A MarshalerError represents an error from calling a MarshalJSON or MarshalText method.
type MarshalerError struct {
Type reflect.Type
Err error
sourceFunc string
}
func (e *MarshalerError) Error() string {
srcFunc := e.sourceFunc
if srcFunc == "" {
srcFunc = "MarshalJSON"
}
return fmt.Sprintf("json: error calling %s for type %s: %s", srcFunc, e.Type, e.Err.Error())
}
// Unwrap returns the underlying error.
func (e *MarshalerError) Unwrap() error { return e.Err }
// A SyntaxError is a description of a JSON syntax error.
type SyntaxError struct {
msg string // description of error
Offset int64 // error occurred after reading Offset bytes
}
func (e *SyntaxError) Error() string { return e.msg }
// An UnmarshalFieldError describes a JSON object key that
// led to an unexported (and therefore unwritable) struct field.
//
// Deprecated: No longer used; kept for compatibility.
type UnmarshalFieldError struct {
Key string
Type reflect.Type
Field reflect.StructField
}
func (e *UnmarshalFieldError) Error() string {
return fmt.Sprintf("json: cannot unmarshal object key %s into unexported field %s of type %s",
strconv.Quote(e.Key), e.Field.Name, e.Type.String(),
)
}
// An UnmarshalTypeError describes a JSON value that was
// not appropriate for a value of a specific Go type.
type UnmarshalTypeError struct {
Value string // description of JSON value - "bool", "array", "number -5"
Type reflect.Type // type of Go value it could not be assigned to
Offset int64 // error occurred after reading Offset bytes
Struct string // name of the struct type containing the field
Field string // the full path from root node to the field
}
func (e *UnmarshalTypeError) Error() string {
if e.Struct != "" || e.Field != "" {
return fmt.Sprintf("json: cannot unmarshal %s into Go struct field %s.%s of type %s",
e.Value, e.Struct, e.Field, e.Type,
)
}
return fmt.Sprintf("json: cannot unmarshal %s into Go value of type %s", e.Value, e.Type)
}
// An UnsupportedTypeError is returned by Marshal when attempting
// to encode an unsupported value type.
type UnsupportedTypeError struct {
Type reflect.Type
}
func (e *UnsupportedTypeError) Error() string {
return fmt.Sprintf("json: unsupported type: %s", e.Type)
}
type UnsupportedValueError struct {
Value reflect.Value
Str string
}
func (e *UnsupportedValueError) Error() string {
return fmt.Sprintf("json: unsupported value: %s", e.Str)
}
func ErrSyntax(msg string, offset int64) *SyntaxError {
return &SyntaxError{msg: msg, Offset: offset}
}
func ErrMarshaler(typ reflect.Type, err error, msg string) *MarshalerError {
return &MarshalerError{
Type: typ,
Err: err,
sourceFunc: msg,
}
}
func ErrExceededMaxDepth(c byte, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf(`invalid character "%c" exceeded max depth`, c),
Offset: cursor,
}
}
func ErrNotAtBeginningOfValue(cursor int64) *SyntaxError {
return &SyntaxError{msg: "not at beginning of value", Offset: cursor}
}
func ErrUnexpectedEndOfJSON(msg string, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf("json: %s unexpected end of JSON input", msg),
Offset: cursor,
}
}
func ErrExpected(msg string, cursor int64) *SyntaxError {
return &SyntaxError{msg: fmt.Sprintf("expected %s", msg), Offset: cursor}
}
func ErrInvalidCharacter(c byte, context string, cursor int64) *SyntaxError {
if c == 0 {
return &SyntaxError{
msg: fmt.Sprintf("json: invalid character as %s", context),
Offset: cursor,
}
}
return &SyntaxError{
msg: fmt.Sprintf("json: invalid character %c as %s", c, context),
Offset: cursor,
}
}
func ErrInvalidBeginningOfValue(c byte, cursor int64) *SyntaxError {
return &SyntaxError{
msg: fmt.Sprintf("invalid character '%c' looking for beginning of value", c),
Offset: cursor,
}
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/runtime/rtype.go
================================================
package runtime
import (
"reflect"
"unsafe"
)
// Type representing reflect.rtype for noescape trick
type Type struct{}
//go:linkname rtype_Align reflect.(*rtype).Align
//go:noescape
func rtype_Align(*Type) int
func (t *Type) Align() int {
return rtype_Align(t)
}
//go:linkname rtype_FieldAlign reflect.(*rtype).FieldAlign
//go:noescape
func rtype_FieldAlign(*Type) int
func (t *Type) FieldAlign() int {
return rtype_FieldAlign(t)
}
//go:linkname rtype_Method reflect.(*rtype).Method
//go:noescape
func rtype_Method(*Type, int) reflect.Method
func (t *Type) Method(a0 int) reflect.Method {
return rtype_Method(t, a0)
}
//go:linkname rtype_MethodByName reflect.(*rtype).MethodByName
//go:noescape
func rtype_MethodByName(*Type, string) (reflect.Method, bool)
func (t *Type) MethodByName(a0 string) (reflect.Method, bool) {
return rtype_MethodByName(t, a0)
}
//go:linkname rtype_NumMethod reflect.(*rtype).NumMethod
//go:noescape
func rtype_NumMethod(*Type) int
func (t *Type) NumMethod() int {
return rtype_NumMethod(t)
}
//go:linkname rtype_Name reflect.(*rtype).Name
//go:noescape
func rtype_Name(*Type) string
func (t *Type) Name() string {
return rtype_Name(t)
}
//go:linkname rtype_PkgPath reflect.(*rtype).PkgPath
//go:noescape
func rtype_PkgPath(*Type) string
func (t *Type) PkgPath() string {
return rtype_PkgPath(t)
}
//go:linkname rtype_Size reflect.(*rtype).Size
//go:noescape
func rtype_Size(*Type) uintptr
func (t *Type) Size() uintptr {
return rtype_Size(t)
}
//go:linkname rtype_String reflect.(*rtype).String
//go:noescape
func rtype_String(*Type) string
func (t *Type) String() string {
return rtype_String(t)
}
//go:linkname rtype_Kind reflect.(*rtype).Kind
//go:noescape
func rtype_Kind(*Type) reflect.Kind
func (t *Type) Kind() reflect.Kind {
return rtype_Kind(t)
}
//go:linkname rtype_Implements reflect.(*rtype).Implements
//go:noescape
func rtype_Implements(*Type, reflect.Type) bool
func (t *Type) Implements(u reflect.Type) bool {
return rtype_Implements(t, u)
}
//go:linkname rtype_AssignableTo reflect.(*rtype).AssignableTo
//go:noescape
func rtype_AssignableTo(*Type, reflect.Type) bool
func (t *Type) AssignableTo(u reflect.Type) bool {
return rtype_AssignableTo(t, u)
}
//go:linkname rtype_ConvertibleTo reflect.(*rtype).ConvertibleTo
//go:noescape
func rtype_ConvertibleTo(*Type, reflect.Type) bool
func (t *Type) ConvertibleTo(u reflect.Type) bool {
return rtype_ConvertibleTo(t, u)
}
//go:linkname rtype_Comparable reflect.(*rtype).Comparable
//go:noescape
func rtype_Comparable(*Type) bool
func (t *Type) Comparable() bool {
return rtype_Comparable(t)
}
//go:linkname rtype_Bits reflect.(*rtype).Bits
//go:noescape
func rtype_Bits(*Type) int
func (t *Type) Bits() int {
return rtype_Bits(t)
}
//go:linkname rtype_ChanDir reflect.(*rtype).ChanDir
//go:noescape
func rtype_ChanDir(*Type) reflect.ChanDir
func (t *Type) ChanDir() reflect.ChanDir {
return rtype_ChanDir(t)
}
//go:linkname rtype_IsVariadic reflect.(*rtype).IsVariadic
//go:noescape
func rtype_IsVariadic(*Type) bool
func (t *Type) IsVariadic() bool {
return rtype_IsVariadic(t)
}
//go:linkname rtype_Elem reflect.(*rtype).Elem
//go:noescape
func rtype_Elem(*Type) reflect.Type
func (t *Type) Elem() *Type {
return Type2RType(rtype_Elem(t))
}
//go:linkname rtype_Field reflect.(*rtype).Field
//go:noescape
func rtype_Field(*Type, int) reflect.StructField
func (t *Type) Field(i int) reflect.StructField {
return rtype_Field(t, i)
}
//go:linkname rtype_FieldByIndex reflect.(*rtype).FieldByIndex
//go:noescape
func rtype_FieldByIndex(*Type, []int) reflect.StructField
func (t *Type) FieldByIndex(index []int) reflect.StructField {
return rtype_FieldByIndex(t, index)
}
//go:linkname rtype_FieldByName reflect.(*rtype).FieldByName
//go:noescape
func rtype_FieldByName(*Type, string) (reflect.StructField, bool)
func (t *Type) FieldByName(name string) (reflect.StructField, bool) {
return rtype_FieldByName(t, name)
}
//go:linkname rtype_FieldByNameFunc reflect.(*rtype).FieldByNameFunc
//go:noescape
func rtype_FieldByNameFunc(*Type, func(string) bool) (reflect.StructField, bool)
func (t *Type) FieldByNameFunc(match func(string) bool) (reflect.StructField, bool) {
return rtype_FieldByNameFunc(t, match)
}
//go:linkname rtype_In reflect.(*rtype).In
//go:noescape
func rtype_In(*Type, int) reflect.Type
func (t *Type) In(i int) reflect.Type {
return rtype_In(t, i)
}
//go:linkname rtype_Key reflect.(*rtype).Key
//go:noescape
func rtype_Key(*Type) reflect.Type
func (t *Type) Key() *Type {
return Type2RType(rtype_Key(t))
}
//go:linkname rtype_Len reflect.(*rtype).Len
//go:noescape
func rtype_Len(*Type) int
func (t *Type) Len() int {
return rtype_Len(t)
}
//go:linkname rtype_NumField reflect.(*rtype).NumField
//go:noescape
func rtype_NumField(*Type) int
func (t *Type) NumField() int {
return rtype_NumField(t)
}
//go:linkname rtype_NumIn reflect.(*rtype).NumIn
//go:noescape
func rtype_NumIn(*Type) int
func (t *Type) NumIn() int {
return rtype_NumIn(t)
}
//go:linkname rtype_NumOut reflect.(*rtype).NumOut
//go:noescape
func rtype_NumOut(*Type) int
func (t *Type) NumOut() int {
return rtype_NumOut(t)
}
//go:linkname rtype_Out reflect.(*rtype).Out
//go:noescape
func rtype_Out(*Type, int) reflect.Type
//go:linkname PtrTo reflect.(*rtype).ptrTo
//go:noescape
func PtrTo(*Type) *Type
func (t *Type) Out(i int) reflect.Type {
return rtype_Out(t, i)
}
//go:linkname IfaceIndir reflect.ifaceIndir
//go:noescape
func IfaceIndir(*Type) bool
//go:linkname RType2Type reflect.toType
//go:noescape
func RType2Type(t *Type) reflect.Type
//go:nolint structcheck
type emptyInterface struct {
_ *Type
ptr unsafe.Pointer
}
func Type2RType(t reflect.Type) *Type {
return (*Type)(((*emptyInterface)(unsafe.Pointer(&t))).ptr)
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/runtime/struct_field.go
================================================
package runtime
import (
"reflect"
"strings"
"unicode"
)
func getTag(field reflect.StructField) string {
return field.Tag.Get("json")
}
func IsIgnoredStructField(field reflect.StructField) bool {
if field.PkgPath != "" {
if field.Anonymous {
t := field.Type
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Struct {
return true
}
} else {
// private field
return true
}
}
tag := getTag(field)
return tag == "-"
}
type StructTag struct {
Key string
IsTaggedKey bool
IsOmitEmpty bool
IsString bool
Field reflect.StructField
}
type StructTags []*StructTag
func (t StructTags) ExistsKey(key string) bool {
for _, tt := range t {
if tt.Key == key {
return true
}
}
return false
}
func isValidTag(s string) bool {
if s == "" {
return false
}
for _, c := range s {
switch {
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
// Backslash and quote chars are reserved, but
// otherwise any punctuation chars are allowed
// in a tag name.
case !unicode.IsLetter(c) && !unicode.IsDigit(c):
return false
}
}
return true
}
func StructTagFromField(field reflect.StructField) *StructTag {
keyName := field.Name
tag := getTag(field)
st := &StructTag{Field: field}
opts := strings.Split(tag, ",")
if len(opts) > 0 {
if opts[0] != "" && isValidTag(opts[0]) {
keyName = opts[0]
st.IsTaggedKey = true
}
}
st.Key = keyName
if len(opts) > 1 {
for _, opt := range opts[1:] {
switch opt {
case "omitempty":
st.IsOmitEmpty = true
case "string":
st.IsString = true
}
}
}
return st
}
================================================
FILE: vendor/github.com/goccy/go-json/internal/runtime/type.go
================================================
package runtime
import (
"reflect"
"unsafe"
)
type SliceHeader struct {
Data unsafe.Pointer
Len int
Cap int
}
const (
maxAcceptableTypeAddrRange = 1024 * 1024 * 2 // 2 Mib
)
type TypeAddr struct {
BaseTypeAddr uintptr
MaxTypeAddr uintptr
AddrRange uintptr
AddrShift uintptr
}
var (
typeAddr *TypeAddr
alreadyAnalyzed bool
)
//go:linkname typelinks reflect.typelinks
func typelinks() ([]unsafe.Pointer, [][]int32)
//go:linkname rtypeOff reflect.rtypeOff
func rtypeOff(unsafe.Pointer, int32) unsafe.Pointer
func AnalyzeTypeAddr() *TypeAddr {
defer func() {
alreadyAnalyzed = true
}()
if alreadyAnalyzed {
return typeAddr
}
sections, offsets := typelinks()
if len(sections) != 1 {
return nil
}
if len(offsets) != 1 {
return nil
}
section := sections[0]
offset := offsets[0]
var (
min uintptr = uintptr(^uint(0))
max uintptr = 0
isAligned64 = true
isAligned32 = true
)
for i := 0; i < len(offset); i++ {
typ := (*Type)(rtypeOff(section, offset[i]))
addr := uintptr(unsafe.Pointer(typ))
if min > addr {
min = addr
}
if max < addr {
max = addr
}
if typ.Kind() == reflect.Ptr {
addr = uintptr(unsafe.Pointer(typ.Elem()))
if min > addr {
min = addr
}
if max < addr {
max = addr
}
}
isAligned64 = isAligned64 && (addr-min)&63 == 0
isAligned32 = isAligned32 && (addr-min)&31 == 0
}
addrRange := max - min
if addrRange == 0 {
return nil
}
var addrShift uintptr
if isAligned64 {
addrShift = 6
} else if isAligned32 {
addrShift = 5
}
cacheSize := addrRange >> addrShift
if cacheSize > maxAcceptableTypeAddrRange {
return nil
}
typeAddr = &TypeAddr{
BaseTypeAddr: min,
MaxTypeAddr: max,
AddrRange: addrRange,
AddrShift: addrShift,
}
return typeAddr
}
================================================
FILE: vendor/github.com/goccy/go-json/json.go
================================================
package json
import (
"bytes"
"context"
"encoding/json"
"github.com/goccy/go-json/internal/encoder"
)
// Marshaler is the interface implemented by types that
// can marshal themselves into valid JSON.
type Marshaler interface {
MarshalJSON() ([]byte, error)
}
// MarshalerContext is the interface implemented by types that
// can marshal themselves into valid JSON with context.Context.
type MarshalerContext interface {
MarshalJSON(context.Context) ([]byte, error)
}
// Unmarshaler is the interface implemented by types
// that can unmarshal a JSON description of themselves.
// The input can be assumed to be a valid encoding of
// a JSON value. UnmarshalJSON must copy the JSON data
// if it wishes to retain the data after returning.
//
// By convention, to approximate the behavior of Unmarshal itself,
// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
type Unmarshaler interface {
UnmarshalJSON([]byte) error
}
// UnmarshalerContext is the interface implemented by types
// that can unmarshal with context.Context a JSON description of themselves.
type UnmarshalerContext interface {
UnmarshalJSON(context.Context, []byte) error
}
// Marshal returns the JSON encoding of v.
//
// Marshal traverses the value v recursively.
// If an encountered value implements the Marshaler interface
// and is not a nil pointer, Marshal calls its MarshalJSON method
// to produce JSON. If no MarshalJSON method is present but the
// value implements encoding.TextMarshaler instead, Marshal calls
// its MarshalText method and encodes the result as a JSON string.
// The nil pointer exception is not strictly necessary
// but mimics a similar, necessary exception in the behavior of
// UnmarshalJSON.
//
// Otherwise, Marshal uses the following type-dependent default encodings:
//
// Boolean values encode as JSON booleans.
//
// Floating point, integer, and Number values encode as JSON numbers.
//
// String values encode as JSON strings coerced to valid UTF-8,
// replacing invalid bytes with the Unicode replacement rune.
// The angle brackets "<" and ">" are escaped to "\u003c" and "\u003e"
// to keep some browsers from misinterpreting JSON output as HTML.
// Ampersand "&" is also escaped to "\u0026" for the same reason.
// This escaping can be disabled using an Encoder that had SetEscapeHTML(false)
// called on it.
//
// Array and slice values encode as JSON arrays, except that
// []byte encodes as a base64-encoded string, and a nil slice
// encodes as the null JSON value.
//
// Struct values encode as JSON objects.
// Each exported struct field becomes a member of the object, using the
// field name as the object key, unless the field is omitted for one of the
// reasons given below.
//
// The encoding of each struct field can be customized by the format string
// stored under the "json" key in the struct field's tag.
// The format string gives the name of the field, possibly followed by a
// comma-separated list of options. The name may be empty in order to
// specify options without overriding the default field name.
//
// The "omitempty" option specifies that the field should be omitted
// from the encoding if the field has an empty value, defined as
// false, 0, a nil pointer, a nil interface value, and any empty array,
// slice, map, or string.
//
// As a special case, if the field tag is "-", the field is always omitted.
// Note that a field with name "-" can still be generated using the tag "-,".
//
// Examples of struct field tags and their meanings:
//
// // Field appears in JSON as key "myName".
// Field int `json:"myName"`
//
// // Field appears in JSON as key "myName" and
// // the field is omitted from the object if its value is empty,
// // as defined above.
// Field int `json:"myName,omitempty"`
//
// // Field appears in JSON as key "Field" (the default), but
// // the field is skipped if empty.
// // Note the leading comma.
// Field int `json:",omitempty"`
//
// // Field is ignored by this package.
// Field int `json:"-"`
//
// // Field appears in JSON as key "-".
// Field int `json:"-,"`
//
// The "string" option signals that a field is stored as JSON inside a
// JSON-encoded string. It applies only to fields of string, floating point,
// integer, or boolean types. This extra level of encoding is sometimes used
// when communicating with JavaScript programs:
//
// Int64String int64 `json:",string"`
//
// The key name will be used if it's a non-empty string consisting of
// only Unicode letters, digits, and ASCII punctuation except quotation
// marks, backslash, and comma.
//
// Anonymous struct fields are usually marshaled as if their inner exported fields
// were fields in the outer struct, subject to the usual Go visibility rules amended
// as described in the next paragraph.
// An anonymous struct field with a name given in its JSON tag is treated as
// having that name, rather than being anonymous.
// An anonymous struct field of interface type is treated the same as having
// that type as its name, rather than being anonymous.
//
// The Go visibility rules for struct fields are amended for JSON when
// deciding which field to marshal or unmarshal. If there are
// multiple fields at the same level, and that level is the least
// nested (and would therefore be the nesting level selected by the
// usual Go rules), the following extra rules apply:
//
// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
// even if there are multiple untagged fields that would otherwise conflict.
//
// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
//
// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
//
// Handling of anonymous struct fields is new in Go 1.1.
// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
// an anonymous struct field in both current and earlier versions, give the field
// a JSON tag of "-".
//
// Map values encode as JSON objects. The map's key type must either be a
// string, an integer type, or implement encoding.TextMarshaler. The map keys
// are sorted and used as JSON object keys by applying the following rules,
// subject to the UTF-8 coercion described for string values above:
// - string keys are used directly
// - encoding.TextMarshalers are marshaled
// - integer keys are converted to strings
//
// Pointer values encode as the value pointed to.
// A nil pointer encodes as the null JSON value.
//
// Interface values encode as the value contained in the interface.
// A nil interface value encodes as the null JSON value.
//
// Channel, complex, and function values cannot be encoded in JSON.
// Attempting to encode such a value causes Marshal to return
// an UnsupportedTypeError.
//
// JSON cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in
// an infinite recursion.
//
func Marshal(v interface{}) ([]byte, error) {
return MarshalWithOption(v)
}
// MarshalNoEscape returns the JSON encoding of v and doesn't escape v.
func MarshalNoEscape(v interface{}) ([]byte, error) {
return marshalNoEscape(v)
}
// MarshalContext returns the JSON encoding of v with context.Context and EncodeOption.
func MarshalContext(ctx context.Context, v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
return marshalContext(ctx, v, optFuncs...)
}
// MarshalWithOption returns the JSON encoding of v with EncodeOption.
func MarshalWithOption(v interface{}, optFuncs ...EncodeOptionFunc) ([]byte, error) {
return marshal(v, optFuncs...)
}
// MarshalIndent is like Marshal but applies Indent to format the output.
// Each JSON element in the output will begin on a new line beginning with prefix
// followed by one or more copies of indent according to the indentation nesting.
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) {
return MarshalIndentWithOption(v, prefix, indent)
}
// MarshalIndentWithOption is like Marshal but applies Indent to format the output with EncodeOption.
func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...EncodeOptionFunc) ([]byte, error) {
return marshalIndent(v, prefix, indent, optFuncs...)
}
// Unmarshal parses the JSON-encoded data and stores the result
// in the value pointed to by v. If v is nil or not a pointer,
// Unmarshal returns an InvalidUnmarshalError.
//
// Unmarshal uses the inverse of the encodings that
// Marshal uses, allocating maps, slices, and pointers as necessary,
// with the following additional rules:
//
// To unmarshal JSON into a pointer, Unmarshal first handles the case of
// the JSON being the JSON literal null. In that case, Unmarshal sets
// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
// the value pointed at by the pointer. If the pointer is nil, Unmarshal
// allocates a new value for it to point to.
//
// To unmarshal JSON into a value implementing the Unmarshaler interface,
// Unmarshal calls that value's UnmarshalJSON method, including
// when the input is a JSON null.
// Otherwise, if the value implements encoding.TextUnmarshaler
// and the input is a JSON quoted string, Unmarshal calls that value's
// UnmarshalText method with the unquoted form of the string.
//
// To unmarshal JSON into a struct, Unmarshal matches incoming object
// keys to the keys used by Marshal (either the struct field name or its tag),
// preferring an exact match but also accepting a case-insensitive match. By
// default, object keys which don't have a corresponding struct field are
// ignored (see Decoder.DisallowUnknownFields for an alternative).
//
// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface value:
//
// bool, for JSON booleans
// float64, for JSON numbers
// string, for JSON strings
// []interface{}, for JSON arrays
// map[string]interface{}, for JSON objects
// nil for JSON null
//
// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
// to zero and then appends each element to the slice.
// As a special case, to unmarshal an empty JSON array into a slice,
// Unmarshal replaces the slice with a new empty slice.
//
// To unmarshal a JSON array into a Go array, Unmarshal decodes
// JSON array elements into corresponding Go array elements.
// If the Go array is smaller than the JSON array,
// the additional JSON array elements are discarded.
// If the JSON array is smaller than the Go array,
// the additional Go array elements are set to zero values.
//
// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
// reuses the existing map, keeping existing entries. Unmarshal then stores
// key-value pairs from the JSON object into the map. The map's key type must
// either be any string type, an integer, implement json.Unmarshaler, or
// implement encoding.TextUnmarshaler.
//
// If a JSON value is not appropriate for a given target type,
// or if a JSON number overflows the target type, Unmarshal
// skips that field and completes the unmarshaling as best it can.
// If no more serious errors are encountered, Unmarshal returns
// an UnmarshalTypeError describing the earliest such error. In any
// case, it's not guaranteed that all the remaining fields following
// the problematic one will be unmarshaled into the target object.
//
// The JSON null value unmarshals into an interface, map, pointer, or slice
// by setting that Go value to nil. Because null is often used in JSON to mean
// ``not present,'' unmarshaling a JSON null into any other Go type has no effect
// on the value and produces no error.
//
// When unmarshaling quoted strings, invalid UTF-8 or
// invalid UTF-16 surrogate pairs are not treated as an error.
// Instead, they are replaced by the Unicode replacement
// character U+FFFD.
//
func Unmarshal(data []byte, v interface{}) error {
return unmarshal(data, v)
}
// UnmarshalContext parses the JSON-encoded data and stores the result
// in the value pointed to by v. If you implement the UnmarshalerContext interface,
// call it with ctx as an argument.
func UnmarshalContext(ctx context.Context, data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
return unmarshalContext(ctx, data, v)
}
func UnmarshalWithOption(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
return unmarshal(data, v, optFuncs...)
}
func UnmarshalNoEscape(data []byte, v interface{}, optFuncs ...DecodeOptionFunc) error {
return unmarshalNoEscape(data, v, optFuncs...)
}
// A Token holds a value of one of these types:
//
// Delim, for the four JSON delimiters [ ] { }
// bool, for JSON booleans
// float64, for JSON numbers
// Number, for JSON numbers
// string, for JSON string literals
// nil, for JSON null
//
type Token = json.Token
// A Number represents a JSON number literal.
type Number = json.Number
// RawMessage is a raw encoded JSON value.
// It implements Marshaler and Unmarshaler and can
// be used to delay JSON decoding or precompute a JSON encoding.
type RawMessage = json.RawMessage
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
type Delim = json.Delim
// Compact appends to dst the JSON-encoded src with
// insignificant space characters elided.
func Compact(dst *bytes.Buffer, src []byte) error {
return encoder.Compact(dst, src, false)
}
// Indent appends to dst an indented form of the JSON-encoded src.
// Each element in a JSON object or array begins on a new,
// indented line beginning with prefix followed by one or more
// copies of indent according to the indentation nesting.
// The data appended to dst does not begin with the prefix nor
// any indentation, to make it easier to embed inside other formatted JSON data.
// Although leading space characters (space, tab, carriage return, newline)
// at the beginning of src are dropped, trailing space characters
// at the end of src are preserved and copied to dst.
// For example, if src has no trailing spaces, neither will dst;
// if src ends in a trailing newline, so will dst.
func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
return encoder.Indent(dst, src, prefix, indent)
}
// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
// so that the JSON will be safe to embed inside HTML