{"id":412273,"date":"2024-06-29T22:26:30","date_gmt":"2024-06-29T22:26:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=412273"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=412273","title":{"rendered":"<span>32 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 Rust \u043a\u0440\u0435\u0439\u0442\u0430, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043a\u0440\u0435\u0439\u0442\u0430\u0445 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430 rust, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438\u043b\u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u044e\u0442 \u0435\u0433\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0438\u0448\u0443\u0442 \u043d\u0430 rust.<\/p>\n<p>\u0414\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a\u0440\u0435\u0439\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c.<\/p>\n<p>\u041f\u043e\u0434 \u043a\u0440\u0435\u0439\u0442\u043e\u043c (crate) \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0430\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u042f \u043d\u0435 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0441\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u0432 \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u0432\u0430\u0441 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b \u043a\u0440\u0435\u0439\u0442, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0438\u043c \u043d\u0430 <a href=\"https:\/\/crates.io\" rel=\"noopener noreferrer nofollow\">crates.io<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/docs.rs\" rel=\"noopener noreferrer nofollow\">docs.rs<\/a>.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044f \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u0441\u0435\u043c\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043a\u0440\u0435\u0439\u0442\u044b \u043a\u0430\u043a <code>serde<\/code>, <code>anyhow<\/code>, <code>itertools<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<h3>Preface<\/h3>\n<p>\u0412\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 rust, \u0438\u043c\u0435\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u0438 \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, \u0432 \u044d\u0442\u043e\u043c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0438 \u0432\u043e\u0442 \u043f\u043e\u0447\u0435\u043c\u0443. Rust \u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044b\u0441\u043e\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 third-party \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c, \u0430 \u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 \u044f\u0437\u044b\u043a\u0430. \u0412 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f rust \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 cargo, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c. \u0412\u043c\u0435\u0441\u0442\u0435 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0440\u0435\u0439\u0442\u0430\u043c rust \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0438\u043c\u0435\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u043b\u0435\u0433\u0430\u0441\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u0430\u0451\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u043c\u0438 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u044b \u044f\u0437\u044b\u043a\u0430 \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443. \u0412\u044b\u0448\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u0435\u0439\u0442\u044b \u0432 \u0441\u0442\u0438\u043b\u0435 Unix way, \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u0436\u0434\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u043d\u0443 \u0432\u0435\u0449\u044c \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0451 \u0445\u043e\u0440\u043e\u0448\u043e.<\/p>\n<p>\u041f\u043e\u0434\u0445\u043e\u0434 &#171;batteries included&#187;, \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0439 \u0432 python, \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 1990-\u0435 \u0433\u043e\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u041f\u041e \u043d\u0435 \u0431\u044b\u043b\u043e \u0442\u0430\u043a\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c. \u0421\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a <a href=\"https:\/\/peps.python.org\/pep-0594\/\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430\u043c \u043f\u043e \u043e\u0447\u0438\u0441\u0442\u043a\u0435<\/a> \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 python.<\/p>\n<h3>tap<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u0432 \u0441\u0443\u0444\u0444\u0438\u043a\u0441\u043d\u0443\u044e. \u0422\u0430\u043a\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0432\u0441\u0435\u0433\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432:<\/p>\n<pre><code class=\"rust\">let val = last(   third(     second(first(original_value), another_arg)   ),   another_arg, ); <\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043d\u0430 \u043a\u0430\u043a:<\/p>\n<pre><code class=\"rust\">let val = original_value   .pipe(first)   .pipe(|v| second(v, another_arg))   .pipe(third)   .pipe(|v| last(v, another_arg)); <\/code><\/pre>\n<p>\u0418\u043b\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 &#171;\u043d\u0430 \u043c\u0435\u0441\u0442\u0435&#187; \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>sort()<\/code>, \u0447\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0441\u0434\u0435\u043b\u0430\u0432 \u0435\u0451 \u0441\u043d\u043e\u0432\u0430 \u043d\u0435\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439:<\/p>\n<pre><code class=\"rust\">let mut collection = stream().collect::&lt;Vec&lt;_>>(); collection.sort(); \/\/ potential error site: inserting other mutations here let collection = collection; \/\/ now immutable <\/code><\/pre>\n<p>\u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 <code>.tap_mut<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043f\u043e \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435:<\/p>\n<pre><code class=\"rust\">let collection = stream.collect::&lt;Vec&lt;_>>().tap_mut(|v| v.sort()); <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>collection<\/code> \u043b\u0438\u0448\u044c \u0440\u0430\u0437 \u0438 \u0441\u0434\u0435\u043b\u0430\u0432 \u0435\u0451 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043d\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0432\u043b\u0438\u044f\u043d\u0438\u044f \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u043d \u043a\u0430\u043a \u0438 &#171;\u043d\u0430\u0438\u0432\u043d\u0430\u044f&#187; \u0432\u0435\u0440\u0441\u0438\u044f.<\/p>\n<p>\u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e \u0432 \u043e\u0431\u043e\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043a\u043e\u0434 \u0441\u0442\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u0438\u0441\u044c \u043e\u0442 \u043b\u0438\u0448\u043d\u0438\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 chain-like \u0432\u0438\u0434, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0435 \u043f\u0440\u044b\u0433\u0430\u044f \u0433\u043b\u0430\u0437\u0430\u043c\u0438 \u043f\u043e \u0441\u0442\u0440\u043e\u0447\u043a\u0430\u043c.<\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <code>tap_x_dbg<\/code> \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 debug \u0440\u0435\u0436\u0438\u043c\u0435 \u0438 \u0443\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432 relese \u0440\u0435\u0436\u0438\u043c\u0435. \u0422\u0430\u043a\u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0441\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0442\u0438\u043f\u0430\u043c\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u043c\u0438 <code>Into<\/code> \u0442\u0440\u0435\u0439\u0442.<\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430.<\/p>\n<h3>strum<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 boilerplate \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0435\u043d\u0430\u043c\u0430\u043c\u0438 \u0432 \u0440\u0430\u0441\u0442\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0437\u0430 \u0441\u0447\u0451\u0442 <code>derive<\/code> \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430:<\/p>\n<ol>\n<li>\n<p><code>strum::Display<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>std::fmt::Display<\/code> \u0434\u043b\u044f \u0435\u043d\u0430\u043c\u0430 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u0442\u043e\u0434 <code>to_string() -> String<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>strum::AsRefStr<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>AsRef&lt;&amp;static str><\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 \u043a\u0430\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>to_string()<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>strum::IntoStaticStr<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>From&lt;MyEnum> for &amp;'static str<\/code>. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumString<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>std::str::FromStr<\/code> \u0438 <code>std::convert::TryFrom&lt;&amp;str><\/code>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u0435\u043d\u0430\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumCount<\/code> &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 <code>COUNT: usize<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0435\u043d\u0430\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumIter<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c \u0435\u043d\u0430\u043c\u0430. \u0414\u0430\u043d\u043d\u044b\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0432 <code>Default::default()<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 <a href=\"https:\/\/docs.rs\/strum\/latest\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430<\/a>.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0432\u044b\u0448\u0435:<\/p>\n<pre><code class=\"rust\">#[derive(     Debug,     PartialEq,     strum::Display,     strum::IntoStaticStr,     strum::AsRefStr,     strum::EnumString,     strum::EnumCount,     strum::EnumIter, )] enum Color {     Red,     Blue(usize),     Green { range: usize }, }  \/\/ convertions to String and &amp;'static str assert_eq!(Color::Blue(2).to_string(), \"Blue\"); assert_eq!(Color::Green { range: 5 }.as_ref(), \"Green\"); assert_eq!(&lt;&amp;str>::from(Color::Red), \"Red\");  assert_eq!(Color::Red, Color::from_str(\"Red\").unwrap()); assert_eq!(Color::COUNT, 3); assert_eq!(     Color::iter().collect::&lt;Vec&lt;_>>(),     vec![Color::Red, Color::Blue(0), Color::Green { range: 0 }] ); <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0430\u043d\u0430\u043c\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>#[strum(serialize = \"redred\")]<\/code>.<\/p>\n<h3>derive_more<\/h3>\n<p>\u0412 \u0440\u0430\u0441\u0442\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u0435\u043d \u043f\u0430\u0442\u0442\u0435\u0440 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c NewType. \u0421\u0443\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 &#171;\u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0438&#187; \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u043d\u0430\u0448\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code class=\"rust\">pub struct NonEmptyVec(Vec&lt;i32>); <\/code><\/pre>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439:<\/p>\n<pre><code class=\"rust\">impl NonEmptyVec {     pub fn new(numbers: Vec&lt;i32>) -> Result&lt;Self> {         if numbers.is_empty() {             bail!(\"expected non empty vector of integers\")         } else {             Ok(Self(numbers))         }     } } <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u041c\u0438\u043d\u0443\u0441\u043e\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430-\u0432\u0440\u0430\u043f\u043f\u0435\u0440 <code>NonEmptyVec<\/code> \u043d\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0442\u0438\u043f\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 <code>IntoIterator<\/code>? \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"rust\">fn collector(iter: impl IntoIterator&lt;Item = i32>) -> Vec&lt;i32> {     iter.into_iter().collect() }  #[test] fn non_emtpy_vec() -> Result&lt;()> {     let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;     assert_eq!(collector(non_empty), vec![1, 2, 3]);     Ok(()) } <\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"rust\">impl IntoIterator for NonEmptyVec {     type Item = &lt;Vec&lt;i32> as IntoIterator>::Item;     type IntoIter = &lt;Vec&lt;i32> as IntoIterator>::IntoIter;      fn into_iter(self) -> Self::IntoIter {         &lt;Vec&lt;i32> as IntoIterator>::into_iter(self.0)     } } <\/code><\/pre>\n<p>\u041d\u043e \u043f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e boilerplate \u043a\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0442\u0438\u043f\u0430. \u0418\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 derive \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b-\u0432\u0440\u0430\u043f\u043f\u0435\u0440\u0430:<\/p>\n<pre><code class=\"rust\">#[derive(derive_more::AsRef, derive_more::Deref, derive_more::IntoIterator, derive_more::Index)] pub struct NonEmptyVec(Vec&lt;i32>); <\/code><\/pre>\n<p>\u0418 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"rust\">fn collector(iter: impl IntoIterator&lt;Item = i32>) -> Vec&lt;i32> {     iter.into_iter().collect() }  #[test] fn non_emtpy_vec() -> Result&lt;()> {     assert!(NonEmptyVec::new(vec![]).is_err());      let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;     assert_eq!(non_empty.as_ref(), &amp;[1, 2, 3]);     assert_eq!(non_empty.deref(), &amp;[1, 2, 3]);     assert_eq!(non_empty[1], 2);     assert_eq!(collector(non_empty), vec![1, 2, 3]);     Ok(()) } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0442\u0440\u0435\u0439\u0442\u043e\u0432.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 (<code>From<\/code>, <code>IntoIterator<\/code>, <code>AsRef<\/code>, etc), \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (<code>Display<\/code>-like), \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 (<code>Add<\/code>, <code>Index<\/code>, etc), \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<code>Constructor<\/code>, <code>Unwap<\/code>, etc).<\/p>\n<h3>derive_builder<\/h3>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0432 \u0440\u0430\u0441\u0442\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f builder [<a href=\"https:\/\/doc.rust-lang.org\/1.0.0\/style\/ownership\/builders.html\" rel=\"noopener noreferrer nofollow\">1<\/a>, <a href=\"https:\/\/rust-unofficial.github.io\/patterns\/patterns\/creational\/builder.html\" rel=\"noopener noreferrer nofollow\">2<\/a>]. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0443\u0434\u043e\u0431\u0435\u043d, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>Calculation<\/code> &#8212; \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 &#8212; \u0430 \u0437\u0430\u0442\u0435\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u0435:<\/p>\n<pre><code class=\"rust\">#[derive(Debug, Eq, PartialEq)] struct Calculation {     a: Option&lt;i32>,     b: Option&lt;i32>,     c: Option&lt;i32>,     d: Option&lt;i32>,     \/\/ ... can be more optional fields }  fn qwe() -> Calculation {     \/\/ does complex calculation     Calculation {         a: Some(1),         b: None,         c: None,         d: None,     } }  fn asd() -> Calculation {     \/\/ does complex calculation     Calculation {         a: Some(6),         b: None,         c: None,         d: Some(7),     } }  fn zxc() -> Calculation {     \/\/ does complex calculation     Calculation {         a: None,         b: Some(2),         c: Some(3),         d: None,     } }  #[test] fn test() -> Result&lt;()> {     assert_eq!(         qwe(),         Calculation {             a: Some(1),             b: None,             c: None,             d: None,         }     );     assert_eq!(         asd(),         Calculation {             a: Some(6),             b: None,             c: None,             d: Some(7),         }     );     assert_eq!(         zxc(),         Calculation {             a: None,             b: Some(2),             c: Some(3),             d: None,         }     );      Ok(()) } <\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>derive_builder<\/code>:<\/p>\n<pre><code class=\"rust\">#[derive(Debug, Eq, PartialEq, Default, derive_builder::Builder)] \/\/ setters calls can be chained, each call clones builder #[builder(pattern = \"immutable\")] \/\/ if field not set then it would be default (None in our case) #[builder(default)] \/\/ setter method accepts T as argument and field value would be Some(T) #[builder(setter(strip_option))] struct Calculation {     a: Option&lt;i32>,     b: Option&lt;i32>,     c: Option&lt;i32>,     d: Option&lt;i32>,     \/\/ ... can be more optional fields }  fn qwe() -> Calculation { \/* same as before *\/ }  fn asd() -> Calculation { \/* same as before *\/ }  fn zxc() -> Calculation { \/* same as before *\/ } <\/code><\/pre>\n<p>\u041a\u0440\u0435\u0439\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0431\u0438\u043b\u0434\u0435\u0440 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>CalculationBuilder<\/code> \u0438 \u0441\u0435\u0442\u0442\u0435\u0440\u0430\u043c\u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0442\u0435\u0441\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0440\u043e\u0447\u0435:<\/p>\n<pre><code class=\"rust\">#[test] fn derive_builder() -> Result&lt;()> {     let builder = CalculationBuilder::default();     assert_eq!(qwe(), builder.a(1).build()?);     assert_eq!(asd(), builder.a(6).d(7).build()?);     assert_eq!(zxc(), builder.b(2).c(3).build()?);      Ok(()) } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0441\u0432\u043e\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u043c \u043f\u043e\u043b\u044f\u043c \u0438 \u0442\u0435\u0441\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0440\u043e\u0447\u0435. \u0415\u0441\u043b\u0438 \u0431\u044b \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0431\u044b\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u0442\u043e \u0438 \u0432\u044b\u0438\u0433\u0440\u044b\u0448 \u0432 \u043a\u0440\u0430\u0442\u043a\u043e\u0441\u0442\u0438 \u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u0431\u044b\u043b \u0432\u044b\u0448\u0435.<\/p>\n<p>\u042d\u0442\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>builder<\/code> \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442. \u0422\u0430\u043a\u0436\u0435 \u043a\u0440\u0435\u0439\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u0435\u0439 \u0431\u0438\u043b\u0434\u0435\u0440\u0430 \u0432 <code>build<\/code> \u043c\u0435\u0442\u043e\u0434\u0435 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u043e\u0432 \u0431\u0438\u043b\u0434\u0435\u0440\u043e\u0432 (owned, mutable, immutable).<\/p>\n<p>\u041f\u043e\u0436\u0430\u043b\u0443\u0439 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 \u044d\u0442\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c\u044b\u0439 <code>build<\/code> \u043c\u0435\u0442\u043e\u0434 \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>Result&lt;T><\/code>, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 <code>T<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439, \u043a\u0430\u043a \u0432 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<h3>insta<\/h3>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0441\u043d\u0430\u043f\u0448\u043e\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0421\u043d\u0430\u043f\u0448\u043e\u0442 &#8212; \u043e\u0436\u0438\u0434\u0430\u043c\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0435\u0441\u0442\u0430, \u043e\u0431\u044b\u0447\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0439 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 command line \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043d\u0430\u043f\u0448\u043e\u0442\u043e\u0432. \u041a\u0440\u0435\u0439\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0444\u0438\u0447, \u043c\u043e\u0436\u043d\u043e \u0441 \u043d\u0438\u043c\u0438 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c <a href=\"https:\/\/insta.rs\/docs\/\" rel=\"noopener noreferrer nofollow\">\u0433\u0430\u0439\u0434\u0435<\/a>.<\/p>\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0438\u0447, \u043f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>redactions<\/code>. \u041e\u043d\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441 \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u043c\u0438 \u043f\u043e\u043b\u044f\u043c\u0438 \u0438\u043b\u0438 \u0441 \u043d\u0435\u0434\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u043c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>HashSet<\/code>:<\/p>\n<pre><code class=\"rust\">#[derive(serde::Serialize)] pub struct User {     id: Uuid,     username: String,     flags: HashSet&lt;&amp;'static str>, }  #[test] fn redactions() {     let user = User {         id: Uuid::new_v4(),         username: \"john_doe\".to_string(),         flags: maplit::hashset! {\"zzz\", \"foo\", \"aha\"},     };     insta::assert_yaml_snapshot!(user, {         \".id\" => \"[uuid]\",         \/\/ make hashset order deterministing         \".flags\" => insta::sorted_redaction()     }); } <\/code><\/pre>\n<p>\u0414\u043b\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0431\u044b\u043b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d \u0441\u043d\u0430\u043f\u0448\u043e\u0442 <code>snapshots\/insta__tests__redactions.snap<\/code> \u0441 \u0434\u0430\u043d\u043d\u044b\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435\u043c:<\/p>\n<pre><code class=\"rust\">--- source: src\/bin\/insta.rs expression: user --- id: \"[uuid]\" username: john_doe flags:   - aha   - foo   - zzz <\/code><\/pre>\n<h3>enum_dispatch<\/h3>\n<p>\u0420\u0430\u0441\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0438\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432. \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0438\u0441\u043f\u0430\u0442\u0447\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u044e, \u0442\u043e \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435\u0433\u0430\u0442\u0438\u0432\u043d\u043e \u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0439\u0442\u0430 \u0438\u0449\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 vtable \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u0439\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0438\u0440\u0438\u0437\u0430\u0446\u0438\u044e \u0432 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0435\u043d\u0430\u043c\u0430. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0442\u0430\u043a\u043e\u0439 \u0442\u0440\u0435\u0439\u0442 \u0438 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<pre><code class=\"rust\">pub trait ReturnsValue {     fn return_value(&amp;self) -> usize; }  pub struct Zero;  impl ReturnsValue for Zero {     fn return_value(&amp;self) -> usize {         0     } }  pub struct Any(usize);  impl ReturnsValue for Any {     fn return_value(&amp;self) -> usize {         self.0     } } <\/code><\/pre>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0434\u0438\u0441\u043f\u0435\u0442\u0447\u0438\u0440\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"rust\">#[test] fn derive_dispatch_dynamic() {     let values: Vec&lt;Box&lt;dyn ReturnsValue>> = vec![Box::new(Zero {}), Box::new(Any(5))];      assert_eq!(         values             .into_iter()             .map(|dispatched| dispatched.return_value())             .collect::&lt;Vec&lt;_>>(),         vec![0, 5]     ); } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u0442\u0440\u0435\u0439\u0442:<\/p>\n<pre><code class=\"rust\">#[enum_dispatch::enum_dispatch] pub trait ReturnsValue {     fn return_value(&amp;self) -> usize; }  \/\/ trait implementations are same  #[enum_dispatch::enum_dispatch(ReturnsValue)] pub enum EnumDispatched {     Zero,     Any, }  #[test] fn derive_dispatch_static() {     let values = vec![EnumDispatched::Zero(Zero {}), EnumDispatched::Any(Any(5))];      assert_eq!(         values             .into_iter()             .map(|dispatched| dispatched.return_value())             .collect::&lt;Vec&lt;_>>(),         vec![0, 5]     ); } <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043a\u0440\u0435\u0439\u0442 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0437\u0430 \u043d\u0430\u0441 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0442\u0440\u0435\u0439\u0442\u0430 <code>ReturnsValue<\/code> \u0434\u043b\u044f \u0435\u043d\u0430\u043c\u0430 <code>EnumDispatched<\/code>. \u0410\u0432\u0442\u043e\u0440\u044b \u043a\u0440\u0435\u0439\u0442\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u043b\u0438 \u0437\u0430\u043c\u0435\u0440\u044b \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u0432\u044b\u044f\u0441\u043d\u0438\u043b\u0438, \u0447\u0442\u043e \u0442\u0430\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0439\u0442\u0430 \u0434\u043e 10-12 \u0440\u0430\u0437.<\/p>\n<p>\u041d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 \u0434\u0430\u043d\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/www.reddit.com\/r\/rust\/comments\/a7n5hb\/comment\/ec5a9ew\" rel=\"noopener noreferrer nofollow\">\u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0440\u0435\u0439\u0442\u0430, \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u0440\u0435\u0439\u0442\u0435<\/a>. \u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0430\u043a\u0440\u043e\u0441 <code>#[enum_dispatch::enum_dispatch]<\/code> \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 \u0442\u0440\u0435\u0439\u0442 (\u0447\u0442\u043e\u0431\u044b <code>enum_dispatch<\/code> \u0441\u043c\u043e\u0433 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0442\u0440\u0435\u0439\u0442\u0430). \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u043c\u0430\u043a\u0440\u043e\u0441 \u043a \u0442\u0440\u0435\u0439\u0442\u0443 \u043c\u043e\u0436\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0432\u0430\u0448\u0435\u043c \u043a\u0440\u0435\u0439\u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h3>paste<\/h3>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f nightly. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e \u043f\u0440\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u0430 \u0438 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b-\u043b\u0438\u0442\u0435\u0440\u0430\u043b\u044b.<\/p>\n<p>\u0421\u043e\u043a\u0440\u0430\u0449\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0437 readme \u043a\u0440\u0435\u0439\u0442\u0430. \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0430\u043a\u0440\u043e\u0441 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 impl \u0431\u043b\u043e\u043a \u0434\u043b\u044f \u0442\u0438\u043f\u0430 \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>$name<\/code> \u0438 \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u043c\u0435\u0442\u043e\u0434\u044b-\u0433\u0435\u0442\u0442\u0435\u0440\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e <code>$field<\/code>.<\/p>\n<pre><code class=\"rust\">macro_rules! make_a_struct_and_getters {     ($name:ident { $($field:ident),* }) => {         \/\/ ...          \/\/ Build an impl block with getters. This expands to:         \/\/     impl S {         \/\/         pub fn get_a(&amp;self) -> &amp;str { &amp;self.a }         \/\/         pub fn get_b(&amp;self) -> &amp;str { &amp;self.b }         \/\/         pub fn get_c(&amp;self) -> &amp;str { &amp;self.c }         \/\/     }         paste! {             impl $name {                 $(                     pub fn [&lt;get_ $field>](&amp;self) -> &amp;str {                         &amp;self.$field                     }                 )*             }         }     } }  make_a_struct_and_getters!(S { a, b, c });  fn call_some_getters(s: &amp;S) -> bool {     s.get_a() == s.get_b() &amp;&amp; s.get_c().is_empty() } <\/code><\/pre>\n<h3>either<\/h3>\n<p>\u0415\u043d\u0430\u043c \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>Either<\/code> \u0441 \u0434\u0432\u0443\u043c\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c\u0438 <code>Left<\/code> \u0438 <code>Right<\/code>. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c \u0435\u043d\u0430\u043c\u043e\u043c.<\/p>\n<pre><code class=\"rust\">use either::Either;  #[test] fn test() {     let values = vec![         Either::Left(1),         Either::Right(true),         Either::Left(10),         Either::Right(false),     ];     assert_eq!(         values             .into_iter()             .map(|int_or_bool| -> Either&lt;i32, bool> {                 let int = either::try_left!(int_or_bool);                 Either::Left(int * 2)             })             .map(|int_or_bool| { either::for_both!(int_or_bool, s => s.to_string()) })             .collect::&lt;Vec&lt;_>>(),         [\"2\", \"true\", \"20\", \"false\"]     ); } <\/code><\/pre>\n<h3>num<\/h3>\n<p>\u041a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u0445 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0438 \u0442\u0438\u043f\u043e\u0432. \u0412\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u044f \u0434\u0436\u0435\u043d\u0435\u0440\u0438\u043a\u0438 \u0434\u043b\u044f \u0447\u0438\u0441\u0435\u043b, \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0447\u0438\u0441\u043b\u0430 (big integers), \u043a\u043e\u043c\u043f\u043b\u0435\u043a\u0441\u043d\u044b\u0435 \u0447\u0438\u0441\u043b\u0430 \u0438 \u0442\u0434.<\/p>\n<pre><code class=\"rust\">use anyhow::{anyhow, Result}; use num::*; use std::fmt::Display;  fn bounds_to_string&lt;N: Bounded + Display>(number: N) -> String {     format!(         \"value {} min is {} max is {}\",         number,         N::min_value(),         N::max_value()     ) }  #[test] fn bounds() {     assert_eq!(bounds_to_string(12u8), \"value 12 min is 0 max is 255\");     assert_eq!(         bounds_to_string(33i16),         \"value 33 min is -32768 max is 32767\"     ); }  fn num_operations&lt;N: Num>(a: &amp;str, b: N) -> Result&lt;N> {     let a = N::from_str_radix(a, 10).map_err(|_| anyhow!(\"could not conert value\"))?;     let value = a + b - N::one();     Ok(if value.is_zero() {         value     } else {         value * (N::one() + N::one())     }) }  #[test] fn test_num_operations() -> Result&lt;()> {     assert_eq!(num_operations(\"2\", 10i32)?, 22i32);     assert_eq!(num_operations(\"-5\", 6i8)?, 0i8);     Ok(()) }  #[test] fn greatest_common_divisor() -> Result&lt;()> {     assert_eq!(num::integer::gcd(25u8, 15u8), 5);     assert_eq!(num::integer::gcd(1024i32, 65536i32), 1024);     Ok(()) } <\/code><\/pre>\n<h3>thiserror<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>std::error::Error<\/code> \u0442\u0440\u0435\u0439\u0442\u0430 \u043d\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438 \u0435\u043d\u0430\u043c\u044b.<\/p>\n<p>\u0421 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0435\u0441\u0442\u044c 2 \u0442\u0438\u043f\u0430 \u043a\u0440\u0435\u0439\u0442\u043e\u0432: \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u0430\u043a third-party \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. \u0414\u043b\u044f \u043a\u0440\u0435\u0439\u0442\u043e\u0432-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432\u0430\u0436\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043c\u043e\u0433 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043a\u0430\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0432 \u043a\u043e\u0434\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0432\u0438\u0434\u043e\u0432 \u043e\u0448\u0438\u0431\u043e\u043a. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0432\u0432\u043e\u0434\u0430-\u0432\u044b\u0432\u043e\u0434\u0430, \u0430 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u0430\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0430\u043d\u0438\u043a\u0443. \u0414\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043e\u0431\u044b\u0447\u043d\u043e \u043d\u0435 \u0432\u0430\u0436\u0435\u043d \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \u043e\u0448\u0438\u0431\u043e\u043a, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043e\u0431\u044b\u0447\u043d\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0442 \u0442\u0438\u043f <code>Result&lt;T, anyhow::Error><\/code>, \u0442\u0430\u043a \u043a\u0430\u043a <code>anyhow<\/code> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0432 <code>anyhow::Error<\/code> \u0442\u0438\u043f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>?<\/code> \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0438\u043b\u0438 <code>From<\/code> \u0442\u0440\u0435\u0439\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0442\u0443\u0442: <a href=\"https:\/\/blog.burntsushi.net\/rust-error-handling\/\" rel=\"noopener noreferrer nofollow\">[1]<\/a> (\u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0430\u0440\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f) \u0438 <a href=\"https:\/\/www.shuttle.rs\/blog\/2022\/06\/30\/error-handling\" rel=\"noopener noreferrer nofollow\">[2]<\/a> (\u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0430\u044f).<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u043a\u0440\u0435\u0439\u0442\u0430\u0445-\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"rust\">#[derive(thiserror::Error, Debug)] pub enum SomeError {     #[error(\"io error\")]     Io(#[from] std::io::Error),     #[error(\"int parsing error\")]     ParseInt(#[from] std::num::ParseIntError),     #[error(\"unknown error\")]     General(#[from] anyhow::Error), }  \/\/\/ library func fn int_error(s: &amp;str) -> Result&lt;i32, SomeError> {     let num = i32::from_str_radix(s, 10)?;     Ok(num + 2) }  #[test] fn test() {     \/\/ application code     assert!(matches!(int_error(\"abc\").unwrap_err(), SomeError::ParseInt(_)));     assert!(matches!(         std::io::Error::new(std::io::ErrorKind::Other, \"oh no!\").into(),         SomeError::Io(_)     )); } <\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u043e\u0448\u0438\u0431\u043a\u0430 <code>std::num::ParseIntError<\/code> \u0431\u044b\u043b\u0430 \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 <code>SomeError::ParseInt<\/code> \u0435\u043d\u0430\u043c. \u0411\u0435\u0437 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<h3>rayon<\/h3>\n<p>\u041e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u0438\u0437\u043c\u0430 \u0432 \u0440\u0430\u0441\u0442\u0435. \u041f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435. \u0413\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0433\u043e\u043d\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 (data-race). \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u044e\u0442 \u0441\u0432\u043e\u0451 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438.<\/p>\n<pre><code class=\"rust\">use rayon::prelude::*; fn sum_of_squares(input: &amp;[i32]) -> i32 {     input          .par_iter() \/\/ &lt;-- just change that!          .map(|&amp;i| i * i)          .sum() } <\/code><\/pre>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0432\u044b\u0448\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u0431\u044b\u043b \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0451\u043d \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u043c \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c <code>iter()<\/code> \u0432 <code>par_iter()<\/code>.<\/p>\n<h3>crossbeam<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: \u0430\u0442\u043e\u043c\u0438\u043a\u0438, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u044c\u044e, \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0442\u0440\u0435\u0434\u043e\u0432 \u0438 \u0442\u0434.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u043e\u0432 (channels) \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043a\u0430\u043d\u0430\u043b\u0430\u043c\u0438 std (\u043f\u043e \u0437\u0430\u0432\u0435\u0440\u0435\u043d\u0438\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432) \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 (multi-producer multi-consumer) \u0432 \u043e\u0442\u043b\u0438\u0438\u0438 \u043e\u0442 std \u043a\u0430\u043d\u0430\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u044e\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0447\u0438\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0442\u043e\u043a (multi-producer single-consumer).<\/p>\n<h3>async_trait<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0442\u0440\u0435\u0439\u0442\u044b \u0441 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438. \u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0430\u0441\u0442 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u0442\u0440\u0435\u0439\u0442\u044b \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430 \u044f\u0437\u044b\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u043e\u0438\u043c\u0451\u043d\u043d\u044b\u0439 \u043c\u0430\u043a\u0440\u043e\u0441 \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430. \u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043f\u043e\u0447\u0435\u043c\u0443 <a href=\"https:\/\/smallcultfollowing.com\/babysteps\/blog\/2019\/10\/26\/async-fn-in-traits-are-hard\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0434\u0435\u0441\u044c<\/a>.<\/p>\n<pre><code class=\"rust\">use async_trait::async_trait;  #[async_trait] trait Advertisement {     async fn run(&amp;self); }  struct Modal;  #[async_trait] impl Advertisement for Modal {     async fn run(&amp;self) {         self.render_fullscreen().await;         for _ in 0..4u16 {             remind_user_to_join_mailing_list().await;         }         self.hide_for_now().await;     } } <\/code><\/pre>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u0442\u0443\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b\u0438 <code>Pin&lt;Box&lt;dyn Future + Send + 'async_trait>><\/code>.<\/p>\n<h3>fs-err<\/h3>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u0432\u0440\u0430\u043f\u043f\u0435\u0440\u044b \u0441 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u043e\u0448\u0438\u0431\u043a\u0430\u043c\u0438 \u0434\u043b\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438\u0437 <code>std::fs<\/code>.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438\u0437 <code>std::fs<\/code> (\u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>read_to_string<\/code> \u0438\u043b\u0438 <code>write<\/code>) \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b \u0437\u0430\u043c\u0435\u0447\u0430\u043b\u0438, \u0447\u0442\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c:<\/p>\n<pre><code class=\"rust\">let content = File::open(\"file-not-exist.txt\")?; let config = File::open(\"config-not-exist.txt\")?;  \/\/ error message would be: \/\/ The system cannot find the file specified. (os error 2) <\/code><\/pre>\n<p>\u0418\u0437 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a\u043e\u0439 \u0438\u0437 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. \u041d\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>fs-err<\/code> \u043a\u0440\u0435\u0439\u0442, \u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435:<\/p>\n<pre><code>failed to open file `config-not-exist.txt`     caused by: The system cannot find the file specified. (os error 2) <\/code><\/pre>\n<h3>tempfile<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439.<\/p>\n<pre><code class=\"rust\">\/\/ Write let mut tmpfile: File = tempfile::tempfile().unwrap(); write!(tmpfile, \"Hello World!\").unwrap();  \/\/ Seek to start tmpfile.seek(SeekFrom::Start(0)).unwrap();  \/\/ Read let mut buf = String::new(); tmpfile.read_to_string(&amp;mut buf).unwrap(); assert_eq!(\"Hello World!\", buf); <\/code><\/pre>\n<h3>bincode<\/h3>\n<p>\u0415\u043d\u043a\u043e\u0434\u0435\u0440 \u0438 \u0434\u0435\u043a\u043e\u0434\u0435\u0440 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442\u043e\u0432 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043d\u0430 \u0434\u0438\u0441\u043a\u0435 \u0438 \u0434\u043b\u044f \u043e\u0431\u043c\u0435\u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u043c\u0435\u0436\u0434\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430\u043c\u0438 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430.<\/p>\n<pre><code class=\"rust\">use anyhow::Result; use serde::{de::DeserializeOwned, Deserialize, Serialize};  #[derive(Serialize, Deserialize, PartialEq, Debug)] struct Entity {     number: i8,     name: String, }  fn check&lt;T>(value: &amp;T, expected_size: usize) where     T: Serialize + DeserializeOwned + PartialEq + std::fmt::Debug, {     let encoded: Vec&lt;u8> = bincode::serialize(&amp;value).unwrap();     assert_eq!(encoded.len(), expected_size);      let decoded: T = bincode::deserialize(&amp;encoded[..]).unwrap();     assert_eq!(value, &amp;decoded); }  #[test] fn test() -> Result&lt;()> {     let first_size = 9; \/\/ i8 + u64 for string length     check(&amp;Entity {number: 1, name: \"\".to_owned()}, first_size);     let second_size = 15; \/\/ i8 + u64 for string length + 6 bytes of string     check(&amp;Entity {number: 2, name: \"string\".to_owned()}, second_size);     Ok(()) } <\/code><\/pre>\n<h3>maplit<\/h3>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0438\u043f\u043e\u0432-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0438\u0437 std. \u041f\u043e \u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u0434\u0435\u043b\u043e \u0432\u043a\u0443\u0441\u0430, \u0432\u0435\u0434\u044c \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438\u043c\u0435\u044e\u0442 <code>from<\/code> \u0438 <code>from_iter<\/code> \u043c\u0435\u0442\u043e\u0434\u044b. \u0415\u0441\u0442\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u0439 <a href=\"https:\/\/github.com\/rust-lang\/rfcs\/issues\/542\" rel=\"noopener noreferrer nofollow\">RFC<\/a> \u043d\u0430 \u044d\u0442\u0443 \u0442\u0435\u043c\u0443.<\/p>\n<pre><code class=\"rust\">let a = btreemap! {     \"a\" => vec![1, 2, 3],     \"b\" => vec![4, 5, 6],     \"c\" => vec![7, 8, 9], }; \/\/ vs let b = BTreeMap::from([     (\"a\", vec![1, 2, 3]),     (\"b\", vec![4, 5, 6]),     (\"c\", vec![7, 8, 9]), ]); <\/code><\/pre>\n<h3>indexmap<\/h3>\n<p>\u0425\u044d\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u043d\u0435\u0451. \u0422\u043e \u0435\u0441\u0442\u044c \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u0445\u044d\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u0432 \u0442\u043e\u043c \u0436\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0447\u0442\u043e \u0438 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u0441\u0442\u0430\u0432\u043a\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043e \u0442\u0435\u0445 \u043f\u043e\u0440, \u043f\u043e\u043a\u0430 \u0432\u044b \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0435 \u043c\u0435\u0442\u043e\u0434 <code>remove<\/code>. \u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438 \u043f\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u044b\u043c \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c (\u043a\u0430\u043a \u043c\u0430\u0441\u0441\u0438\u0432) \u0438 \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e \u043f\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c. \u0412\u0441\u0435 \u044d\u0442\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0438\u0437 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e <a href=\"https:\/\/github.com\/bluss\/indexmap\/blob\/11ac52c3c828a42d69c5fb3248198511836bfd2f\/src\/map\/core.rs#L24-L30\" rel=\"noopener noreferrer nofollow\">\u0432\u043d\u0443\u0442\u0440\u0438 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f<\/a> \u0432\u0435\u043a\u0442\u043e\u0440 \u043f\u0430\u0440 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438 \u0445\u044d\u0448-\u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u043e\u0442 \u0445\u044d\u0448\u0435\u0439 \u043a\u043b\u044e\u0447\u0435\u0439 \u043a \u0438\u0445 \u0438\u043d\u0434\u0435\u043a\u0441\u0430\u043c \u0432 \u0432\u0435\u043a\u0442\u043e\u0440\u0435. \u0421\u0442\u043e\u0438\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438.<\/p>\n<h3>getset<\/h3>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u043f\u043e\u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0431\u044b\u0432\u0448\u0438\u043c Java \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430\u043c. \u041a\u0440\u0435\u0439\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0433\u0435\u0442\u0442\u0435\u0440\u043e\u0432 \u0438 \u0441\u0435\u0442\u0442\u0435\u0440\u043e\u0432.<\/p>\n<pre><code class=\"rust\">use getset::{CopyGetters, Getters, MutGetters, Setters};  #[derive(Getters, Setters, MutGetters, CopyGetters, Default)] pub struct Foo&lt;T> where     T: Copy + Clone + Default, {     \/\/\/ Doc comments are supported!     \/\/\/ Multiline, even.     #[getset(get, set, get_mut)]     private: T,      \/\/\/ Doc comments are supported!     \/\/\/ Multiline, even.     #[getset(get_copy = \"pub\", set = \"pub\", get_mut = \"pub\")]     public: T, }  fn main() {     let mut foo = Foo::default();     foo.set_private(1);     (*foo.private_mut()) += 1;     assert_eq!(*foo.private(), 2); } <\/code><\/pre>\n<h3>mockall<\/h3>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f mock \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043b\u044f (\u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435\u0445) \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440. \u0414\u0430\u043d\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u044e\u043d\u0438\u0442-\u0442\u0435\u0441\u0442\u0430\u0445 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u043e\u0432 \u0438\u043b\u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c\u044b\u0435 \u043a\u0440\u0430\u0439\u043d\u0438\u0435 \u0441\u043b\u0443\u0447\u0430\u0438.<\/p>\n<pre><code class=\"rust\">#[cfg(test)] use mockall::{automock, predicate::*};  #[cfg_attr(test, automock)] trait CalcTrait {     fn foo(&amp;self, x: u32) -> u32; }  fn calculation(calc: impl CalcTrait, x: u32) -> u32 {     calc.foo(x) }  #[test] fn test() {     let mut mock = MockCalcTrait::new();     mock.expect_foo().with(eq(4)).times(1).returning(|x| x + 1);      assert_eq!(5, calculation(mock, 4)); } <\/code><\/pre>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c mock \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0435\u0441\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e attribute-\u043c\u0430\u043a\u0440\u043e\u0441\u0430 <code>#[automock]<\/code>. \u041d\u043e \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u0441\u0432\u043e\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u043d\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u044b\u0439 \u043c\u0430\u043a\u0440\u043e\u0441 <code>mock!<\/code> \u0441 \u0431\u043e\u043b\u0435\u0435 \u0440\u0443\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 mock \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432.<\/p>\n<h3>quickcheck<\/h3>\n<p>\u0424\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u041f\u0440\u0438 \u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u043e\u0448\u0438\u0431\u043a\u0438 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0435\u0441\u0442-\u043a\u0435\u0439\u0441 \u0434\u043b\u044f \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<pre><code class=\"rust\">#[cfg(test)] mod tests {     fn reverse&lt;T: Clone>(xs: &amp;[T]) -> Vec&lt;T> {         let mut rev = vec!();         for x in xs {             rev.insert(0, x.clone())         }         rev     }      #[quickcheck]     fn double_reversal_is_identity(xs: Vec&lt;isize>) -> bool {         xs == reverse(&amp;reverse(&amp;xs))     } } <\/code><\/pre>\n<h3>proptest<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0438 <code>quickcheck<\/code> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u043e\u043c \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432. \u041d\u043e \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 <a href=\"https:\/\/github.com\/proptest-rs\/proptest\/blob\/master\/proptest\/README.md#differences-between-quickcheck-and-proptest\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/a> \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 <code>quickcheck<\/code>, \u0445\u043e\u0442\u044f \u0434\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u0434\u043e\u043b\u044c\u0448\u0435 \u0447\u0435\u043c <code>quickcheck<\/code>.<\/p>\n<pre><code class=\"rust\">proptest! {     #[test]     fn doesnt_crash(s in \"\\\\PC*\") {         parse_date(&amp;s);     }      #[test]     fn parses_date_back_to_original(y in 0u32..10000,                                     m in 1u32..13,                                     d in 1u32..32)     {         let result = parse_date(&amp;format!(\"{:04}-{:02}-{:02}\", y, m, d)).unwrap();          prop_assert_eq!((y, m, d), result);     } } <\/code><\/pre>\n<h3>heck<\/h3>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u0431\u0449\u0435\u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0435 \u0441\u0442\u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>CamelCase<\/code>, <code>snake_case<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <a href=\"https:\/\/docs.rs\/sqlx\/latest\/sqlx\/trait.FromRow.html#rename_all\" rel=\"noopener noreferrer nofollow\">rename_all<\/a> \u0432 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 <code>sqlx<\/code>, \u0442\u043e <a href=\"https:\/\/github.com\/launchbadge\/sqlx\/blob\/4f1ac1d6060ee73edf83c8365fafb12df44deecc\/sqlx-macros-core\/src\/derives\/mod.rs#L13\" rel=\"noopener noreferrer nofollow\">\u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f<\/a> \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b <code>heck<\/code>.<\/p>\n<pre><code class=\"rust\">use heck::ToShoutyKebabCase;  #[test] fn test() {     assert_eq!(\"i am very angry!\".to_shouty_kebab_case(), \"I-AM-VERY-ANGRY\"); } <\/code><\/pre>\n<h3>num_cpus<\/h3>\n<p>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043a\u0440\u0435\u0439\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u044f\u0434\u0435\u0440 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430 \u0438\u043b\u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u044f \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0434\u043b\u044f <a href=\"https:\/\/github.com\/artslob\/ray-tracing-one-weekend\/blob\/f39a09a18a9c52543c8bf7ad928f8d32e530ba24\/src\/main.rs#L67\" rel=\"noopener noreferrer nofollow\">\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u0440\u0435\u0434\u043e\u0432<\/a> \u043f\u0440\u0438 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0438 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430 <a href=\"https:\/\/raytracing.github.io\/books\/RayTracingInOneWeekend.html\" rel=\"noopener noreferrer nofollow\">Ray Tracing in One Weekend<\/a>.<\/p>\n<h3>humantime<\/h3>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0442\u0435\u0440 \u0438 \u043f\u0430\u0440\u0441\u0435\u0440 \u0434\u043b\u044f <code>std::time::{Duration, SystemTime}<\/code> \u0432 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u043c \u0432\u0438\u0434\u0435. \u0422\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 <code>serde<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0440\u0435\u0439\u0442\u0430 <code>humantime-serde<\/code>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>Duration<\/code> \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\/\u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0432 \u0443\u0434\u043e\u0431\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u043c \u0432\u0438\u0434\u0435 \u0432\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0435\u0434\u0438\u043d\u0438\u0446 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432 \u0438\u043c\u0435\u043d\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439, \u0447\u0442\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u0442 \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438:<\/p>\n<pre><code class=\"yaml\"># for example instead of this: timeout_mins: 120 # you can write this: timeout: 2 hours <\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<pre><code class=\"rust\">use serde::{Deserialize, Serialize}; use std::time::Duration;  #[test] fn format() {     let duration = Duration::new(9420, 0);     let as_str = \"2h 37m\";     assert_eq!(humantime::format_duration(duration).to_string(), as_str);     assert_eq!(humantime::parse_duration(as_str), Ok(duration)); }  #[derive(Serialize, Deserialize)] struct Foo {     #[serde(with = \"humantime_serde\")]     timeout: Duration, }  #[test] fn serde() {     let input = r#\" { \"timeout\": \"3 days 1hour 12min 5s\" } \"#;     let foo: Foo = serde_json::from_str(input).unwrap();     assert_eq!(foo.timeout, Duration::new(263525, 0)); } <\/code><\/pre>\n<h3>overload<\/h3>\n<p>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441 \u0434\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432-\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432. \u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0445\u0438\u0442\u0440\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430: \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435 \u043c\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u0432\u0443\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a <code>a * b + 1<\/code>. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u043a\u0440\u0435\u0439\u0442 <code>derive_more<\/code>.<\/p>\n<pre><code class=\"rust\">use overload::overload; use std::ops;  #[derive(PartialEq, Debug)] struct A {     v: i32, }  #[derive(PartialEq, Debug)] struct B {     v: i32, }  \/\/ ? below generate operator for A and &amp;A values overload!((a: ?A) + (b: ?B) -> B { B { v: a.v * b.v + 1 } });  #[test] fn test() {     assert_eq!(&amp;A { v: 3 } + B { v: 5 }, B { v: 16 }); } <\/code><\/pre>\n<h3>enum-iterator<\/h3>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043f\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c \u0435\u043d\u0430\u043c\u0430 \u0438\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b.<\/p>\n<pre><code class=\"rust\">use enum_iterator::{all, first, last, next, Sequence}; use itertools::Itertools;  #[derive(Debug, PartialEq, Sequence)] enum Direction {     Left,     Middle,     Right, }  #[test] fn test_enum() {     use Direction::*;      assert_eq!(all::&lt;Direction>().collect_vec(), vec![Left, Middle, Right]);     assert_eq!(first::&lt;Direction>(), Some(Left));     assert_eq!(last::&lt;Direction>(), Some(Right));     assert_eq!(next(&amp;Middle), Some(Right)); }  #[derive(Debug, PartialEq, Sequence)] struct Foo {     a: bool,     b: u8, }  #[test] fn test_struct() {     let expected_number_of_elements = 512;     assert_eq!(         enum_iterator::cardinality::&lt;Foo>(),         expected_number_of_elements     );     assert_eq!(first::&lt;Foo>(), Some(Foo { a: false, b: 0 }));     assert_eq!(last::&lt;Foo>(), Some(Foo { a: true, b: 255 })); } <\/code><\/pre>\n<h3>cfg-if<\/h3>\n<p>\u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u0437\u0430\u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u043e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 <code>#[cfg]<\/code>, \u0432 \u0432\u0438\u0434\u0435 if-else \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"rust\">cfg_if::cfg_if! {     if #[cfg(unix)] {         fn foo() { \/* unix specific functionality *\/ }     } else if #[cfg(target_pointer_width = \"32\")] {         fn foo() { \/* non-unix, 32-bit functionality *\/ }     } else {         fn foo() { \/* fallback implementation *\/ }     } } <\/code><\/pre>\n<h3>arrayref<\/h3>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432 (<code>array<\/code>) \u0438\u0437 \u0441\u043b\u0430\u0439\u0441\u043e\u0432.<\/p>\n<pre><code class=\"rust\">let addr: &amp;[u8; 16] = ...; let mut segments = [0u16; 8]; \/\/ array-based API for i in 0 .. 8 {     let mut two_bytes = [addr[2*i], addr[2*i+1]];     segments[i] = read_u16_array(&amp;two_bytes); } \/\/ array-based API with arrayref for i in 0 .. 8 {     segments[i] = read_u16_array(array_ref![addr, 2*i, 2]); } <\/code><\/pre>\n<h3>educe<\/h3>\n<p>\u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0439, \u0433\u0438\u0431\u043a\u043e\u0439 \u0438 \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0438\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 <code>Debug<\/code>, <code>Eq<\/code>, <code>Ord<\/code>, <code>Deref<\/code> \u0438 \u0442\u0434. \u0413\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043f\u043e\u043b\u044f \u0438\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f trait bounds \u0438 \u0442\u0434.<\/p>\n<pre><code class=\"rust\">#[derive(educe::Educe)] \/\/ note `new` below: generate `new()` that calls Default #[educe(Default(new))] #[derive(Debug, PartialEq)] struct Struct {     #[educe(Default = 3)]     f1: u8,     #[educe(Default = true)]     f2: bool,     #[educe(Default = \"Hello\")]     f3: String, }  #[test] fn test() {     let expected = Struct {         f1: 3,         f2: true,         f3: String::from(\"Hello\"),     };     assert_eq!(Struct::default(), expected);     assert_eq!(Struct::new(), expected); } <\/code><\/pre>\n<h3>derivative<\/h3>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043a\u0430\u043a \u0438 <code>educe<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041d\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0431\u044b\u043b\u043e \u0432 \u044f\u043d\u0432\u0430\u0440\u0435 2021 \u0433\u043e\u0434\u0430.<\/p>\n<pre><code class=\"rust\">#[derive(Derivative)] #[derivative(PartialEq)] struct Foo {     foo: u8,     #[derivative(PartialEq=\"ignore\")]     bar: u8, }  assert!(Foo { foo: 0, bar: 42 } == Foo { foo: 0, bar: 7}); assert!(Foo { foo: 42, bar: 0 } != Foo { foo: 7, bar: 0}); <\/code><\/pre>\n<h3>chronoutil<\/h3>\n<p>\u0412 rust \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u0438\u043f <code>Duration<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u0438 \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434. \u0422\u0430\u043a <a href=\"https:\/\/docs.rs\/chrono\/latest\/chrono\/struct.Duration.html\" rel=\"noopener noreferrer nofollow\">chrono::Duration<\/a> \u0438\u043c\u0435\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u044b \u0441 \u0438\u043c\u0435\u043d\u0430\u043c\u0438 <code>weeks<\/code>, <code>days<\/code>, <code>hours<\/code>, \u043d\u043e \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 <code>month<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043d\u0435\u043b\u044c\u0437\u044f \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u044c \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u0442\u0443 \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u0443\u044e \u0434\u043b\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u0440\u0438\u0431\u0430\u0432\u0438\u0442\u044c \u043c\u0435\u0441\u044f\u0446 \u0438\u043b\u0438 \u0433\u043e\u0434, \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430.<\/p>\n<pre><code class=\"rust\">let delta = RelativeDuration::months(1) + RelativeDuration::days(1); assert_eq!(     NaiveDate::from_ymd(2021, 1, 28) + delta,     NaiveDate::from_ymd(2021, 3, 1) ); assert_eq!(     NaiveDate::from_ymd(2020, 1, 28) + delta,     NaiveDate::from_ymd(2020, 2, 29) ); <\/code><\/pre>\n<h3>References<\/h3>\n<ol>\n<li>\n<p><a href=\"https:\/\/www.reddit.com\/r\/rust\/comments\/uevmnx\/what_crates_would_you_consider_essential\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.reddit.com\/r\/rust\/comments\/uevmnx\/what_crates_would_you_consider_essential\/<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.reddit.com\/r\/rust\/comments\/ylp4nz\/what_crates_are_considered_as_defacto_standard\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.reddit.com\/r\/rust\/comments\/ylp4nz\/what_crates_are_considered_as_defacto_standard\/<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/blessed.rs\/crates\" rel=\"noopener noreferrer nofollow\">https:\/\/blessed.rs\/crates<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/lib.rs\/\" rel=\"noopener noreferrer nofollow\">https:\/\/lib.rs\/<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/crates.io\/crates?sort=recent-downloads\" rel=\"noopener noreferrer nofollow\">https:\/\/crates.io\/crates?sort=recent-downloads<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.reddit.com\/r\/rust\/comments\/nuq1ix\/whats_your_favourite_underrated_rust_crate_and_why\/\" rel=\"noopener noreferrer nofollow\">https:\/\/www.reddit.com\/r\/rust\/comments\/nuq1ix\/whats_your_favourite_underrated_rust_crate_and_why\/<\/a><\/p>\n<\/li>\n<\/ol>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/733622\/\"> https:\/\/habr.com\/ru\/articles\/733622\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e \u043a\u0440\u0435\u0439\u0442\u0430\u0445 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430 rust, \u043f\u0440\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0438\u0437 \u043d\u0438\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0438\u043b\u0438 \u0443\u043b\u0443\u0447\u0448\u0430\u044e\u0442 \u0435\u0433\u043e \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c. \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0438\u0448\u0443\u0442 \u043d\u0430 rust.<\/p>\n<p>\u0414\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u043a\u0440\u0435\u0439\u0442\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u043b\u0435\u0437\u043d\u044b \u0434\u0440\u0443\u0433\u0438\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c.<\/p>\n<p>\u041f\u043e\u0434 \u043a\u0440\u0435\u0439\u0442\u043e\u043c (crate) \u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043a\u0430\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0432 \u0432\u0430\u0448 \u043f\u0440\u043e\u0435\u043a\u0442.<\/p>\n<p>\u042f \u043d\u0435 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043b \u0432\u0441\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u0432 \u044d\u0442\u0443 \u0441\u0442\u0430\u0442\u044c\u044e, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0435\u0441\u043b\u0438 \u0432\u0430\u0441 \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b \u043a\u0440\u0435\u0439\u0442, \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043d\u0438\u043c \u043d\u0430 <a href=\"https:\/\/crates.io\" rel=\"noopener noreferrer nofollow\">crates.io<\/a> \u0438\u043b\u0438 <a href=\"https:\/\/docs.rs\" rel=\"noopener noreferrer nofollow\">docs.rs<\/a>.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u044f \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b \u0432 \u043f\u0440\u0438\u043c\u0435\u0440 \u0432\u0441\u0435\u043c\u0438 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043a\u0440\u0435\u0439\u0442\u044b \u043a\u0430\u043a <code>serde<\/code>, <code>anyhow<\/code>, <code>itertools<\/code> \u0438 \u0434\u0440\u0443\u0433\u0438\u0435.<\/p>\n<h3>Preface<\/h3>\n<p>\u0412\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043c\u043d\u043e\u0433\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u044b, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043d\u0430 rust, \u0438\u043c\u0435\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u0445 \u0438 \u0432\u0442\u043e\u0440\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439. \u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e, \u0432 \u044d\u0442\u043e\u043c \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u043f\u043b\u043e\u0445\u043e\u0433\u043e \u0438 \u0432\u043e\u0442 \u043f\u043e\u0447\u0435\u043c\u0443. Rust \u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u044b\u0441\u043e\u043a\u0438\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u0438 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 third-party \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e\u043c, \u0430 \u043d\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438 \u044f\u0437\u044b\u043a\u0430. \u0412 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f rust \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043f\u043e\u044f\u0432\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u0432\u0438\u0434\u0435 cargo, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u043b\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u044b\u043c. \u0412\u043c\u0435\u0441\u0442\u0435 \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043a\u0440\u0435\u0439\u0442\u0430\u043c rust \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0438\u043c\u0435\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 \u043b\u0435\u0433\u0430\u0441\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0434\u0430\u0451\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u0430 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0445\u043e\u0434\u0430\u043c\u0438 \u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0430 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440\u044b \u044f\u0437\u044b\u043a\u0430 \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u0432 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443. \u0412\u044b\u0448\u0435 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u0440\u0435\u0439\u0442\u044b \u0432 \u0441\u0442\u0438\u043b\u0435 Unix way, \u043a\u043e\u0433\u0434\u0430 \u043a\u0430\u0436\u0434\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u043d\u0443 \u0432\u0435\u0449\u044c \u0438 \u0434\u0435\u043b\u0430\u0435\u0442 \u0435\u0451 \u0445\u043e\u0440\u043e\u0448\u043e.<\/p>\n<p>\u041f\u043e\u0434\u0445\u043e\u0434 &#171;batteries included&#187;, \u043f\u0440\u0438\u043d\u044f\u0442\u044b\u0439 \u0432 python, \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0432 1990-\u0435 \u0433\u043e\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u041f\u041e \u043d\u0435 \u0431\u044b\u043b\u043e \u0442\u0430\u043a\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c. \u0421\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a <a href=\"https:\/\/peps.python.org\/pep-0594\/\" rel=\"noopener noreferrer nofollow\">\u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0430\u043c \u043f\u043e \u043e\u0447\u0438\u0441\u0442\u043a\u0435<\/a> \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 python.<\/p>\n<h3>tap<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438\u0437 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u044b \u0432 \u0441\u0443\u0444\u0444\u0438\u043a\u0441\u043d\u0443\u044e. \u0422\u0430\u043a\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u043a\u043e\u0434.<\/p>\n<p>\u041b\u0435\u0433\u0447\u0435 \u0432\u0441\u0435\u0433\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432:<\/p>\n<pre><code class=\"rust\">let val = last(   third(     second(first(original_value), another_arg)   ),   another_arg, ); <\/code><\/pre>\n<p>\u041c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043d\u0430 \u043a\u0430\u043a:<\/p>\n<pre><code class=\"rust\">let val = original_value   .pipe(first)   .pipe(|v| second(v, another_arg))   .pipe(third)   .pipe(|v| last(v, another_arg)); <\/code><\/pre>\n<p>\u0418\u043b\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043c\u0430\u0441\u0441\u0438\u0432 &#171;\u043d\u0430 \u043c\u0435\u0441\u0442\u0435&#187; \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <code>sort()<\/code>, \u0447\u0442\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e, \u0441\u0434\u0435\u043b\u0430\u0432 \u0435\u0451 \u0441\u043d\u043e\u0432\u0430 \u043d\u0435\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439:<\/p>\n<pre><code class=\"rust\">let mut collection = stream().collect::&lt;Vec&lt;_>>(); collection.sort(); \/\/ potential error site: inserting other mutations here let collection = collection; \/\/ now immutable <\/code><\/pre>\n<p>\u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 \u043c\u0435\u0442\u043e\u0434 <code>.tap_mut<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u0437\u0430\u043c\u044b\u043a\u0430\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043f\u043e \u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0435:<\/p>\n<pre><code class=\"rust\">let collection = stream.collect::&lt;Vec&lt;_>>().tap_mut(|v| v.sort()); <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e <code>collection<\/code> \u043b\u0438\u0448\u044c \u0440\u0430\u0437 \u0438 \u0441\u0434\u0435\u043b\u0430\u0432 \u0435\u0451 \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u043c\u0443\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u043e\u0439.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043d\u0435 \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u0432\u043b\u0438\u044f\u043d\u0438\u044f \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u043d\u0430 \u044d\u0442\u0430\u043f\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0437\u043e\u0432\u044b \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u0435\u043d \u043a\u0430\u043a \u0438 &#171;\u043d\u0430\u0438\u0432\u043d\u0430\u044f&#187; \u0432\u0435\u0440\u0441\u0438\u044f.<\/p>\n<p>\u041f\u043e \u043c\u043e\u0435\u043c\u0443 \u043c\u043d\u0435\u043d\u0438\u044e \u0432 \u043e\u0431\u043e\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u043a\u043e\u0434 \u0441\u0442\u0430\u043b \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0438\u0437\u0431\u0430\u0432\u0438\u043b\u0438\u0441\u044c \u043e\u0442 \u043b\u0438\u0448\u043d\u0438\u0445 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u0439 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0438 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u044b\u0437\u043e\u0432\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 chain-like \u0432\u0438\u0434, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u043e\u0434 \u043d\u0435 \u043f\u0440\u044b\u0433\u0430\u044f \u0433\u043b\u0430\u0437\u0430\u043c\u0438 \u043f\u043e \u0441\u0442\u0440\u043e\u0447\u043a\u0430\u043c.<\/p>\n<p>\u042d\u0442\u043e \u043d\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <code>tap_x_dbg<\/code> \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 debug \u0440\u0435\u0436\u0438\u043c\u0435 \u0438 \u0443\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432 relese \u0440\u0435\u0436\u0438\u043c\u0435. \u0422\u0430\u043a\u0436\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0441\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0442\u0438\u043f\u0430\u043c\u0438, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u043c\u0438 <code>Into<\/code> \u0442\u0440\u0435\u0439\u0442.<\/p>\n<p>\u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430.<\/p>\n<h3>strum<\/h3>\n<p>\u041a\u0440\u0435\u0439\u0442 \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 boilerplate \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0435\u043d\u0430\u043c\u0430\u043c\u0438 \u0432 \u0440\u0430\u0441\u0442\u0435. \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0437\u0430 \u0441\u0447\u0451\u0442 <code>derive<\/code> \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430:<\/p>\n<ol>\n<li>\n<p><code>strum::Display<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>std::fmt::Display<\/code> \u0434\u043b\u044f \u0435\u043d\u0430\u043c\u0430 \u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043c\u0435\u0442\u043e\u0434 <code>to_string() -> String<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>strum::AsRefStr<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>AsRef&lt;&amp;static str><\/code>. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u043b\u043b\u043e\u043a\u0430\u0446\u0438\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 \u043a\u0430\u043a \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>to_string()<\/code>.<\/p>\n<\/li>\n<li>\n<p><code>strum::IntoStaticStr<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>From&lt;MyEnum> for &amp;'static str<\/code>. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u043c\u0443 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0443.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumString<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 <code>std::str::FromStr<\/code> \u0438 <code>std::convert::TryFrom&lt;&amp;str><\/code>, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u0435\u043d\u0430\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumCount<\/code> &#8212; \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443 <code>COUNT: usize<\/code>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0435\u043d\u0430\u043c\u0430.<\/p>\n<\/li>\n<li>\n<p><code>strum::EnumIter<\/code> &#8212; \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440 \u043f\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c \u0435\u043d\u0430\u043c\u0430. \u0414\u0430\u043d\u043d\u044b\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0431\u0443\u0434\u0443\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b \u0432 <code>Default::default()<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418 \u0434\u0430\u0436\u0435 \u0431\u043e\u043b\u044c\u0448\u0435. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0437\u0430\u0433\u043b\u044f\u043d\u0443\u0442\u044c \u0432 <a href=\"https:\/\/docs.rs\/strum\/latest\" rel=\"noopener noreferrer nofollow\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430<\/a>.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0432\u044b\u0448\u0435:<\/p>\n<pre><code class=\"rust\">#[derive(     Debug,     PartialEq,     strum::Display,     strum::IntoStaticStr,     strum::AsRefStr,     strum::EnumString,     strum::EnumCount,     strum::EnumIter, )] enum Color {     Red,     Blue(usize),     Green { range: usize }, }  \/\/ convertions to String and &amp;'static str assert_eq!(Color::Blue(2).to_string(), \"Blue\"); assert_eq!(Color::Green { range: 5 }.as_ref(), \"Green\"); assert_eq!(&lt;&amp;str>::from(Color::Red), \"Red\");  assert_eq!(Color::Red, Color::from_str(\"Red\").unwrap()); assert_eq!(Color::COUNT, 3); assert_eq!(     Color::iter().collect::&lt;Vec&lt;_>>(),     vec![Color::Red, Color::Blue(0), Color::Green { range: 0 }] ); <\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0440\u0430\u0437\u043d\u044b\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u043c\u0435\u043d\u044f\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u0430\u043d\u0430\u043c\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u043c <code>#[strum(serialize = \"redred\")]<\/code>.<\/p>\n<h3>derive_more<\/h3>\n<p>\u0412 \u0440\u0430\u0441\u0442\u0435 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u0435\u043d \u043f\u0430\u0442\u0442\u0435\u0440 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c NewType. \u0421\u0443\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 &#171;\u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0438&#187; \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u0447\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0432 \u043d\u0430\u0448\u0443 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443:<\/p>\n<pre><code class=\"rust\">pub struct NonEmptyVec(Vec&lt;i32>); <\/code><\/pre>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432. \u0414\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e-\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u0441\u0435\u0433\u0434\u0430 \u043d\u0435 \u043f\u0443\u0441\u0442\u043e\u0439:<\/p>\n<pre><code class=\"rust\">impl NonEmptyVec {     pub fn new(numbers: Vec&lt;i32>) -> Result&lt;Self> {         if numbers.is_empty() {             bail!(\"expected non empty vector of integers\")         } else {             Ok(Self(numbers))         }     } } <\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0438\u043d\u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u041c\u0438\u043d\u0443\u0441\u043e\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e, \u0447\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430-\u0432\u0440\u0430\u043f\u043f\u0435\u0440 <code>NonEmptyVec<\/code> \u043d\u0435 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0442\u0438\u043f\u0430.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0430 \u0432\u0445\u043e\u0434 <code>IntoIterator<\/code>? \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u043d\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"rust\">fn collector(iter: impl IntoIterator&lt;Item = i32>) -> Vec&lt;i32> {     iter.into_iter().collect() }  #[test] fn non_emtpy_vec() -> Result&lt;()> {     let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;     assert_eq!(collector(non_empty), vec![1, 2, 3]);     Ok(()) } <\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:<\/p>\n<pre><code class=\"rust\">impl IntoIterator for NonEmptyVec {     type Item = &lt;Vec&lt;i32> as IntoIterator>::Item;     type IntoIter = &lt;Vec&lt;i32> as IntoIterator>::IntoIter;      fn into_iter(self) -> Self::IntoIter {         &lt;Vec&lt;i32> as IntoIterator>::into_iter(self.0)     } } <\/code><\/pre>\n<p>\u041d\u043e \u043f\u043e \u0441\u0443\u0442\u0438 \u044d\u0442\u043e boilerplate \u043a\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u0430 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u0442\u0438\u043f\u0430. \u0418\u0437\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u043e\u0442 \u0442\u0430\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442. \u041f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 derive \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b-\u0432\u0440\u0430\u043f\u043f\u0435\u0440\u0430:<\/p>\n<pre><code class=\"rust\">#[derive(derive_more::AsRef, derive_more::Deref, derive_more::IntoIterator, derive_more::Index)] pub struct NonEmptyVec(Vec&lt;i32>); <\/code><\/pre>\n<p>\u0418 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442:<\/p>\n<pre><code class=\"rust\">fn collector(iter: impl IntoIterator&lt;Item = i32>) -> Vec&lt;i32> {     iter.into_iter().collect() }  #[test] fn non_emtpy_vec() -> Result&lt;()> {     assert!(NonEmptyVec::new(vec![]).is_err());      let non_empty = NonEmptyVec::new(vec![1, 2, 3])?;     assert_eq!(non_empty.as_ref(), &amp;[1, 2, 3]);     assert_eq!(non_empty.deref(), &amp;[1, 2, 3]);     assert_eq!(non_empty[1], 2);     assert_eq!(collector(non_empty), vec![1, 2, 3]);     Ok(()) } <\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0440\u0430\u0437\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0442\u0440\u0435\u0439\u0442\u043e\u0432.<\/p>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0442\u0440\u0435\u0439\u0442\u043e\u0432 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0430\u0446\u0438\u0438 (<code>From<\/code>, <code>IntoIterator<\/code>, <code>AsRef<\/code>, etc), \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (<code>Display<\/code>-like), \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 (<code>Add<\/code>, <code>Index<\/code>, etc), \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (<code>Constructor<\/code>, <code>Unwap<\/code>, etc).<\/p>\n<h3>derive_builder<\/h3>\n<p>\u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u0432 \u0440\u0430\u0441\u0442\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f builder [<a href=\"https:\/\/doc.rust-lang.org\/1.0.0\/style\/ownership\/builders.html\" rel=\"noopener noreferrer nofollow\">1<\/a>, <a href=\"https:\/\/rust-unofficial.github.io\/patterns\/patterns\/creational\/builder.html\" rel=\"noopener noreferrer nofollow\">2<\/a>]. \u0414\u0430\u043d\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0443\u0434\u043e\u0431\u0435\u043d, \u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u044e\u0449\u0438\u0445 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0445 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>Calculation<\/code> &#8212; \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 &#8212; \u0430 \u0437\u0430\u0442\u0435\u043c \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 \u044e\u043d\u0438\u0442 \u0442\u0435\u0441\u0442\u0435:<\/p>\n<pre><code class=\"rust\">#[derive(Debug, Eq, PartialEq)] struct Calculation {     a: Option&lt;i32>,     b: Option&lt;i32>,     c: Option&lt;i32>,     d: Option&lt;i32>,     \/\/ ... can be more optional fields }  fn qwe() -> Calculation {     \/\/ does complex calculation     Calculation {         a: Some(1),         b: None,         c: None,         d: None,     } }  fn asd() -> Calculation {     \/\/ does complex calculation     Calculation {         a: Some(6),         b: None,         c: None,         d: Some(7),     } }  fn zxc() -> Calculation {     \/\/ does complex calculation     Calculation {         a: None,         b: Some(2),         c: Some(3),         d: None,     } }  #[test] fn test() -> Result&lt;()> {     assert_eq!(         qwe(),         Calculation {             a: Some(1),             b: None,             c: None,             d: None,         }     );     assert_eq!(         asd(),         Calculation {             a: Some(6),             b: None,             c: None,             d: Some(7),         }     );     assert_eq!(         zxc(),         Calculation {             a: None,             b: Some(2),             c: Some(3),             d: None,         }     );      Ok(()) } <\/code><\/pre>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <code>derive_builder<\/code>:<\/p>\n<pre><code class=\"rust\">#[derive(Debug, Eq, PartialEq, Default, derive_builder::Builder)] \/\/ setters calls can be chained, each call clones builder #[builder(pattern = \"immutable\")] \/\/ if field not set then it would be default (None in our case) #[builder(default)] \/\/ setter method accepts T as argument and field<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-412273","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=412273"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412273\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=412273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=412273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=412273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}