Since Go doesn't support unions, and because the translation format is a bit
wacky with the same field having multiple types, we must resort to
introspection to switch between single-item translation (for singular), and
multi-items ones (for plurals).
Previously, introspection was done at runtime, which is not only slow, but will
also only catch typing errors while trying to use the translations. The current
approach is to use a struct with a different field per possible type, and
implement a custom unmarshaller to dispatch the translations to the right one.
This should marginally reduce the memory consumption since interface-boxing
doesn't happen anymore, speed up the translations matching, and enforce proper
typing earlier. This also allows us to remove a bunch of now-useless tests.
As stated in the documentation:
> Read calls io.ReadFull on Reader and crashes the program irrecoverably if an
error is returned. The default Reader uses operating system APIs that are
documented to never return an error on all but legacy Linux systems.
- Use an iterator instead of generating a whole slice when iterating on the selection.
- Using an iterator allows to use a for-loop construct, instead of a lambda,
which is a bit clearer
- Do the filtering Find()'s selector, instead of in the loop, which doesn't
matter much now that we're using an iterator, but it makes the code a bit
more obvious/simpler, and likely reduces a bit the number of iterations.
There is no need to materialize the whole text content of the selection only to
count its number of commas. As we already have a getLengthOfTextContent
function that is pretty similar, this commit refactors it to make it more
generic, in the form of a map/fold(+).
- Don't define the queries before possible early returns
- Check for the presence of the href attribute in the queries, instead of later
on iterating on the selection
- Add two edge-cases to the tests
- Use EachIter instead of Each, if only to avoid the lambda
There is no need to try to match the regexp over the whole input, having it
anchored is enough. If we feel extra-lenient, we might strip spaces in
front/tail, but I don't think it's necessary.
This commit also invert a condition to reduce the level of nested indentation,
and make a condition stricter.
Instead of doing some ciphers manipulation before instantiating the http.Transport
and then assigning them, instantiate http.Transport, and then in an if do the
manipulation. This makes the code a bit clearer, which is always nice when it
comes to cryptographic shenanigans.
- Surface the faulty line number when trying to parse it
- Use strings.Cut instead of strings.SplitN
- Use strings.TrimSuffix instead of an if
- Simplify parseStringList and make its code more compact
There is no need to allocate half a kilobyte of memory only check that a buffer
starts with a bunch of spaces and a `{`, 32b should be more than enough. Also,
no need to allocate it on the heap, having it on the stack works perfectly.
- Reuse isAudio and isVideo instead of re-implementing them
- In IsImage, return early is the mimetype is enough, instead of systematically
lowercasing the url as well.
- Extract the common parts of the two ProxifyAbsoluteURL implementations into a
private function, make the code smaller and clearer.
- Fix a logic error where `A && B || C` was used instead of `A && (B || C)
Instead of using an ugly (and incomplete) regex, let's use a simple for-loop to
parse ISO8601 dates, and make it explicit that we're only supporting a subset
of the spec, as we only care about youtube video durations.
There is no need to use a mutex to check the length of the proxies list,
as it's read-only during the whole lifetime of a ProxyRotator structure.
Moreover, it's a bit clearer to explicitly wrap the 2 lines of mutex-needing
operations between a Lock/Unlock instead of using a defer.